3
3
module ActiveSupport
4
4
# +ActiveSupport::ErrorReporter+ is a common interface for error reporting services.
5
5
#
6
- # To rescue and report any unhandled error, you can use the + handle+ method:
6
+ # To rescue and report any unhandled error, you can use the # handle method:
7
7
#
8
8
# Rails.error.handle do
9
9
# do_something!
10
10
# end
11
11
#
12
12
# If an error is raised, it will be reported and swallowed.
13
13
#
14
- # Alternatively if you want to report the error but not swallow it, you can use + record+
14
+ # Alternatively, if you want to report the error but not swallow it, you can use # record:
15
15
#
16
16
# Rails.error.record do
17
17
# do_something!
18
18
# end
19
19
#
20
- # Both methods can be restricted to only handle a specific exception class
20
+ # Both methods can be restricted to handle only a specific error class:
21
21
#
22
22
# maybe_tags = Rails.error.handle(Redis::BaseError) { redis.get("tags") }
23
23
#
24
- # You can also pass some extra context information that may be used by the error subscribers:
25
- #
26
- # Rails.error.handle(context: { section: "admin" }) do
27
- # # ...
28
- # end
29
- #
30
- # Additionally a +severity+ can be passed along to communicate how important the error report is.
31
- # +severity+ can be one of +:error+, +:warning+, or +:info+. Handled errors default to the +:warning+
32
- # severity, and unhandled ones to +:error+.
33
- #
34
- # A +source+ can also be specified, describing where the error originates from. Error subscribers can
35
- # use this to ignore certain errors. For instance, ActiveSupport may report internal errors
36
- # such as cache failures with a source like "redis_cache_store.active_support".
37
- # The default +source+ is "application".
38
- #
39
- # Both +handle+ and +record+ pass through the return value from the block. In the case of +handle+
40
- # rescuing an error, a fallback can be provided. The fallback must be a callable whose result will
41
- # be returned when the block raises and is handled:
42
- #
43
- # user = Rails.error.handle(fallback: -> { User.anonymous }) do
44
- # User.find_by(params)
45
- # end
46
24
class ErrorReporter
47
25
SEVERITIES = %i( error warning info )
48
26
DEFAULT_SOURCE = "application"
@@ -54,26 +32,78 @@ def initialize(*subscribers, logger: nil)
54
32
@logger = logger
55
33
end
56
34
57
- # Report any unhandled exception, and swallow it.
35
+ # Evaluates the given block, reporting and swallowing any unhandled error.
36
+ # If no error is raised, returns the return value of the block. Otherwise,
37
+ # returns the result of +fallback.call+, or +nil+ if +fallback+ is not
38
+ # specified.
58
39
#
40
+ # # Will report a TypeError to all subscribers and return nil.
59
41
# Rails.error.handle do
60
42
# 1 + '1'
61
43
# end
62
44
#
45
+ # Can be restricted to handle only a specific error class:
46
+ #
47
+ # maybe_tags = Rails.error.handle(Redis::BaseError) { redis.get("tags") }
48
+ #
49
+ # ==== Options
50
+ #
51
+ # * +:severity+ - This value is passed along to subscribers to indicate how
52
+ # important the error report is. Can be +:error+, +:warning+, or +:info+.
53
+ # Defaults to +:warning+.
54
+ #
55
+ # * +:context+ - Extra information that is passed along to subscribers. For
56
+ # example:
57
+ #
58
+ # Rails.error.handle(context: { section: "admin" }) do
59
+ # # ...
60
+ # end
61
+ #
62
+ # * +:fallback+ - A callable that provides +handle+'s return value when an
63
+ # unhandled error is raised. For example:
64
+ #
65
+ # user = Rails.error.handle(fallback: -> { User.anonymous }) do
66
+ # User.find_by(params)
67
+ # end
68
+ #
69
+ # * +:source+ - This value is passed along to subscribers to indicate the
70
+ # source of the error. Subscribers can use this value to ignore certain
71
+ # errors. Defaults to <tt>"application"</tt>.
63
72
def handle ( error_class = StandardError , severity : :warning , context : { } , fallback : nil , source : DEFAULT_SOURCE )
64
73
yield
65
74
rescue error_class => error
66
75
report ( error , handled : true , severity : severity , context : context , source : source )
67
76
fallback . call if fallback
68
77
end
69
78
70
- # Report any unhandled exception, but do not swallow it.
79
+ # Evaluates the given block, reporting and re-raising any unhandled error.
80
+ # If no error is raised, returns the return value of the block.
71
81
#
82
+ # # Will report a TypeError to all subscribers and re-raise it.
72
83
# Rails.error.record do
73
- # # Will report the TypeError to all subscribers and then raise it.
74
84
# 1 + '1'
75
85
# end
76
86
#
87
+ # Can be restricted to handle only a specific error class:
88
+ #
89
+ # tags = Rails.error.record(Redis::BaseError) { redis.get("tags") }
90
+ #
91
+ # ==== Options
92
+ #
93
+ # * +:severity+ - This value is passed along to subscribers to indicate how
94
+ # important the error report is. Can be +:error+, +:warning+, or +:info+.
95
+ # Defaults to +:error+.
96
+ #
97
+ # * +:context+ - Extra information that is passed along to subscribers. For
98
+ # example:
99
+ #
100
+ # Rails.error.record(context: { section: "admin" }) do
101
+ # # ...
102
+ # end
103
+ #
104
+ # * +:source+ - This value is passed along to subscribers to indicate the
105
+ # source of the error. Subscribers can use this value to ignore certain
106
+ # errors. Defaults to <tt>"application"</tt>.
77
107
def record ( error_class = StandardError , severity : :error , context : { } , source : DEFAULT_SOURCE )
78
108
yield
79
109
rescue error_class => error
@@ -85,7 +115,7 @@ def record(error_class = StandardError, severity: :error, context: {}, source: D
85
115
#
86
116
# report(Exception, handled: Boolean, severity: (:error OR :warning OR :info), context: Hash, source: String)
87
117
#
88
- # The +report+ method + should+ never raise an error.
118
+ # The +report+ method <b> should never</b> raise an error.
89
119
def subscribe ( subscriber )
90
120
unless subscriber . respond_to? ( :report )
91
121
raise ArgumentError , "Error subscribers must respond to #report"
@@ -108,19 +138,21 @@ def disable(subscriber)
108
138
end
109
139
end
110
140
111
- # Update the execution context that is accessible to error subscribers
141
+ # Update the execution context that is accessible to error subscribers. Any
142
+ # context passed to #handle, #record, or #report will be merged with the
143
+ # context set here.
112
144
#
113
145
# Rails.error.set_context(section: "checkout", user_id: @user.id)
114
146
#
115
- # Any context passed to +handle+, +record+, or +report+ will be merged with the context set here.
116
- # See +ActiveSupport::ExecutionContext.set+
117
147
def set_context ( ...)
118
148
ActiveSupport ::ExecutionContext . set ( ...)
119
149
end
120
150
121
- # When the block based +handle+ and +record+ methods are not suitable, you can directly use +report+
151
+ # Report an error directly to subscribers. You can use this method when the
152
+ # block-based #handle and #record methods are not suitable.
122
153
#
123
154
# Rails.error.report(error)
155
+ #
124
156
def report ( error , handled : true , severity : handled ? :warning : :error , context : { } , source : DEFAULT_SOURCE )
125
157
unless SEVERITIES . include? ( severity )
126
158
raise ArgumentError , "severity must be one of #{ SEVERITIES . map ( &:inspect ) . join ( ", " ) } , got: #{ severity . inspect } "
0 commit comments