Module: ExceptionHandling
- Defined in:
- lib/exception_handling.rb,
lib/exception_handling/sensu.rb,
lib/exception_handling/mailer.rb,
lib/exception_handling/methods.rb,
lib/exception_handling/testing.rb,
lib/exception_handling/version.rb,
lib/exception_handling/exception_catalog.rb,
lib/exception_handling/exception_description.rb
Overview
some useful test objects
Defined Under Namespace
Modules: Methods, Sensu, Testing Classes: ClientLoggingError, ExceptionCatalog, ExceptionDescription, Mailer, MailerTimeout, Warning
Constant Summary collapse
- SUMMARY_THRESHOLD =
5- SUMMARY_PERIOD =
1.hour
60*60
- SECTIONS =
[:request, :session, :environment, :backtrace, :event_response]
- ENVIRONMENT_WHITELIST =
[ /^HTTP_/, /^QUERY_/, /^REQUEST_/, /^SERVER_/ ]
- ENVIRONMENT_OMIT =
( <<EOF CONTENT_TYPE: application/x-www-form-urlencoded GATEWAY_INTERFACE: CGI/1.2 HTTP_ACCEPT: */* HTTP_ACCEPT: */*, text/javascript, text/html, application/xml, text/xml, */* HTTP_ACCEPT_CHARSET: ISO-8859-1,utf-8;q=0.7,*;q=0.7 HTTP_ACCEPT_ENCODING: gzip, deflate HTTP_ACCEPT_ENCODING: gzip,deflate HTTP_ACCEPT_LANGUAGE: en-us HTTP_CACHE_CONTROL: no-cache HTTP_CONNECTION: Keep-Alive HTTP_HOST: www.invoca.com HTTP_MAX_FORWARDS: 10 HTTP_UA_CPU: x86 HTTP_VERSION: HTTP/1.1 HTTP_X_FORWARDED_HOST: www.invoca.com HTTP_X_FORWARDED_SERVER: www2.invoca.com HTTP_X_REQUESTED_WITH: XMLHttpRequest LANG: LANG: PATH: /sbin:/usr/sbin:/bin:/usr/bin PWD: / RAILS_ENV: production RAW_POST_DATA: id=500 REMOTE_ADDR: 10.251.34.225 SCRIPT_NAME: / SERVER_NAME: www.invoca.com SERVER_PORT: 80 SERVER_PROTOCOL: HTTP/1.1 SERVER_SOFTWARE: Mongrel 1.1.4 SHLVL: 1 TERM: linux TERM: xterm-color _: /usr/bin/mongrel_cluster_ctl EOF ).split("\n")
- AUTHENTICATION_HEADERS =
['HTTP_AUTHORIZATION','X-HTTP_AUTHORIZATION','X_HTTP_AUTHORIZATION','REDIRECT_X_HTTP_AUTHORIZATION']
- VERSION =
"1.1.0"
Class Attribute Summary collapse
-
.current_controller ⇒ Object
internal settings (don’t set directly).
-
.custom_data_hook ⇒ Object
Returns the value of attribute custom_data_hook.
-
.email_environment ⇒ Object
Returns the value of attribute email_environment.
-
.escalation_recipients ⇒ Object
optional settings.
-
.eventmachine_safe ⇒ Object
Returns the value of attribute eventmachine_safe.
-
.eventmachine_synchrony ⇒ Object
Returns the value of attribute eventmachine_synchrony.
-
.exception_recipients ⇒ Object
Returns the value of attribute exception_recipients.
-
.filter_list_filename ⇒ Object
Returns the value of attribute filter_list_filename.
-
.last_exception_timestamp ⇒ Object
Returns the value of attribute last_exception_timestamp.
-
.logger ⇒ Object
Returns the value of attribute logger.
-
.mailer_send_enabled ⇒ Object
Returns the value of attribute mailer_send_enabled.
-
.periodic_exception_intervals ⇒ Object
Returns the value of attribute periodic_exception_intervals.
-
.post_log_error_hook ⇒ Object
Returns the value of attribute post_log_error_hook.
-
.sender_address ⇒ Object
Returns the value of attribute sender_address.
-
.sensu_host ⇒ Object
Returns the value of attribute sensu_host.
-
.sensu_port ⇒ Object
Returns the value of attribute sensu_port.
-
.sensu_prefix ⇒ Object
Returns the value of attribute sensu_prefix.
-
.server_name ⇒ Object
required settings.
-
.stub_handler ⇒ Object
Returns the value of attribute stub_handler.
Class Method Summary collapse
- .alert_warning(exception_or_string, alert_name, exception_context) ⇒ Object
- .enhance_exception_data(data) ⇒ Object
- .ensure_alert(alert_name, exception_context) ⇒ Object
- .ensure_completely_safe(exception_context = "") ⇒ Object
- .ensure_escalation(email_subject) ⇒ Object
- .ensure_safe(exception_context = "") ⇒ Object
- .escalate_error(exception_or_string, email_subject) ⇒ Object
- .escalate_warning(message, email_subject) ⇒ Object
-
.extract_and_merge_controller_data(controller, data) ⇒ Object
Pull certain fields out of the controller and add to the data hash.
- .log_debug(message) ⇒ Object
-
.log_error(exception_or_string, exception_context = '', controller = nil, treat_as_local = false) ⇒ Object
Normal Operation: Called directly by our code, usually from rescue blocks.
-
.log_error_rack(exception, env, rack_filter) ⇒ Object
Gets called by Rack Middleware: DebugExceptions or ShowExceptions it does 2 things: log the error email the error.
- .log_info(message) ⇒ Object
- .log_periodically(exception_key, interval, message) ⇒ Object
- .log_warning(message) ⇒ Object
- .set_log_error_timestamp ⇒ Object
- .should_send_email? ⇒ Boolean
- .trace_timing(description) ⇒ Object
-
.write_exception_to_log(ex, exception_context, timestamp) ⇒ Object
Write an exception out to the log file using our own custom format.
Class Attribute Details
.current_controller ⇒ Object
internal settings (don’t set directly)
148 149 150 |
# File 'lib/exception_handling.rb', line 148 def current_controller @current_controller end |
.custom_data_hook ⇒ Object
Returns the value of attribute custom_data_hook.
109 110 111 |
# File 'lib/exception_handling.rb', line 109 def custom_data_hook @custom_data_hook end |
.email_environment ⇒ Object
Returns the value of attribute email_environment.
104 105 106 |
# File 'lib/exception_handling.rb', line 104 def email_environment @email_environment end |
.escalation_recipients ⇒ Object
optional settings
103 104 105 |
# File 'lib/exception_handling.rb', line 103 def escalation_recipients @escalation_recipients end |
.eventmachine_safe ⇒ Object
Returns the value of attribute eventmachine_safe.
107 108 109 |
# File 'lib/exception_handling.rb', line 107 def eventmachine_safe @eventmachine_safe end |
.eventmachine_synchrony ⇒ Object
Returns the value of attribute eventmachine_synchrony.
108 109 110 |
# File 'lib/exception_handling.rb', line 108 def eventmachine_synchrony @eventmachine_synchrony end |
.exception_recipients ⇒ Object
Returns the value of attribute exception_recipients.
81 82 83 |
# File 'lib/exception_handling.rb', line 81 def exception_recipients @exception_recipients end |
.filter_list_filename ⇒ Object
Returns the value of attribute filter_list_filename.
105 106 107 |
# File 'lib/exception_handling.rb', line 105 def filter_list_filename @filter_list_filename end |
.last_exception_timestamp ⇒ Object
Returns the value of attribute last_exception_timestamp.
149 150 151 |
# File 'lib/exception_handling.rb', line 149 def @last_exception_timestamp end |
.logger ⇒ Object
Returns the value of attribute logger.
82 83 84 |
# File 'lib/exception_handling.rb', line 82 def logger @logger end |
.mailer_send_enabled ⇒ Object
Returns the value of attribute mailer_send_enabled.
106 107 108 |
# File 'lib/exception_handling.rb', line 106 def mailer_send_enabled @mailer_send_enabled end |
.periodic_exception_intervals ⇒ Object
Returns the value of attribute periodic_exception_intervals.
150 151 152 |
# File 'lib/exception_handling.rb', line 150 def periodic_exception_intervals @periodic_exception_intervals end |
.post_log_error_hook ⇒ Object
Returns the value of attribute post_log_error_hook.
110 111 112 |
# File 'lib/exception_handling.rb', line 110 def post_log_error_hook @post_log_error_hook end |
.sender_address ⇒ Object
Returns the value of attribute sender_address.
80 81 82 |
# File 'lib/exception_handling.rb', line 80 def sender_address @sender_address end |
.sensu_host ⇒ Object
Returns the value of attribute sensu_host.
112 113 114 |
# File 'lib/exception_handling.rb', line 112 def sensu_host @sensu_host end |
.sensu_port ⇒ Object
Returns the value of attribute sensu_port.
113 114 115 |
# File 'lib/exception_handling.rb', line 113 def sensu_port @sensu_port end |
.sensu_prefix ⇒ Object
Returns the value of attribute sensu_prefix.
114 115 116 |
# File 'lib/exception_handling.rb', line 114 def sensu_prefix @sensu_prefix end |
.server_name ⇒ Object
required settings
79 80 81 |
# File 'lib/exception_handling.rb', line 79 def server_name @server_name end |
.stub_handler ⇒ Object
Returns the value of attribute stub_handler.
111 112 113 |
# File 'lib/exception_handling.rb', line 111 def stub_handler @stub_handler end |
Class Method Details
.alert_warning(exception_or_string, alert_name, exception_context) ⇒ Object
312 313 314 315 316 317 318 319 320 |
# File 'lib/exception_handling.rb', line 312 def alert_warning(exception_or_string, alert_name, exception_context) ex = make_exception(exception_or_string) log_error(ex, exception_context) begin ExceptionHandling::Sensu.generate_event(alert_name, exception_context.to_s + "\n" + ex..to_s) rescue => send_ex log_error(send_ex, 'ExceptionHandling.alert_warning') end end |
.enhance_exception_data(data) ⇒ Object
357 358 359 360 361 362 363 364 365 |
# File 'lib/exception_handling.rb', line 357 def enhance_exception_data(data) return if ! ExceptionHandling.custom_data_hook begin ExceptionHandling.custom_data_hook.call(data) rescue Exception => ex # can't call log_error here or we will blow the call stack log_info( "Unable to execute custom custom_data_hook callback. #{ex.} #{ex.backtrace.each {|l| "#{l}\n"}}" ) end end |
.ensure_alert(alert_name, exception_context) ⇒ Object
322 323 324 325 326 327 328 329 |
# File 'lib/exception_handling.rb', line 322 def ensure_alert(alert_name, exception_context) begin yield rescue => ex alert_warning(ex, alert_name, exception_context) nil end end |
.ensure_completely_safe(exception_context = "") ⇒ Object
283 284 285 286 287 288 289 |
# File 'lib/exception_handling.rb', line 283 def ensure_completely_safe( exception_context = "" ) yield rescue SystemExit, SystemStackError, NoMemoryError, SecurityError, SignalException raise rescue Exception => ex log_error ex, exception_context end |
.ensure_escalation(email_subject) ⇒ Object
303 304 305 306 307 308 309 310 |
# File 'lib/exception_handling.rb', line 303 def ensure_escalation(email_subject) begin yield rescue => ex escalate_error(ex, email_subject) nil end end |
.ensure_safe(exception_context = "") ⇒ Object
276 277 278 279 280 281 |
# File 'lib/exception_handling.rb', line 276 def ensure_safe( exception_context = "" ) yield rescue => ex log_error ex, exception_context return nil end |
.escalate_error(exception_or_string, email_subject) ⇒ Object
291 292 293 294 295 |
# File 'lib/exception_handling.rb', line 291 def escalate_error(exception_or_string, email_subject) ex = make_exception(exception_or_string) log_error(ex) escalate(email_subject, ex, ExceptionHandling.) end |
.escalate_warning(message, email_subject) ⇒ Object
297 298 299 300 301 |
# File 'lib/exception_handling.rb', line 297 def escalate_warning(, email_subject) ex = Warning.new() log_error(ex) escalate(email_subject, ex, ExceptionHandling.) end |
.extract_and_merge_controller_data(controller, data) ⇒ Object
Pull certain fields out of the controller and add to the data hash.
249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/exception_handling.rb', line 249 def extract_and_merge_controller_data(controller, data) data[:request] = { :params => controller.request.parameters.to_hash, :rails_root => defined?(Rails) ? Rails.root : "Rails.root not defined. Is this a test environment?", :url => controller.complete_request_uri } data[:environment].merge!(controller.request.env.to_hash) controller.session[:fault_in_session] data[:session] = { :key => controller.request.[:id], :data => controller.session.dup } end |
.log_debug(message) ⇒ Object
272 273 274 |
# File 'lib/exception_handling.rb', line 272 def log_debug( ) ExceptionHandling.logger.debug( ) end |
.log_error(exception_or_string, exception_context = '', controller = nil, treat_as_local = false) ⇒ Object
Normal Operation:
Called directly by our code, usually from rescue blocks.
Does two things: write to log file and send an email
Functional Test Operation:
Calls into handle_stub_log_error and returns. no log file. no email.
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/exception_handling.rb', line 193 def log_error(exception_or_string, exception_context = '', controller = nil, treat_as_local = false) begin ex = make_exception(exception_or_string) = data = exception_to_data(ex, exception_context, ) if stub_handler return stub_handler.handle_stub_log_error(data) end write_exception_to_log(ex, exception_context, ) if treat_as_local return end if should_send_email? controller ||= current_controller if block_given? # the expectation is that if the caller passed a block then they will be # doing their own merge of hash values into data begin yield data rescue Exception => ex data.merge!(:environment => "Exception in yield: #{ex.class}:#{ex}") end elsif controller # most of the time though, this method will not get passed a block # and additional hash data is extracted from the controller extract_and_merge_controller_data(controller, data) end log_error_email(data, ex) end rescue LogErrorStub::UnexpectedExceptionLogged, LogErrorStub::ExpectedExceptionNotLogged raise rescue Exception => ex $stderr.puts("ExceptionHandling.log_error rescued exception while logging #{exception_context}: #{exception_or_string}:\n#{ex.class}: #{ex}\n#{ex.backtrace.join("\n")}") write_exception_to_log(ex, "ExceptionHandling.log_error rescued exception while logging #{exception_context}: #{exception_or_string}", ) end end |
.log_error_rack(exception, env, rack_filter) ⇒ Object
Gets called by Rack Middleware: DebugExceptions or ShowExceptions it does 2 things:
log the error
email the error
but not during functional tests, when rack middleware is not used
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/exception_handling.rb', line 160 def log_error_rack(exception, env, rack_filter) = exception_data = exception_to_data(exception, env, ) if stub_handler return stub_handler.handle_stub_log_error(exception_data) end # TODO: add a more interesting custom description, like: # custom_description = ": caught and processed by Rack middleware filter #{rack_filter}" # which would be nice, but would also require changing quite a few tests custom_description = "" write_exception_to_log(exception, custom_description, ) if should_send_email? controller = env['action_controller.instance'] # controller may not exist in some cases (like most 404 errors) if controller extract_and_merge_controller_data(controller, exception_data) controller.session["last_exception_timestamp"] = ExceptionHandling. end log_error_email(exception_data, exception) end end |
.log_info(message) ⇒ Object
268 269 270 |
# File 'lib/exception_handling.rb', line 268 def log_info( ) ExceptionHandling.logger.info( ) end |
.log_periodically(exception_key, interval, message) ⇒ Object
348 349 350 351 352 353 354 355 |
# File 'lib/exception_handling.rb', line 348 def log_periodically(exception_key, interval, ) self.periodic_exception_intervals ||= {} last_logged = self.periodic_exception_intervals[exception_key] if !last_logged || ( (last_logged + interval) < Time.now ) log_error( ) self.periodic_exception_intervals[exception_key] = Time.now end end |
.log_warning(message) ⇒ Object
264 265 266 |
# File 'lib/exception_handling.rb', line 264 def log_warning( ) log_error( Warning.new() ) end |
.set_log_error_timestamp ⇒ Object
331 332 333 |
# File 'lib/exception_handling.rb', line 331 def ExceptionHandling. = Time.now.to_i end |
.should_send_email? ⇒ Boolean
335 336 337 |
# File 'lib/exception_handling.rb', line 335 def should_send_email? ExceptionHandling.mailer_send_enabled end |
.trace_timing(description) ⇒ Object
339 340 341 342 343 344 345 346 |
# File 'lib/exception_handling.rb', line 339 def trace_timing(description) result = nil time = Benchmark.measure do result = yield end log_info "#{description} %.4fs " % time.real result end |
.write_exception_to_log(ex, exception_context, timestamp) ⇒ Object
Write an exception out to the log file using our own custom format.
240 241 242 243 244 |
# File 'lib/exception_handling.rb', line 240 def write_exception_to_log(ex, exception_context, ) ActiveSupport::Deprecation.silence do ExceptionHandling.logger.fatal("\n(Error:#{}) #{ex.class} #{exception_context} (#{ex.}):\n " + clean_backtrace(ex).join("\n ") + "\n\n") end end |