error_report.rb
3.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
require 'hoptoad_notifier'
##
# Processes a new error report.
#
# Accepts a hash with the following attributes:
#
# * <tt>:error_class</tt> - the class of error
# * <tt>:message</tt> - the error message
# * <tt>:backtrace</tt> - an array of stack trace lines
#
# * <tt>:request</tt> - a hash of values describing the request
# * <tt>:server_environment</tt> - a hash of values describing the server environment
#
# * <tt>:notifier</tt> - information to identify the source of the error report
#
class ErrorReport
attr_reader :api_key
attr_reader :error_class
attr_reader :framework
attr_reader :message
attr_reader :notice
attr_reader :notifier
attr_reader :problem
attr_reader :request
attr_reader :server_environment
attr_reader :user_attributes
cattr_accessor :fingerprint_strategy do
Fingerprint::Sha1
end
def initialize(xml_or_attributes)
@attributes = xml_or_attributes
@attributes = Hoptoad.parse_xml!(@attributes) if @attributes.is_a? String
@attributes = @attributes.with_indifferent_access
@attributes.each { |k, v| instance_variable_set(:"@#{k}", v) }
end
def rails_env
rails_env = server_environment['environment-name']
rails_env = 'development' if rails_env.blank?
rails_env
end
def app
@app ||= App.where(api_key: api_key).first
end
def backtrace
@normalized_backtrace ||= Backtrace.find_or_create(@backtrace)
end
def generate_notice!
return unless valid?
return @notice if @notice
make_notice
error.notices << @notice
cache_attributes_on_problem
email_notification
services_notification
@notice
end
def make_notice
@notice = Notice.new(
message: message,
error_class: error_class,
backtrace: backtrace,
request: request,
server_environment: server_environment,
notifier: notifier,
user_attributes: user_attributes,
framework: framework
)
end
# Update problem cache with information about this notice
def cache_attributes_on_problem
@problem = Problem.cache_notice(@error.problem_id, @notice)
# cache_notice returns the old problem, so the count is one higher
@similar_count = @problem.notices_count + 1
end
# Send email notification if needed
def email_notification
return false unless app.emailable?
return false unless app.email_at_notices.include?(@similar_count)
Mailer.err_notification(@notice).deliver
rescue => e
HoptoadNotifier.notify(e)
end
def should_notify?
app.notification_service.notify_at_notices.include?(0) ||
app.notification_service.notify_at_notices.include?(@similar_count)
end
# Launch all notification define on the app associate to this notice
def services_notification
return true unless app.notification_service_configured? and should_notify?
app.notification_service.create_notification(problem)
rescue => e
HoptoadNotifier.notify(e)
end
##
# Error associate to this error_report
#
# Can already exist or not
#
# @return [ Error ]
def error
@error ||= app.find_or_create_err!(
error_class: error_class,
environment: rails_env,
fingerprint: fingerprint
)
end
def valid?
app.present?
end
def should_keep?
app_version = server_environment['app-version'] || ''
current_version = app.current_app_version
return true unless current_version.present?
return false if app_version.length <= 0
Gem::Version.new(app_version) >= Gem::Version.new(current_version)
end
private
def fingerprint
@fingerprint ||= fingerprint_strategy.generate(notice, api_key)
end
end