{"action":"created","comment":{"url":"https://api.github.com/repos/Invoca/exception_handling/pulls/comments/213486862","pull_request_review_id":150334570,"id":213486862,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxMzQ4Njg2Mg==","diff_hunk":"@@ -100,926 +100,922 @@ def asend(hash)\n   class SmtpClientErrbackStub < SmtpClientStub\n   end\n \n-  class HoneybadgerStub\n-    def self.notify(data)\n-    end\n-  end\n-\n-  context \"#log_error\" do\n+  context \"with honeybadger notify stubbed\" do\n     setup do\n-      ExceptionHandling.mailer_send_enabled = true\n+      stub(Honeybadger).notify(anything)\n     end\n \n-    should \"log the info and not raise another exception when sending email fails\" do\n-      9.times { ExceptionHandling.log_error('SomeError', 'Error Context') }\n-      mock(ExceptionHandling::Mailer).exception_notification(anything, anything, anything) { raise 'An Error' }\n-      mock(ExceptionHandling.logger) do |logger|\n-        logger.info(/ExceptionHandling.log_error_email rescued exception while logging StandardError: SomeError/)\n+    context \"#log_error\" do\n+      setup do\n+        ExceptionHandling.mailer_send_enabled = true\n       end\n-      stub($stderr).puts\n-      ExceptionHandling.log_error('SomeError', 'Error Context')\n-    end\n-  end\n \n-  context \"#log_warning\" do\n-    should \"have empty array as a backtrace\" do\n-      mock(ExceptionHandling).log_error(is_a(ExceptionHandling::Warning)) do |error|\n-        assert_equal [], error.backtrace\n+      should \"log the info and not raise another exception when sending email fails\" do\n+        9.times { ExceptionHandling.log_error('SomeError', 'Error Context') }\n+        mock(ExceptionHandling::Mailer).exception_notification(anything, anything, anything) { raise 'An Error' }\n+        mock(ExceptionHandling.logger) do |logger|\n+          logger.info(/ExceptionHandling.log_error_email rescued exception while logging StandardError: SomeError/)\n+        end\n+        stub($stderr).puts\n+        ExceptionHandling.log_error('SomeError', 'Error Context')\n       end\n-      ExceptionHandling.log_warning('Now with empty array as a backtrace!')\n     end\n-  end\n \n-  context \"configuration\" do\n-    should \"support a custom_data_hook\" do\n-      ExceptionHandling.custom_data_hook = method(:append_organization_info_config)\n-      ExceptionHandling.ensure_safe(\"mooo\") { raise \"Some BS\" }\n-      assert_match(/Invoca Engineering Dept./, ActionMailer::Base.deliveries[-1].body.to_s)\n-      ExceptionHandling.custom_data_hook = nil\n+    context \"#log_warning\" do\n+      should \"have empty array as a backtrace\" do\n+        mock(ExceptionHandling).log_error(is_a(ExceptionHandling::Warning)) do |error|\n+          assert_equal [], error.backtrace\n+        end\n+        ExceptionHandling.log_warning('Now with empty array as a backtrace!')\n+      end\n     end\n \n-    should \"support a log_error hook and pass exception data and treat like warning to it\" do\n-      begin\n-        @fail_count = 0\n-        ExceptionHandling.post_log_error_hook = method(:log_error_callback_config)\n+    context \"configuration\" do\n+      should \"support a custom_data_hook\" do\n+        ExceptionHandling.custom_data_hook = method(:append_organization_info_config)\n         ExceptionHandling.ensure_safe(\"mooo\") { raise \"Some BS\" }\n-        assert_equal 1, @fail_count\n-        assert_equal false, @treat_like_warning\n-      ensure\n-        ExceptionHandling.post_log_error_hook = nil\n-      end\n-\n-      assert_equal \"this is used by a test\", @callback_data[\"notes\"]\n-      assert_match(/this is used by a test/, ActionMailer::Base.deliveries[-1].body.to_s)\n-    end\n+        assert_match(/Invoca Engineering Dept./, ActionMailer::Base.deliveries[-1].body.to_s)\n+        ExceptionHandling.custom_data_hook = nil\n+      end\n+\n+      should \"support a log_error hook and pass exception data and treat like warning to it\" do\n+        begin\n+          @fail_count = 0\n+          ExceptionHandling.post_log_error_hook = method(:log_error_callback_config)\n+          ExceptionHandling.ensure_safe(\"mooo\") { raise \"Some BS\" }\n+          assert_equal 1, @fail_count\n+          assert_equal false, @treat_like_warning\n+        ensure\n+          ExceptionHandling.post_log_error_hook = nil\n+        end\n \n-    should \"plumb treat like warning to log error hook\" do\n-      begin\n-        @fail_count = 0\n-        ExceptionHandling.post_log_error_hook = method(:log_error_callback_config)\n-        ExceptionHandling.log_error(StandardError.new(\"Some BS\"), \"mooo\", treat_like_warning: true)\n-        assert_equal 1, @fail_count\n-        assert_equal true, @treat_like_warning\n-      ensure\n-        ExceptionHandling.post_log_error_hook = nil\n+        assert_equal \"this is used by a test\", @callback_data[\"notes\"]\n+        assert_match(/this is used by a test/, ActionMailer::Base.deliveries[-1].body.to_s)\n       end\n-    end\n \n-    should \"support rescue exceptions from a log_error hook\" do\n-      ExceptionHandling.post_log_error_hook = method(:log_error_callback_with_failure)\n-      log_info_messages = []\n-      stub(ExceptionHandling.logger).info.with_any_args do |message, _|\n-        log_info_messages << message\n+      should \"plumb treat like warning to log error hook\" do\n+        begin\n+          @fail_count = 0\n+          ExceptionHandling.post_log_error_hook = method(:log_error_callback_config)\n+          ExceptionHandling.log_error(StandardError.new(\"Some BS\"), \"mooo\", treat_like_warning: true)\n+          assert_equal 1, @fail_count\n+          assert_equal true, @treat_like_warning\n+        ensure\n+          ExceptionHandling.post_log_error_hook = nil\n+        end\n       end\n-      assert_nothing_raised { ExceptionHandling.ensure_safe(\"mooo\") { raise \"Some BS\" } }\n-      assert log_info_messages.find { |message| message =~ /Unable to execute custom log_error callback/ }\n-      ExceptionHandling.post_log_error_hook = nil\n-    end\n \n-    should \"handle nil message exceptions resulting from the log_error hook\" do\n-      ExceptionHandling.post_log_error_hook = method(:log_error_callback_returns_nil_message_exception)\n-      log_info_messages = []\n-      stub(ExceptionHandling.logger).info.with_any_args do |message, _|\n-        log_info_messages << message\n+      should \"support rescue exceptions from a log_error hook\" do\n+        ExceptionHandling.post_log_error_hook = method(:log_error_callback_with_failure)\n+        log_info_messages = []\n+        stub(ExceptionHandling.logger).info.with_any_args do |message, _|\n+          log_info_messages << message\n+        end\n+        assert_nothing_raised { ExceptionHandling.ensure_safe(\"mooo\") { raise \"Some BS\" } }\n+        assert log_info_messages.find { |message| message =~ /Unable to execute custom log_error callback/ }\n+        ExceptionHandling.post_log_error_hook = nil\n       end\n-      assert_nothing_raised { ExceptionHandling.ensure_safe(\"mooo\") { raise \"Some BS\" } }\n-      assert log_info_messages.find { |message| message =~ /Unable to execute custom log_error callback/ }\n-      ExceptionHandling.post_log_error_hook = nil\n-    end\n \n-    should \"handle nil message exceptions resulting from the custom data hook\" do\n-      ExceptionHandling.custom_data_hook = method(:custom_data_callback_returns_nil_message_exception)\n-      log_info_messages = []\n-      stub(ExceptionHandling.logger).info.with_any_args do |message, _|\n-        log_info_messages << message\n+      should \"handle nil message exceptions resulting from the log_error hook\" do\n+        ExceptionHandling.post_log_error_hook = method(:log_error_callback_returns_nil_message_exception)\n+        log_info_messages = []\n+        stub(ExceptionHandling.logger).info.with_any_args do |message, _|\n+          log_info_messages << message\n+        end\n+        assert_nothing_raised { ExceptionHandling.ensure_safe(\"mooo\") { raise \"Some BS\" } }\n+        assert log_info_messages.find { |message| message =~ /Unable to execute custom log_error callback/ }\n+        ExceptionHandling.post_log_error_hook = nil\n       end\n-      assert_nothing_raised { ExceptionHandling.ensure_safe(\"mooo\") { raise \"Some BS\" } }\n-      assert log_info_messages.find { |message| message =~ /Unable to execute custom custom_data_hook callback/ }\n-      ExceptionHandling.custom_data_hook = nil\n-    end\n \n-  end\n+      should \"handle nil message exceptions resulting from the custom data hook\" do\n+        ExceptionHandling.custom_data_hook = method(:custom_data_callback_returns_nil_message_exception)\n+        log_info_messages = []\n+        stub(ExceptionHandling.logger).info.with_any_args do |message, _|\n+          log_info_messages << message\n+        end\n+        assert_nothing_raised { ExceptionHandling.ensure_safe(\"mooo\") { raise \"Some BS\" } }\n+        assert log_info_messages.find { |message| message =~ /Unable to execute custom custom_data_hook callback/ }\n+        ExceptionHandling.custom_data_hook = nil\n+      end\n \n-  context \"Exception Handling\" do\n-    setup do\n-      ActionMailer::Base.deliveries.clear\n-      ExceptionHandling.send(:clear_exception_summary)\n     end\n \n-    context \"default_metric_name\" do\n-      should \"return exception_handling.warning when using log warning\" do\n-        warning = ExceptionHandling::Warning.new('this is a warning')\n-        metric  = ExceptionHandling.default_metric_name({}, warning, false)\n-        assert_equal 'exception_handling.warning', metric\n+    context \"Exception Handling\" do\n+      setup do\n+        ActionMailer::Base.deliveries.clear\n+        ExceptionHandling.send(:clear_exception_summary)\n       end\n \n-      should \"return exception_handling.warning when using treat_like_warning\" do\n-        exception = StandardError.new('this is an exception')\n-        metric    = ExceptionHandling.default_metric_name({}, exception, true)\n-        assert_equal 'exception_handling.warning', metric\n-      end\n+      context \"default_metric_name\" do\n+        should \"return exception_handling.warning when using log warning\" do\n+          warning = ExceptionHandling::Warning.new('this is a warning')\n+          metric  = ExceptionHandling.default_metric_name({}, warning, false)\n+          assert_equal 'exception_handling.warning', metric\n+        end\n \n-      should \"return exception_handling.exception when using log error\" do\n-        exception = StandardError.new('this is an exception')\n-        metric    = ExceptionHandling.default_metric_name({}, exception, false)\n-        assert_equal 'exception_handling.exception', metric\n-      end\n+        should \"return exception_handling.warning when using treat_like_warning\" do\n+          exception = StandardError.new('this is an exception')\n+          metric    = ExceptionHandling.default_metric_name({}, exception, true)\n+          assert_equal 'exception_handling.warning', metric\n+        end\n \n-      should \"return special metric when specified in exception filtering\" do\n-        exception = StandardError.new('this is an exception')\n-        metric    = ExceptionHandling.default_metric_name({ 'metric_name' => 'special_metric' }, exception, true)\n-        assert_equal 'exception_handling.special_metric', metric\n-      end\n-    end\n+        should \"return exception_handling.exception when using log error\" do\n+          exception = StandardError.new('this is an exception')\n+          metric    = ExceptionHandling.default_metric_name({}, exception, false)\n+          assert_equal 'exception_handling.exception', metric\n+        end\n \n-    context \"ExceptionHandling.ensure_safe\" do\n-      should \"log an exception with call stack if an exception is raised.\" do\n-        mock(ExceptionHandling.logger).fatal(/\\(blah\\):\\n.*exception_handling_test\\.rb/)\n-        ExceptionHandling.ensure_safe { raise ArgumentError.new(\"blah\") }\n+        should \"return special metric when specified in exception filtering\" do\n+          exception = StandardError.new('this is an exception')\n+          metric    = ExceptionHandling.default_metric_name({ 'metric_name' => 'special_metric' }, exception, true)\n+          assert_equal 'exception_handling.special_metric', metric\n+        end\n       end\n \n-      should \"log an exception with call stack if an ActionView template exception is raised.\" do\n-        mock(ExceptionHandling.logger).fatal(/\\(Error:\\d+\\) ActionView::Template::Error  \\(blah\\):\\n /)\n-        ExceptionHandling.ensure_safe { raise ActionView::TemplateError.new({}, ArgumentError.new(\"blah\")) }\n-      end\n+      context \"ExceptionHandling.ensure_safe\" do\n+        should \"log an exception with call stack if an exception is raised.\" do\n+          mock(ExceptionHandling.logger).fatal(/\\(blah\\):\\n.*exception_handling_test\\.rb/)\n+          ExceptionHandling.ensure_safe { raise ArgumentError.new(\"blah\") }\n+        end\n \n-      should \"should not log an exception if an exception is not raised.\" do\n-        dont_allow(ExceptionHandling.logger).fatal\n-        ExceptionHandling.ensure_safe { ; }\n-      end\n+        should \"log an exception with call stack if an ActionView template exception is raised.\" do\n+          mock(ExceptionHandling.logger).fatal(/\\(Error:\\d+\\) ActionView::Template::Error  \\(blah\\):\\n /)\n+          ExceptionHandling.ensure_safe { raise ActionView::TemplateError.new({}, ArgumentError.new(\"blah\")) }\n+        end\n \n-      should \"return its value if used during an assignment\" do\n-        dont_allow(ExceptionHandling.logger).fatal\n-        b = ExceptionHandling.ensure_safe { 5 }\n-        assert_equal 5, b\n-      end\n+        should \"should not log an exception if an exception is not raised.\" do\n+          dont_allow(ExceptionHandling.logger).fatal\n+          ExceptionHandling.ensure_safe { ; }\n+        end\n \n-      should \"return nil if an exception is raised during an assignment\" do\n-        mock(ExceptionHandling.logger).fatal(/\\(blah\\):\\n.*exception_handling_test\\.rb/)\n-        b = ExceptionHandling.ensure_safe { raise ArgumentError.new(\"blah\") }\n-        assert_nil b\n-      end\n+        should \"return its value if used during an assignment\" do\n+          dont_allow(ExceptionHandling.logger).fatal\n+          b = ExceptionHandling.ensure_safe { 5 }\n+          assert_equal 5, b\n+        end\n \n-      should \"allow a message to be appended to the error when logged.\" do\n-        mock(ExceptionHandling.logger).fatal(/mooo \\(blah\\):\\n.*exception_handling_test\\.rb/)\n-        b = ExceptionHandling.ensure_safe(\"mooo\") { raise ArgumentError.new(\"blah\") }\n-        assert_nil b\n-      end\n+        should \"return nil if an exception is raised during an assignment\" do\n+          mock(ExceptionHandling.logger).fatal(/\\(blah\\):\\n.*exception_handling_test\\.rb/)\n+          b = ExceptionHandling.ensure_safe { raise ArgumentError.new(\"blah\") }\n+          assert_nil b\n+        end\n \n-      should \"only rescue StandardError and descendents\" do\n-        assert_raise(Exception) { ExceptionHandling.ensure_safe(\"mooo\") { raise Exception } }\n+        should \"allow a message to be appended to the error when logged.\" do\n+          mock(ExceptionHandling.logger).fatal(/mooo \\(blah\\):\\n.*exception_handling_test\\.rb/)\n+          b = ExceptionHandling.ensure_safe(\"mooo\") { raise ArgumentError.new(\"blah\") }\n+          assert_nil b\n+        end\n \n-        mock(ExceptionHandling.logger).fatal(/mooo \\(blah\\):\\n.*exception_handling_test\\.rb/)\n+        should \"only rescue StandardError and descendents\" do\n+          assert_raise(Exception) { ExceptionHandling.ensure_safe(\"mooo\") { raise Exception } }\n \n-        b = ExceptionHandling.ensure_safe(\"mooo\") { raise StandardError.new(\"blah\") }\n-        assert_nil b\n-      end\n-    end\n+          mock(ExceptionHandling.logger).fatal(/mooo \\(blah\\):\\n.*exception_handling_test\\.rb/)\n \n-    context \"ExceptionHandling.ensure_completely_safe\" do\n-      should \"log an exception if an exception is raised.\" do\n-        mock(ExceptionHandling.logger).fatal(/\\(blah\\):\\n.*exception_handling_test\\.rb/)\n-        ExceptionHandling.ensure_completely_safe { raise ArgumentError.new(\"blah\") }\n+          b = ExceptionHandling.ensure_safe(\"mooo\") { raise StandardError.new(\"blah\") }\n+          assert_nil b\n+        end\n       end\n \n-      should \"should not log an exception if an exception is not raised.\" do\n-        mock(ExceptionHandling.logger).fatal.times(0)\n-        ExceptionHandling.ensure_completely_safe { ; }\n-      end\n+      context \"ExceptionHandling.ensure_completely_safe\" do\n+        should \"log an exception if an exception is raised.\" do\n+          mock(ExceptionHandling.logger).fatal(/\\(blah\\):\\n.*exception_handling_test\\.rb/)\n+          ExceptionHandling.ensure_completely_safe { raise ArgumentError.new(\"blah\") }\n+        end\n \n-      should \"return its value if used during an assignment\" do\n-        mock(ExceptionHandling.logger).fatal.times(0)\n-        b = ExceptionHandling.ensure_completely_safe { 5 }\n-        assert_equal 5, b\n-      end\n+        should \"should not log an exception if an exception is not raised.\" do\n+          mock(ExceptionHandling.logger).fatal.times(0)\n+          ExceptionHandling.ensure_completely_safe { ; }\n+        end\n \n-      should \"return nil if an exception is raised during an assignment\" do\n-        mock(ExceptionHandling.logger).fatal(/\\(blah\\):\\n.*exception_handling_test\\.rb/) { nil }\n-        b = ExceptionHandling.ensure_completely_safe { raise ArgumentError.new(\"blah\") }\n-        assert_nil b\n-      end\n+        should \"return its value if used during an assignment\" do\n+          mock(ExceptionHandling.logger).fatal.times(0)\n+          b = ExceptionHandling.ensure_completely_safe { 5 }\n+          assert_equal 5, b\n+        end\n \n-      should \"allow a message to be appended to the error when logged.\" do\n-        mock(ExceptionHandling.logger).fatal(/mooo \\(blah\\):\\n.*exception_handling_test\\.rb/)\n-        b = ExceptionHandling.ensure_completely_safe(\"mooo\") { raise ArgumentError.new(\"blah\") }\n-        assert_nil b\n-      end\n+        should \"return nil if an exception is raised during an assignment\" do\n+          mock(ExceptionHandling.logger).fatal(/\\(blah\\):\\n.*exception_handling_test\\.rb/) { nil }\n+          b = ExceptionHandling.ensure_completely_safe { raise ArgumentError.new(\"blah\") }\n+          assert_nil b\n+        end\n \n-      should \"rescue any instance or child of Exception\" do\n-        mock(ExceptionHandling.logger).fatal(/\\(blah\\):\\n.*exception_handling_test\\.rb/)\n-        ExceptionHandling::ensure_completely_safe { raise Exception.new(\"blah\") }\n-      end\n+        should \"allow a message to be appended to the error when logged.\" do\n+          mock(ExceptionHandling.logger).fatal(/mooo \\(blah\\):\\n.*exception_handling_test\\.rb/)\n+          b = ExceptionHandling.ensure_completely_safe(\"mooo\") { raise ArgumentError.new(\"blah\") }\n+          assert_nil b\n+        end\n \n-      should \"not rescue the special exceptions that Ruby uses\" do\n-        [SystemExit, SystemStackError, NoMemoryError, SecurityError].each do |exception|\n-          assert_raise exception do\n-            ExceptionHandling.ensure_completely_safe do\n-              raise exception.new\n+        should \"rescue any instance or child of Exception\" do\n+          mock(ExceptionHandling.logger).fatal(/\\(blah\\):\\n.*exception_handling_test\\.rb/)\n+          ExceptionHandling::ensure_completely_safe { raise Exception.new(\"blah\") }\n+        end\n+\n+        should \"not rescue the special exceptions that Ruby uses\" do\n+          [SystemExit, SystemStackError, NoMemoryError, SecurityError].each do |exception|\n+            assert_raise exception do\n+              ExceptionHandling.ensure_completely_safe do\n+                raise exception.new\n+              end\n             end\n           end\n         end\n       end\n-    end\n-\n-    context \"ExceptionHandling.ensure_escalation\" do\n-      should \"log the exception as usual and send the proper email\" do\n-        assert_equal 0, ActionMailer::Base.deliveries.count\n-        mock(ExceptionHandling.logger).fatal(/\\(blah\\):\\n.*exception_handling_test\\.rb/)\n-        ExceptionHandling.ensure_escalation( \"Favorite Feature\") { raise ArgumentError.new(\"blah\") }\n-        assert_equal 2, ActionMailer::Base.deliveries.count\n-        email = ActionMailer::Base.deliveries.last\n-        assert_equal \"#{ExceptionHandling.email_environment} Escalation: Favorite Feature\", email.subject\n-        assert_match 'ArgumentError: blah', email.body.to_s\n-        assert_match ExceptionHandling.last_exception_timestamp.to_s, email.body.to_s\n-      end\n \n-      should \"should not escalate if an exception is not raised.\" do\n-        assert_equal 0, ActionMailer::Base.deliveries.count\n-        dont_allow(ExceptionHandling.logger).fatal\n-        ExceptionHandling.ensure_escalation('Ignored') { ; }\n-        assert_equal 0, ActionMailer::Base.deliveries.count\n-      end\n+      context \"ExceptionHandling.ensure_escalation\" do\n+        should \"log the exception as usual and send the proper email\" do\n+          assert_equal 0, ActionMailer::Base.deliveries.count\n+          mock(ExceptionHandling.logger).fatal(/\\(blah\\):\\n.*exception_handling_test\\.rb/)\n+          ExceptionHandling.ensure_escalation( \"Favorite Feature\") { raise ArgumentError.new(\"blah\") }\n+          assert_equal 2, ActionMailer::Base.deliveries.count\n+          email = ActionMailer::Base.deliveries.last\n+          assert_equal \"#{ExceptionHandling.email_environment} Escalation: Favorite Feature\", email.subject\n+          assert_match 'ArgumentError: blah', email.body.to_s\n+          assert_match ExceptionHandling.last_exception_timestamp.to_s, email.body.to_s\n+        end\n \n-      should \"log if the escalation email can not be sent\" do\n-        any_instance_of(Mail::Message) do |message|\n-          mock(message).deliver\n-          mock(message).deliver { raise RuntimeError.new, \"Delivery Error\" }\n+        should \"should not escalate if an exception is not raised.\" do\n+          assert_equal 0, ActionMailer::Base.deliveries.count\n+          dont_allow(ExceptionHandling.logger).fatal\n+          ExceptionHandling.ensure_escalation('Ignored') { ; }\n+          assert_equal 0, ActionMailer::Base.deliveries.count\n         end\n-        mock(ExceptionHandling.logger) do |logger|\n-          logger.fatal(/first_test_exception/)\n-          logger.fatal(/safe_email_deliver .*Delivery Error/)\n+\n+        should \"log if the escalation email can not be sent\" do\n+          any_instance_of(Mail::Message) do |message|\n+            mock(message).deliver\n+            mock(message).deliver { raise RuntimeError.new, \"Delivery Error\" }\n+          end\n+          mock(ExceptionHandling.logger) do |logger|\n+            logger.fatal(/first_test_exception/)\n+            logger.fatal(/safe_email_deliver .*Delivery Error/)\n+          end\n+          ExceptionHandling.ensure_escalation(\"Not Used\") { raise ArgumentError.new(\"first_test_exception\") }\n+          assert_equal 0, ActionMailer::Base.deliveries.count\n         end\n-        ExceptionHandling.ensure_escalation(\"Not Used\") { raise ArgumentError.new(\"first_test_exception\") }\n-        assert_equal 0, ActionMailer::Base.deliveries.count\n       end\n-    end\n \n-    context \"ExceptionHandling.ensure_alert\" do\n-      should \"log the exception as usual and fire a sensu event\" do\n-        mock(ExceptionHandling::Sensu).generate_event(\"Favorite Feature\", \"test context\\nblah\")\n-        mock(ExceptionHandling.logger).fatal(/\\(blah\\):\\n.*exception_handling_test\\.rb/)\n-        ExceptionHandling.ensure_alert('Favorite Feature', 'test context') { raise ArgumentError.new(\"blah\") }\n-      end\n+      context \"ExceptionHandling.ensure_alert\" do\n+        should \"log the exception as usual and fire a sensu event\" do\n+          mock(ExceptionHandling::Sensu).generate_event(\"Favorite Feature\", \"test context\\nblah\")\n+          mock(ExceptionHandling.logger).fatal(/\\(blah\\):\\n.*exception_handling_test\\.rb/)\n+          ExceptionHandling.ensure_alert('Favorite Feature', 'test context') { raise ArgumentError.new(\"blah\") }\n+        end\n \n-      should \"should not send sensu event if an exception is not raised.\" do\n-        dont_allow(ExceptionHandling.logger).fatal\n-        dont_allow(ExceptionHandling::Sensu).generate_event\n-        ExceptionHandling.ensure_alert('Ignored', 'test context') { ; }\n-      end\n+        should \"should not send sensu event if an exception is not raised.\" do\n+          dont_allow(ExceptionHandling.logger).fatal\n+          dont_allow(ExceptionHandling::Sensu).generate_event\n+          ExceptionHandling.ensure_alert('Ignored', 'test context') { ; }\n+        end\n \n-      should \"log if the sensu event could not be sent\" do\n-        mock(ExceptionHandling::Sensu).send_event(anything) { raise \"Failed to send\" }\n-        mock(ExceptionHandling.logger) do |logger|\n-          logger.fatal(/first_test_exception/)\n-          logger.fatal(/Failed to send/)\n+        should \"log if the sensu event could not be sent\" do\n+          mock(ExceptionHandling::Sensu).send_event(anything) { raise \"Failed to send\" }\n+          mock(ExceptionHandling.logger) do |logger|\n+            logger.fatal(/first_test_exception/)\n+            logger.fatal(/Failed to send/)\n+          end\n+          ExceptionHandling.ensure_alert(\"Not Used\", 'test context') { raise ArgumentError.new(\"first_test_exception\") }\n         end\n-        ExceptionHandling.ensure_alert(\"Not Used\", 'test context') { raise ArgumentError.new(\"first_test_exception\") }\n-      end\n \n-      should \"log if the exception message is nil\" do\n-        mock(ExceptionHandling::Sensu).generate_event(\"some alert\", \"test context\\n\")\n-        ExceptionHandling.ensure_alert('some alert', 'test context') { raise_exception_with_nil_message }\n+        should \"log if the exception message is nil\" do\n+          mock(ExceptionHandling::Sensu).generate_event(\"some alert\", \"test context\\n\")\n+          ExceptionHandling.ensure_alert('some alert', 'test context') { raise_exception_with_nil_message }\n+        end\n       end\n-    end\n \n-    context \"ExceptionHandling.escalate_to_production_support\" do\n-      should \"notify production support\" do\n-        subject = \"Runtime Error found!\"\n-        exception = RuntimeError.new(\"Test\")\n-        recipients = [\"prodsupport@example.com\"]\n+      context \"ExceptionHandling.escalate_to_production_support\" do\n+        should \"notify production support\" do\n+          subject = \"Runtime Error found!\"\n+          exception = RuntimeError.new(\"Test\")\n+          recipients = [\"prodsupport@example.com\"]\n \n-        mock(ExceptionHandling).production_support_recipients { recipients }.times(2)\n-        mock(ExceptionHandling).escalate_custom(subject, exception, ExceptionHandling.last_exception_timestamp, recipients)\n-        ExceptionHandling.escalate_to_production_support(exception, subject)\n+          mock(ExceptionHandling).production_support_recipients { recipients }.times(2)\n+          mock(ExceptionHandling).escalate_custom(subject, exception, ExceptionHandling.last_exception_timestamp, recipients)\n+          ExceptionHandling.escalate_to_production_support(exception, subject)\n+        end\n       end\n-    end\n \n-    context \"exception timestamp\" do\n-      setup do\n-        Time.now_override = Time.parse( '1986-5-21 4:17 am UTC' )\n-      end\n+      context \"exception timestamp\" do\n+        setup do\n+          Time.now_override = Time.parse( '1986-5-21 4:17 am UTC' )\n+        end\n \n-      should \"include the timestamp when the exception is logged\" do\n-        mock(ExceptionHandling.logger).fatal(/\\(Error:517033020\\) ArgumentError mooo \\(blah\\):\\n.*exception_handling_test\\.rb/)\n-        b = ExceptionHandling.ensure_safe(\"mooo\") { raise ArgumentError.new(\"blah\") }\n-        assert_nil b\n+        should \"include the timestamp when the exception is logged\" do\n+          mock(ExceptionHandling.logger).fatal(/\\(Error:517033020\\) ArgumentError mooo \\(blah\\):\\n.*exception_handling_test\\.rb/)\n+          b = ExceptionHandling.ensure_safe(\"mooo\") { raise ArgumentError.new(\"blah\") }\n+          assert_nil b\n \n-        assert_equal 517033020, ExceptionHandling.last_exception_timestamp\n+          assert_equal 517033020, ExceptionHandling.last_exception_timestamp\n \n-        assert_emails 1\n-        assert_match(/517033020/, ActionMailer::Base.deliveries[-1].body.to_s)\n+          assert_emails 1\n+          assert_match(/517033020/, ActionMailer::Base.deliveries[-1].body.to_s)\n+        end\n       end\n-    end\n-\n-    should \"send just one copy of exceptions that don't repeat\" do\n-      ExceptionHandling.log_error(exception_1)\n-      ExceptionHandling.log_error(exception_2)\n-      assert_emails 2\n-      assert_match(/Exception 1/, ActionMailer::Base.deliveries[-2].subject)\n-      assert_match(/Exception 2/, ActionMailer::Base.deliveries[-1].subject)\n-    end\n-\n-    should \"not send emails if exception is a warning\" do\n-      ExceptionHandling.log_error(ExceptionHandling::Warning.new(\"Don't send email\"))\n-      assert_emails 0\n-    end\n \n-    should \"not send emails when log_warning is called\" do\n-      ExceptionHandling.log_warning(\"Don't send email\")\n-      assert_emails 0\n-    end\n-\n-    should \"log the error if the exception message is nil\" do\n-      ExceptionHandling.log_error(exception_with_nil_message)\n-      assert_emails(1)\n-      assert_match(/RuntimeError/, ActionMailer::Base.deliveries.last.subject)\n-    end\n-\n-    should \"log the error if the exception message is nil and the exception context is a hash\" do\n-      ExceptionHandling.log_error(exception_with_nil_message, \"SERVER_NAME\" => \"exceptional.com\")\n-      assert_emails(1)\n-      assert_match(/RuntimeError/, ActionMailer::Base.deliveries.last.subject)\n-    end\n-\n-    should \"only send 5 of a repeated error, but call post hook for every exception\" do\n-      @fail_count = 0\n-      ExceptionHandling.post_log_error_hook = method(:log_error_callback)\n-      assert_emails 5 do\n-        10.times do\n-          ExceptionHandling.log_error(exception_1)\n-        end\n+      should \"send just one copy of exceptions that don't repeat\" do\n+        ExceptionHandling.log_error(exception_1)\n+        ExceptionHandling.log_error(exception_2)\n+        assert_emails 2\n+        assert_match(/Exception 1/, ActionMailer::Base.deliveries[-2].subject)\n+        assert_match(/Exception 2/, ActionMailer::Base.deliveries[-1].subject)\n       end\n-      assert_equal 10, @fail_count\n-    end\n \n-    should \"only send 5 of a repeated error but don't send summary if 6th is different\" do\n-      assert_emails 5 do\n-        5.times do\n-          ExceptionHandling.log_error(exception_1)\n-        end\n+      should \"not send emails if exception is a warning\" do\n+        ExceptionHandling.log_error(ExceptionHandling::Warning.new(\"Don't send email\"))\n+        assert_emails 0\n       end\n-      assert_emails 1 do\n-        ExceptionHandling.log_error(exception_2)\n+\n+      should \"not send emails when log_warning is called\" do\n+        ExceptionHandling.log_warning(\"Don't send email\")\n+        assert_emails 0\n       end\n-    end\n \n-    should \"send the summary when the error is encountered an hour after the first occurrence\" do\n-      assert_emails 5 do # 5 exceptions, 4 summarized\n-        9.times do |t|\n-          ExceptionHandling.log_error(exception_1)\n-        end\n+      should \"log the error if the exception message is nil\" do\n+        ExceptionHandling.log_error(exception_with_nil_message)\n+        assert_emails(1)\n+        assert_match(/RuntimeError/, ActionMailer::Base.deliveries.last.subject)\n       end\n-      Time.now_override = 2.hours.from_now\n-      assert_emails 1 do # 1 summary (4 + 1 = 5) after 2 hours\n-        ExceptionHandling.log_error(exception_1)\n+\n+      should \"log the error if the exception message is nil and the exception context is a hash\" do\n+        ExceptionHandling.log_error(exception_with_nil_message, \"SERVER_NAME\" => \"exceptional.com\")\n+        assert_emails(1)\n+        assert_match(/RuntimeError/, ActionMailer::Base.deliveries.last.subject)\n       end\n-      assert_match(/\\[5 SUMMARIZED\\]/, ActionMailer::Base.deliveries.last.subject)\n-      assert_match(/This exception occurred 5 times since/, ActionMailer::Base.deliveries.last.body.to_s)\n \n-      assert_emails 0 do # still summarizing...\n-        7.times do\n-          ExceptionHandling.log_error(exception_1)\n+      should \"only send 5 of a repeated error, but call post hook for every exception\" do\n+        @fail_count = 0\n+        ExceptionHandling.post_log_error_hook = method(:log_error_callback)\n+        assert_emails 5 do\n+          10.times do\n+            ExceptionHandling.log_error(exception_1)\n+          end\n         end\n+        assert_equal 10, @fail_count\n       end\n \n-      Time.now_override = 3.hours.from_now\n-\n-      assert_emails 1 + 2 do # 1 summary and 2 new\n-        2.times do\n+      should \"only send 5 of a repeated error but don't send summary if 6th is different\" do\n+        assert_emails 5 do\n+          5.times do\n+            ExceptionHandling.log_error(exception_1)\n+          end\n+        end\n+        assert_emails 1 do\n           ExceptionHandling.log_error(exception_2)\n         end\n       end\n-      assert_match(/\\[7 SUMMARIZED\\]/, ActionMailer::Base.deliveries[-3].subject)\n-      assert_match(/This exception occurred 7 times since/, ActionMailer::Base.deliveries[-3].body.to_s)\n-    end\n \n-    should \"send the summary if a summary is available, but not sent when another exception comes up\" do\n-      assert_emails 5 do # 5 to start summarizing\n-        6.times do\n+      should \"send the summary when the error is encountered an hour after the first occurrence\" do\n+        assert_emails 5 do # 5 exceptions, 4 summarized\n+          9.times do |t|\n+            ExceptionHandling.log_error(exception_1)\n+          end\n+        end\n+        Time.now_override = 2.hours.from_now\n+        assert_emails 1 do # 1 summary (4 + 1 = 5) after 2 hours\n           ExceptionHandling.log_error(exception_1)\n         end\n-      end\n+        assert_match(/\\[5 SUMMARIZED\\]/, ActionMailer::Base.deliveries.last.subject)\n+        assert_match(/This exception occurred 5 times since/, ActionMailer::Base.deliveries.last.body.to_s)\n \n-      assert_emails 1 + 1 do # 1 summary of previous, 1 from new exception\n-        ExceptionHandling.log_error(exception_2)\n-      end\n+        assert_emails 0 do # still summarizing...\n+          7.times do\n+            ExceptionHandling.log_error(exception_1)\n+          end\n+        end\n \n-      assert_match(/\\[1 SUMMARIZED\\]/, ActionMailer::Base.deliveries[-2].subject)\n-      assert_match(/This exception occurred 1 times since/, ActionMailer::Base.deliveries[-2].body.to_s)\n+        Time.now_override = 3.hours.from_now\n \n-      assert_emails 5 do # 5 to start summarizing\n-        10.times do\n-          ExceptionHandling.log_error(exception_1)\n+        assert_emails 1 + 2 do # 1 summary and 2 new\n+          2.times do\n+            ExceptionHandling.log_error(exception_2)\n+          end\n         end\n+        assert_match(/\\[7 SUMMARIZED\\]/, ActionMailer::Base.deliveries[-3].subject)\n+        assert_match(/This exception occurred 7 times since/, ActionMailer::Base.deliveries[-3].body.to_s)\n       end\n \n-      assert_emails 0 do # still summarizing\n-        11.times do\n-          ExceptionHandling.log_error(exception_1)\n+      should \"send the summary if a summary is available, but not sent when another exception comes up\" do\n+        assert_emails 5 do # 5 to start summarizing\n+          6.times do\n+            ExceptionHandling.log_error(exception_1)\n+          end\n         end\n-      end\n-    end\n \n-    context \"Honeybadger integration\" do\n-      context \"with Honeybadger not defined\" do\n-        should \"not invoke send_exception_to_honeybadger when log_error is executed\" do\n-          dont_allow(ExceptionHandling).send_exception_to_honeybadger\n-          ExceptionHandling.log_error(exception_1)\n+        assert_emails 1 + 1 do # 1 summary of previous, 1 from new exception\n+          ExceptionHandling.log_error(exception_2)\n         end\n \n-        should \"not invoke send_exception_to_honeybadger when ensure_safe is executed\" do\n-          dont_allow(ExceptionHandling).send_exception_to_honeybadger\n-          ExceptionHandling.ensure_safe { raise exception_1 }\n-        end\n-      end\n+        assert_match(/\\[1 SUMMARIZED\\]/, ActionMailer::Base.deliveries[-2].subject)\n+        assert_match(/This exception occurred 1 times since/, ActionMailer::Base.deliveries[-2].body.to_s)\n \n-      context \"with Honeybadger defined\" do\n-        setup do\n-          stub(ExceptionHandling).honeybadger? { true }\n-          ExceptionHandling.const_set('Honeybadger', HoneybadgerStub)\n+        assert_emails 5 do # 5 to start summarizing\n+          10.times do\n+            ExceptionHandling.log_error(exception_1)\n+          end\n         end\n \n-        teardown do\n-          ExceptionHandling.send(:remove_const, 'Honeybadger')\n+        assert_emails 0 do # still summarizing\n+          11.times do\n+            ExceptionHandling.log_error(exception_1)\n+          end\n         end\n+      end\n \n-        should \"not send_exception_to_honeybadger when log_warning is executed\" do\n-          dont_allow(ExceptionHandling).send_exception_to_honeybadger\n-          ExceptionHandling.log_warning(\"This should not go to honeybadger\")\n-        end\n+      context \"Honeybadger integration\" do\n+        context \"with Honeybadger not defined\" do\n+          setup do\n+            stub(ExceptionHandling).honeybadger? { false }\n+          end\n \n-        should \"not send_exception_to_honeybadger when log_error is called with a Warning\" do\n-          dont_allow(ExceptionHandling).send_exception_to_honeybadger\n-          ExceptionHandling.log_error(ExceptionHandling::Warning.new(\"This should not go to honeybadger\"))\n-        end\n+          should \"not invoke send_exception_to_honeybadger when log_error is executed\" do\n+            dont_allow(ExceptionHandling).send_exception_to_honeybadger\n+            ExceptionHandling.log_error(exception_1)\n+          end\n \n-        should \"invoke send_exception_to_honeybadger when log_error is executed\" do\n-          mock.proxy(ExceptionHandling).send_exception_to_honeybadger.with_any_args\n-          ExceptionHandling.log_error(exception_1)\n+          should \"not invoke send_exception_to_honeybadger when ensure_safe is executed\" do\n+            dont_allow(ExceptionHandling).send_exception_to_honeybadger\n+            ExceptionHandling.ensure_safe { raise exception_1 }\n+          end\n         end\n \n-        should \"invoke send_exception_to_honeybadger when log_error_rack is executed\" do\n-          mock.proxy(ExceptionHandling).send_exception_to_honeybadger.with_any_args\n-          ExceptionHandling.log_error_rack(exception_1, {}, nil)\n-        end\n+        context \"with Honeybadger defined\" do\n+          should \"not send_exception_to_honeybadger when log_warning is executed\" do\n+            dont_allow(ExceptionHandling).send_exception_to_honeybadger\n+            ExceptionHandling.log_warning(\"This should not go to honeybadger\")\n+          end\n \n-        should \"invoke send_exception_to_honeybadger when ensure_safe is executed\" do\n-          mock.proxy(ExceptionHandling).send_exception_to_honeybadger.with_any_args\n-          ExceptionHandling.ensure_safe { raise exception_1 }\n-        end\n+          should \"not send_exception_to_honeybadger when log_error is called with a Warning\" do\n+            dont_allow(ExceptionHandling).send_exception_to_honeybadger\n+            ExceptionHandling.log_error(ExceptionHandling::Warning.new(\"This should not go to honeybadger\"))\n+          end\n \n-        should \"specify error message as an empty string when notifying honeybadger if exception message is nil\" do\n-          mock(ExceptionHandling::Honeybadger).notify.with_any_args do |args|\n-            assert_equal \"\", args[:error_message]\n+          should \"invoke send_exception_to_honeybadger when log_error is executed\" do\n+            mock.proxy(ExceptionHandling).send_exception_to_honeybadger.with_any_args\n+            ExceptionHandling.log_error(exception_1)\n           end\n-          ExceptionHandling.log_error(exception_with_nil_message)\n-        end\n \n-        should \"send error details and relevant context data to Honeybadger\" do\n-          Time.now_override = Time.now\n-          env = { server: \"fe98\" }\n-          parameters = { advertiser_id: 435 }\n-          session = { username: \"jsmith\" }\n-          request_uri = \"host/path\"\n-          controller = create_dummy_controller(env, parameters, session, request_uri)\n-          stub(ExceptionHandling).server_name { \"invoca_fe98\" }\n-\n-          exception = StandardError.new(\"Some BS\")\n-          exception.set_backtrace([\n-            \"test/unit/exception_handling_test.rb:847:in `exception_1'\",\n-            \"test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'\"])\n-          exception_context = { \"SERVER_NAME\" => \"exceptional.com\" }\n-\n-          honeybadger_data = nil\n-          mock(ExceptionHandling::Honeybadger).notify.with_any_args do |data|\n-            honeybadger_data = data\n+          should \"invoke send_exception_to_honeybadger when log_error_rack is executed\" do\n+            mock.proxy(ExceptionHandling).send_exception_to_honeybadger.with_any_args\n+            ExceptionHandling.log_error_rack(exception_1, {}, nil)\n           end\n-          ExceptionHandling.log_error(exception, exception_context, controller) do |data|\n-            data[:scm_revision] = \"5b24eac37aaa91f5784901e9aabcead36fd9df82\"\n-            data[:user_details] = { username: \"jsmith\" }\n-            data[:event_response] = \"Event successfully received\"\n-            data[:other_section] = \"This should not be included in the response\"\n+\n+          should \"invoke send_exception_to_honeybadger when ensure_safe is executed\" do\n+            mock.proxy(ExceptionHandling).send_exception_to_honeybadger.with_any_args\n+            ExceptionHandling.ensure_safe { raise exception_1 }\n           end\n \n-          expected_data = {\n-            error_class: :\"Test BS\",\n-            error_message: \"Some BS\",\n-            exception: exception,\n-            context: {\n-              timestamp: Time.now.to_i,\n-              error_class: \"StandardError\",\n-              server: \"invoca_fe98\",\n-              exception_context: { \"SERVER_NAME\" => \"exceptional.com\" },\n-              scm_revision: \"5b24eac37aaa91f5784901e9aabcead36fd9df82\",\n-              notes: \"this is used by a test\",\n-              user_details: { \"username\" => \"jsmith\" },\n-              request: {\n-                \"params\" => { \"advertiser_id\" => 435 },\n-                \"rails_root\" => \"Rails.root not defined. Is this a test environment?\",\n-                \"url\" => \"host/path\" },\n-              session: {\n-                \"key\" => nil,\n-                \"data\" => { \"username\" => \"jsmith\" } },\n-              environment: {\n-                \"SERVER_NAME\" => \"exceptional.com\" },\n-              backtrace: [\n-                \"test/unit/exception_handling_test.rb:847:in `exception_1'\",\n-                \"test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'\"],\n-              event_response: \"Event successfully received\"\n+          should \"specify error message as an empty string when notifying honeybadger if exception message is nil\" do\n+            mock(Honeybadger).notify.with_any_args do |args|\n+              assert_equal \"\", args[:error_message]\n+            end\n+            ExceptionHandling.log_error(exception_with_nil_message)\n+          end\n+\n+          should \"send error details and relevant context data to Honeybadger\" do\n+            Time.now_override = Time.now\n+            env = { server: \"fe98\" }\n+            parameters = { advertiser_id: 435 }\n+            session = { username: \"jsmith\" }\n+            request_uri = \"host/path\"\n+            controller = create_dummy_controller(env, parameters, session, request_uri)\n+            stub(ExceptionHandling).server_name { \"invoca_fe98\" }\n+\n+            exception = StandardError.new(\"Some BS\")\n+            exception.set_backtrace([\n+              \"test/unit/exception_handling_test.rb:847:in `exception_1'\",\n+              \"test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'\"])\n+            exception_context = { \"SERVER_NAME\" => \"exceptional.com\" }\n+\n+            honeybadger_data = nil\n+            mock(Honeybadger).notify.with_any_args do |data|\n+              honeybadger_data = data\n+            end\n+            ExceptionHandling.log_error(exception, exception_context, controller) do |data|\n+              data[:scm_revision] = \"5b24eac37aaa91f5784901e9aabcead36fd9df82\"\n+              data[:user_details] = { username: \"jsmith\" }\n+              data[:event_response] = \"Event successfully received\"\n+              data[:other_section] = \"This should not be included in the response\"\n+            end\n+\n+            expected_data = {\n+              error_class: :\"Test BS\",\n+              error_message: \"Some BS\",\n+              exception: exception,\n+              context: {\n+                timestamp: Time.now.to_i,\n+                error_class: \"StandardError\",\n+                server: \"invoca_fe98\",\n+                exception_context: { \"SERVER_NAME\" => \"exceptional.com\" },\n+                scm_revision: \"5b24eac37aaa91f5784901e9aabcead36fd9df82\",\n+                notes: \"this is used by a test\",\n+                user_details: { \"username\" => \"jsmith\" },\n+                request: {\n+                  \"params\" => { \"advertiser_id\" => 435 },\n+                  \"rails_root\" => \"Rails.root not defined. Is this a test environment?\",\n+                  \"url\" => \"host/path\" },\n+                session: {\n+                  \"key\" => nil,\n+                  \"data\" => { \"username\" => \"jsmith\" } },\n+                environment: {\n+                  \"SERVER_NAME\" => \"exceptional.com\" },\n+                backtrace: [\n+                  \"test/unit/exception_handling_test.rb:847:in `exception_1'\",\n+                  \"test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'\"],\n+                event_response: \"Event successfully received\"\n+              }\n             }\n-          }\n-          assert_equal_with_diff expected_data, honeybadger_data\n-        end\n+            assert_equal_with_diff expected_data, honeybadger_data\n+          end\n \n-        should \"not send notification to honeybadger when exception description has the flag turned off\" do\n-          filter_list = {\n-            NoHoneybadger: {\n-              error: \"suppress Honeybadger notification\",\n-              send_to_honeybadger: false\n+          should \"not send notification to honeybadger when exception description has the flag turned off\" do\n+            filter_list = {\n+              NoHoneybadger: {\n+                error: \"suppress Honeybadger notification\",\n+                send_to_honeybadger: false\n+              }\n             }\n-          }\n-          stub(File).mtime { incrementing_mtime }\n-          mock(YAML).load_file.with_any_args { ActiveSupport::HashWithIndifferentAccess.new(filter_list) }.at_least(1)\n-\n-          exception = StandardError.new(\"suppress Honeybadger notification\")\n-          mock.proxy(ExceptionHandling).send_exception_to_honeybadger.with_any_args.once\n-          dont_allow(ExceptionHandling::Honeybadger).notify\n-          ExceptionHandling.log_error(exception)\n+            stub(File).mtime { incrementing_mtime }\n+            mock(YAML).load_file.with_any_args { ActiveSupport::HashWithIndifferentAccess.new(filter_list) }.at_least(1)\n+\n+            exception = StandardError.new(\"suppress Honeybadger notification\")\n+            mock.proxy(ExceptionHandling).send_exception_to_honeybadger.with_any_args.once\n+            dont_allow(Honeybadger).notify\n+            ExceptionHandling.log_error(exception)\n+          end\n         end\n       end\n-    end\n \n-    class EventResponse\n-      def to_s\n-        \"message from to_s!\"\n+      class EventResponse\n+        def to_s\n+          \"message from to_s!\"\n+        end\n       end\n-    end\n \n-    should \"allow sections to have data with just a to_s method\" do\n-      ExceptionHandling.log_error(\"This is my RingSwitch example.  Log, don't email!\") do |data|\n-        data.merge!(:event_response => EventResponse.new)\n+      should \"allow sections to have data with just a to_s method\" do\n+        ExceptionHandling.log_error(\"This is my RingSwitch example.  Log, don't email!\") do |data|\n+          data.merge!(:event_response => EventResponse.new)\n+        end\n+        assert_emails 1\n+        assert_match(/message from to_s!/, ActionMailer::Base.deliveries.last.body.to_s)\n       end\n-      assert_emails 1\n-      assert_match(/message from to_s!/, ActionMailer::Base.deliveries.last.body.to_s)\n     end\n-  end\n \n-  should \"rescue exceptions that happen in log_error\" do\n-    stub(ExceptionHandling).make_exception { raise ArgumentError.new(\"Bad argument\") }\n-    mock(ExceptionHandling).write_exception_to_log(satisfy { |ex| ex.to_s['Bad argument'] },\n-                                                   satisfy { |context| context['ExceptionHandling.log_error rescued exception while logging Runtime message'] },\n-                                                   anything)\n-    stub($stderr).puts\n-    ExceptionHandling.log_error(RuntimeError.new(\"A runtime error\"), \"Runtime message\")\n-  end\n-\n-  should \"rescue exceptions that happen when log_error yields\" do\n-    mock(ExceptionHandling).write_exception_to_log(satisfy { |ex| ex.to_s['Bad argument'] },\n-                                                   satisfy { |context| context['Context message'] },\n-                                                   anything)\n-    ExceptionHandling.log_error(ArgumentError.new(\"Bad argument\"), \"Context message\") { |data| raise 'Error!!!' }\n-  end\n-\n-  context \"Exception Filtering\" do\n-    setup do\n-      filter_list = { :exception1 => { 'error' => \"my error message\" },\n-                      :exception2 => { 'error' => \"some other message\", :session => \"misc data\" } }\n-      stub(YAML).load_file { ActiveSupport::HashWithIndifferentAccess.new(filter_list) }\n-\n-      # bump modified time up to get the above filter loaded\n-      stub(File).mtime { incrementing_mtime }\n+    should \"rescue exceptions that happen in log_error\" do\n+      stub(ExceptionHandling).make_exception { raise ArgumentError.new(\"Bad argument\") }\n+      mock(ExceptionHandling).write_exception_to_log(satisfy { |ex| ex.to_s['Bad argument'] },\n+                                                     satisfy { |context| context['ExceptionHandling.log_error rescued exception while logging Runtime message'] },\n+                                                     anything)\n+      stub($stderr).puts\n+      ExceptionHandling.log_error(RuntimeError.new(\"A runtime error\"), \"Runtime message\")\n     end\n \n-    should \"handle case where filter list is not found\" do\n-      stub(YAML).load_file { raise Errno::ENOENT.new(\"File not found\") }\n-\n-      ActionMailer::Base.deliveries.clear\n-      ExceptionHandling.log_error( \"My error message is in list\" )\n-      assert_emails 1\n+    should \"rescue exceptions that happen when log_error yields\" do\n+      mock(ExceptionHandling).write_exception_to_log(satisfy { |ex| ex.to_s['Bad argument'] },\n+                                                     satisfy { |context| context['Context message'] },\n+                                                     anything)\n+      ExceptionHandling.log_error(ArgumentError.new(\"Bad argument\"), \"Context message\") { |data| raise 'Error!!!' }\n     end\n \n-    should \"log exception and suppress email when exception is on filter list\" do\n-      ActionMailer::Base.deliveries.clear\n-      ExceptionHandling.log_error( \"Error message is not in list\" )\n-      assert_emails 1\n+    context \"Exception Filtering\" do\n+      setup do\n+        filter_list = { :exception1 => { 'error' => \"my error message\" },\n+                        :exception2 => { 'error' => \"some other message\", :session => \"misc data\" } }\n+        stub(YAML).load_file { ActiveSupport::HashWithIndifferentAccess.new(filter_list) }\n \n-      ActionMailer::Base.deliveries.clear\n-      ExceptionHandling.log_error( \"My error message is in list\" )\n-      assert_emails 0\n-    end\n+        # bump modified time up to get the above filter loaded\n+        stub(File).mtime { incrementing_mtime }\n+      end\n \n-    should \"allow filtering exception on any text in exception data\" do\n-      filters = { :exception1 => { :session => \"data: my extra session data\" } }\n-      stub(YAML).load_file { ActiveSupport::HashWithIndifferentAccess.new(filters) }\n+      should \"handle case where filter list is not found\" do\n+        stub(YAML).load_file { raise Errno::ENOENT.new(\"File not found\") }\n \n-      ActionMailer::Base.deliveries.clear\n-      ExceptionHandling.log_error( \"No match here\" ) do |data|\n-        data[:session] = {\n-            :key         => \"@session_id\",\n-            :data        => \"my extra session data\"\n-          }\n-      end\n-      assert_emails 0\n-\n-      ActionMailer::Base.deliveries.clear\n-      ExceptionHandling.log_error( \"No match here\" ) do |data|\n-        data[:session] = {\n-            :key         => \"@session_id\",\n-            :data        => \"my extra session <no match!> data\"\n-          }\n+        ActionMailer::Base.deliveries.clear\n+        ExceptionHandling.log_error( \"My error message is in list\" )\n+        assert_emails 1\n       end\n-      assert_emails 1, ActionMailer::Base.deliveries.*.body.*.inspect\n-    end\n \n-    should \"reload filter list on the next exception if file was modified\" do\n-      ActionMailer::Base.deliveries.clear\n-      ExceptionHandling.log_error( \"Error message is not in list\" )\n-      assert_emails 1\n+      should \"log exception and suppress email when exception is on filter list\" do\n+        ActionMailer::Base.deliveries.clear\n+        ExceptionHandling.log_error( \"Error message is not in list\" )\n+        assert_emails 1\n \n-      filter_list = { :exception1 => { 'error' => \"Error message is not in list\" } }\n-      stub(YAML).load_file { ActiveSupport::HashWithIndifferentAccess.new(filter_list) }\n-      stub(File).mtime { incrementing_mtime }\n+        ActionMailer::Base.deliveries.clear\n+        ExceptionHandling.log_error( \"My error message is in list\" )\n+        assert_emails 0\n+      end\n \n-      ActionMailer::Base.deliveries.clear\n-      ExceptionHandling.log_error( \"Error message is not in list\" )\n-      assert_emails 0, ActionMailer::Base.deliveries.*.body.*.inspect\n-    end\n+      should \"allow filtering exception on any text in exception data\" do\n+        filters = { :exception1 => { :session => \"data: my extra session data\" } }\n+        stub(YAML).load_file { ActiveSupport::HashWithIndifferentAccess.new(filters) }\n \n-    should \"not consider filter if both error message and body do not match\" do\n-      # error message matches, but not full text\n-      ActionMailer::Base.deliveries.clear\n-      ExceptionHandling.log_error( \"some other message\" )\n-      assert_emails 1, ActionMailer::Base.deliveries.*.body.*.inspect\n+        ActionMailer::Base.deliveries.clear\n+        ExceptionHandling.log_error( \"No match here\" ) do |data|\n+          data[:session] = {\n+              :key         => \"@session_id\",\n+              :data        => \"my extra session data\"\n+            }\n+        end\n+        assert_emails 0\n \n-      # now both match\n-      ActionMailer::Base.deliveries.clear\n-      ExceptionHandling.log_error( \"some other message\" ) do |data|\n-        data[:session] = {:some_random_key => \"misc data\"}\n+        ActionMailer::Base.deliveries.clear\n+        ExceptionHandling.log_error( \"No match here\" ) do |data|\n+          data[:session] = {\n+              :key         => \"@session_id\",\n+              :data        => \"my extra session <no match!> data\"\n+            }\n+        end\n+        assert_emails 1, ActionMailer::Base.deliveries.*.body.*.inspect\n       end\n-      assert_emails 0, ActionMailer::Base.deliveries.*.body.*.inspect\n-    end\n \n-    should \"skip environment keys not on whitelist\" do\n-      ActionMailer::Base.deliveries.clear\n-      ExceptionHandling.log_error( \"some message\" ) do |data|\n-        data[:environment] = { :SERVER_PROTOCOL => \"HTTP/1.0\", :RAILS_SECRETS_YML_CONTENTS => 'password: VERY_SECRET_PASSWORD' }\n-      end\n-      assert_emails 1, ActionMailer::Base.deliveries.*.body.*.inspect\n-      mail = ActionMailer::Base.deliveries.last\n-      assert_nil mail.body.to_s[\"RAILS_SECRETS_YML_CONTENTS\"], mail.body.to_s # this is not on whitelist\n-      assert     mail.body.to_s[\"SERVER_PROTOCOL: HTTP/1.0\" ], mail.body.to_s # this is\n-    end\n+      should \"reload filter list on the next exception if file was modified\" do\n+        ActionMailer::Base.deliveries.clear\n+        ExceptionHandling.log_error( \"Error message is not in list\" )\n+        assert_emails 1\n+\n+        filter_list = { :exception1 => { 'error' => \"Error message is not in list\" } }\n+        stub(YAML).load_file { ActiveSupport::HashWithIndifferentAccess.new(filter_list) }\n+        stub(File).mtime { incrementing_mtime }\n \n-    should \"omit environment defaults\" do\n-      ActionMailer::Base.deliveries.clear\n-      ExceptionHandling.log_error( \"some message\" ) do |data|\n-        data[:environment] = {:SERVER_PORT => '80', :SERVER_PROTOCOL => \"HTTP/1.0\"}\n+        ActionMailer::Base.deliveries.clear\n+        ExceptionHandling.log_error( \"Error message is not in list\" )\n+        assert_emails 0, ActionMailer::Base.deliveries.*.body.*.inspect\n       end\n-      assert_emails 1, ActionMailer::Base.deliveries.*.body.*.inspect\n-      mail = ActionMailer::Base.deliveries.last\n-      assert_nil mail.body.to_s[\"SERVER_PORT\"              ], mail.body.to_s # this was default\n-      assert     mail.body.to_s[\"SERVER_PROTOCOL: HTTP/1.0\"], mail.body.to_s # this was not\n-    end\n \n-    should \"reject the filter file if any contain all empty regexes\" do\n-      filter_list = { :exception1 => { 'error' => \"\", :session => \"\" },\n-                      :exception2 => { 'error' => \"is not in list\", :session => \"\" } }\n-      stub(YAML).load_file { ActiveSupport::HashWithIndifferentAccess.new(filter_list) }\n-      stub(File).mtime { incrementing_mtime }\n+      should \"not consider filter if both error message and body do not match\" do\n+        # error message matches, but not full text\n+        ActionMailer::Base.deliveries.clear\n+        ExceptionHandling.log_error( \"some other message\" )\n+        assert_emails 1, ActionMailer::Base.deliveries.*.body.*.inspect\n \n-      ActionMailer::Base.deliveries.clear\n-      ExceptionHandling.log_error( \"Error message is not in list\" )\n-      assert_emails 1, ActionMailer::Base.deliveries.*.inspect\n-    end\n+        # now both match\n+        ActionMailer::Base.deliveries.clear\n+        ExceptionHandling.log_error( \"some other message\" ) do |data|\n+          data[:session] = {:some_random_key => \"misc data\"}\n+        end\n+        assert_emails 0, ActionMailer::Base.deliveries.*.body.*.inspect\n+      end\n \n-    should \"reload filter file if filename changes\" do\n-      catalog = ExceptionHandling.exception_catalog\n-      ExceptionHandling.filter_list_filename = \"./config/other_exception_filters.yml\"\n-      assert_not_equal catalog, ExceptionHandling.exception_catalog\n-    end\n+      should \"skip environment keys not on whitelist\" do\n+        ActionMailer::Base.deliveries.clear\n+        ExceptionHandling.log_error( \"some message\" ) do |data|\n+          data[:environment] = { :SERVER_PROTOCOL => \"HTTP/1.0\", :RAILS_SECRETS_YML_CONTENTS => 'password: VERY_SECRET_PASSWORD' }\n+        end\n+        assert_emails 1, ActionMailer::Base.deliveries.*.body.*.inspect\n+        mail = ActionMailer::Base.deliveries.last\n+        assert_nil mail.body.to_s[\"RAILS_SECRETS_YML_CONTENTS\"], mail.body.to_s # this is not on whitelist\n+        assert     mail.body.to_s[\"SERVER_PROTOCOL: HTTP/1.0\" ], mail.body.to_s # this is\n+      end\n \n-    context \"Exception Handling Mailer\" do\n-      should \"create email\" do\n-        ExceptionHandling.log_error(exception_1) do |data|\n-          data[:request] = { :params => {:id => 10993}, :url => \"www.ringrevenue.com\" }\n-          data[:session] = { :key => \"DECAFE\" }\n+      should \"omit environment defaults\" do\n+        ActionMailer::Base.deliveries.clear\n+        ExceptionHandling.log_error( \"some message\" ) do |data|\n+          data[:environment] = {:SERVER_PORT => '80', :SERVER_PROTOCOL => \"HTTP/1.0\"}\n         end\n+        assert_emails 1, ActionMailer::Base.deliveries.*.body.*.inspect\n+        mail = ActionMailer::Base.deliveries.last\n+        assert_nil mail.body.to_s[\"SERVER_PORT\"              ], mail.body.to_s # this was default\n+        assert     mail.body.to_s[\"SERVER_PROTOCOL: HTTP/1.0\"], mail.body.to_s # this was not\n+      end\n+\n+      should \"reject the filter file if any contain all empty regexes\" do\n+        filter_list = { :exception1 => { 'error' => \"\", :session => \"\" },\n+                        :exception2 => { 'error' => \"is not in list\", :session => \"\" } }\n+        stub(YAML).load_file { ActiveSupport::HashWithIndifferentAccess.new(filter_list) }\n+        stub(File).mtime { incrementing_mtime }\n+\n+        ActionMailer::Base.deliveries.clear\n+        ExceptionHandling.log_error( \"Error message is not in list\" )\n         assert_emails 1, ActionMailer::Base.deliveries.*.inspect\n-        assert mail = ActionMailer::Base.deliveries.last\n-        assert_equal ['exceptions@example.com'], mail.to\n-        assert_equal ['server@example.com'].to_s, mail.from.to_s\n-        assert_match(/Exception 1/, mail.to_s)\n-        assert_match(/key: DECAFE/, mail.to_s)\n-        assert_match(/id: 10993/, mail.to_s)\n       end\n \n-      EXPECTED_SMTP_HASH =\n-          {\n-              :host   => '127.0.0.1',\n-              :domain => 'localhost.localdomain',\n-              :from   => 'server@example.com',\n-              :to     => 'exceptions@example.com'\n-          }\n+      should \"reload filter file if filename changes\" do\n+        catalog = ExceptionHandling.exception_catalog\n+        ExceptionHandling.filter_list_filename = \"./config/other_exception_filters.yml\"\n+        assert_not_equal catalog, ExceptionHandling.exception_catalog\n+      end\n \n-      [[true, false], [true, true]].each do |em_flag, synchrony_flag|\n-        context \"eventmachine_safe = #{em_flag} && eventmachine_synchrony = #{synchrony_flag}\" do\n-          setup do\n-            ExceptionHandling.eventmachine_safe       = em_flag\n-            ExceptionHandling.eventmachine_synchrony  = synchrony_flag\n-            EventMachineStub.block = nil\n-            set_test_const('EventMachine', EventMachineStub)\n-            set_test_const('EventMachine::Protocols', Module.new)\n-            set_test_const('EventMachine::DNS', Module.new)\n-            set_test_const('EventMachine::DNS::Resolver', DNSResolvStub)\n+      context \"Exception Handling Mailer\" do\n+        should \"create email\" do\n+          ExceptionHandling.log_error(exception_1) do |data|\n+            data[:request] = { :params => {:id => 10993}, :url => \"www.ringrevenue.com\" }\n+            data[:session] = { :key => \"DECAFE\" }\n           end\n+          assert_emails 1, ActionMailer::Base.deliveries.*.inspect\n+          assert mail = ActionMailer::Base.deliveries.last\n+          assert_equal ['exceptions@example.com'], mail.to\n+          assert_equal ['server@example.com'].to_s, mail.from.to_s\n+          assert_match(/Exception 1/, mail.to_s)\n+          assert_match(/key: DECAFE/, mail.to_s)\n+          assert_match(/id: 10993/, mail.to_s)\n+        end\n \n-          teardown do\n-            ExceptionHandling.eventmachine_safe       = false\n-            ExceptionHandling.eventmachine_synchrony  = false\n-          end\n+        EXPECTED_SMTP_HASH =\n+            {\n+                :host   => '127.0.0.1',\n+                :domain => 'localhost.localdomain',\n+                :from   => 'server@example.com',\n+                :to     => 'exceptions@example.com'\n+            }\n \n-          should \"schedule EventMachine STMP when EventMachine defined\" do\n-            set_test_const('EventMachine::Protocols::SmtpClient', SmtpClientStub)\n+        [[true, false], [true, true]].each do |em_flag, synchrony_flag|\n+          context \"eventmachine_safe = #{em_flag} && eventmachine_synchrony = #{synchrony_flag}\" do\n+            setup do\n+              ExceptionHandling.eventmachine_safe       = em_flag\n+              ExceptionHandling.eventmachine_synchrony  = synchrony_flag\n+              EventMachineStub.block = nil\n+              set_test_const('EventMachine', EventMachineStub)\n+              set_test_const('EventMachine::Protocols', Module.new)\n+              set_test_const('EventMachine::DNS', Module.new)\n+              set_test_const('EventMachine::DNS::Resolver', DNSResolvStub)\n+            end\n \n-            ExceptionHandling.log_error(exception_1)\n-            assert EventMachineStub.block\n-            EventMachineStub.block.call\n-            assert DNSResolvStub.callback_block\n-            DNSResolvStub.callback_block.call ['127.0.0.1']\n-            assert_equal_with_diff EXPECTED_SMTP_HASH, (SmtpClientStub.send_hash & EXPECTED_SMTP_HASH.keys).map_hash { |k,v| v.to_s }, SmtpClientStub.send_hash.inspect\n-            assert_equal((synchrony_flag ? :asend : :send), SmtpClientStub.last_method)\n-            assert_match(/Exception 1/, SmtpClientStub.send_hash[:content])\n-            assert_emails 0, ActionMailer::Base.deliveries.*.to_s\n-          end\n+            teardown do\n+              ExceptionHandling.eventmachine_safe       = false\n+              ExceptionHandling.eventmachine_synchrony  = false\n+            end\n \n","path":"test/unit/exception_handling_test.rb","position":1334,"original_position":1536,"commit_id":"f564ccf49208df2bbc03042a350ab67ec2942426","original_commit_id":"f564ccf49208df2bbc03042a350ab67ec2942426","user":{"login":"houndci-bot","id":6697940,"node_id":"MDQ6VXNlcjY2OTc5NDA=","avatar_url":"https://avatars0.githubusercontent.com/u/6697940?v=4","gravatar_id":"","url":"https://api.github.com/users/houndci-bot","html_url":"https://github.com/houndci-bot","followers_url":"https://api.github.com/users/houndci-bot/followers","following_url":"https://api.github.com/users/houndci-bot/following{/other_user}","gists_url":"https://api.github.com/users/houndci-bot/gists{/gist_id}","starred_url":"https://api.github.com/users/houndci-bot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/houndci-bot/subscriptions","organizations_url":"https://api.github.com/users/houndci-bot/orgs","repos_url":"https://api.github.com/users/houndci-bot/repos","events_url":"https://api.github.com/users/houndci-bot/events{/privacy}","received_events_url":"https://api.github.com/users/houndci-bot/received_events","type":"User","site_admin":false},"body":"Style/HashSyntax: Use the new Ruby 1.9 hash syntax.<br>Layout/SpaceAroundOperators: Surrounding space missing for operator =>.","created_at":"2018-08-28T22:00:40Z","updated_at":"2018-08-28T22:00:42Z","html_url":"https://github.com/Invoca/exception_handling/pull/33#discussion_r213486862","pull_request_url":"https://api.github.com/repos/Invoca/exception_handling/pulls/33","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/Invoca/exception_handling/pulls/comments/213486862"},"html":{"href":"https://github.com/Invoca/exception_handling/pull/33#discussion_r213486862"},"pull_request":{"href":"https://api.github.com/repos/Invoca/exception_handling/pulls/33"}}},"pull_request":{"url":"https://api.github.com/repos/Invoca/exception_handling/pulls/33","id":211497610,"node_id":"MDExOlB1bGxSZXF1ZXN0MjExNDk3NjEw","html_url":"https://github.com/Invoca/exception_handling/pull/33","diff_url":"https://github.com/Invoca/exception_handling/pull/33.diff","patch_url":"https://github.com/Invoca/exception_handling/pull/33.patch","issue_url":"https://api.github.com/repos/Invoca/exception_handling/issues/33","number":33,"state":"open","locked":false,"title":"TECH-2730 honeybadger upgrade","user":{"login":"gabe-kent","id":7633743,"node_id":"MDQ6VXNlcjc2MzM3NDM=","avatar_url":"https://avatars1.githubusercontent.com/u/7633743?v=4","gravatar_id":"","url":"https://api.github.com/users/gabe-kent","html_url":"https://github.com/gabe-kent","followers_url":"https://api.github.com/users/gabe-kent/followers","following_url":"https://api.github.com/users/gabe-kent/following{/other_user}","gists_url":"https://api.github.com/users/gabe-kent/gists{/gist_id}","starred_url":"https://api.github.com/users/gabe-kent/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gabe-kent/subscriptions","organizations_url":"https://api.github.com/users/gabe-kent/orgs","repos_url":"https://api.github.com/users/gabe-kent/repos","events_url":"https://api.github.com/users/gabe-kent/events{/privacy}","received_events_url":"https://api.github.com/users/gabe-kent/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-08-28T17:19:57Z","updated_at":"2018-08-28T22:00:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a97a19ad11a189a9a9b058cf9771e9038491e535","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/Invoca/exception_handling/pulls/33/commits","review_comments_url":"https://api.github.com/repos/Invoca/exception_handling/pulls/33/comments","review_comment_url":"https://api.github.com/repos/Invoca/exception_handling/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Invoca/exception_handling/issues/33/comments","statuses_url":"https://api.github.com/repos/Invoca/exception_handling/statuses/f564ccf49208df2bbc03042a350ab67ec2942426","head":{"label":"Invoca:1808/TECH-2730_honeybadger_upgrade","ref":"1808/TECH-2730_honeybadger_upgrade","sha":"f564ccf49208df2bbc03042a350ab67ec2942426","user":{"login":"Invoca","id":808155,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgwODE1NQ==","avatar_url":"https://avatars1.githubusercontent.com/u/808155?v=4","gravatar_id":"","url":"https://api.github.com/users/Invoca","html_url":"https://github.com/Invoca","followers_url":"https://api.github.com/users/Invoca/followers","following_url":"https://api.github.com/users/Invoca/following{/other_user}","gists_url":"https://api.github.com/users/Invoca/gists{/gist_id}","starred_url":"https://api.github.com/users/Invoca/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Invoca/subscriptions","organizations_url":"https://api.github.com/users/Invoca/orgs","repos_url":"https://api.github.com/users/Invoca/repos","events_url":"https://api.github.com/users/Invoca/events{/privacy}","received_events_url":"https://api.github.com/users/Invoca/received_events","type":"Organization","site_admin":false},"repo":{"id":11936991,"node_id":"MDEwOlJlcG9zaXRvcnkxMTkzNjk5MQ==","name":"exception_handling","full_name":"Invoca/exception_handling","owner":{"login":"Invoca","id":808155,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgwODE1NQ==","avatar_url":"https://avatars1.githubusercontent.com/u/808155?v=4","gravatar_id":"","url":"https://api.github.com/users/Invoca","html_url":"https://github.com/Invoca","followers_url":"https://api.github.com/users/Invoca/followers","following_url":"https://api.github.com/users/Invoca/following{/other_user}","gists_url":"https://api.github.com/users/Invoca/gists{/gist_id}","starred_url":"https://api.github.com/users/Invoca/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Invoca/subscriptions","organizations_url":"https://api.github.com/users/Invoca/orgs","repos_url":"https://api.github.com/users/Invoca/repos","events_url":"https://api.github.com/users/Invoca/events{/privacy}","received_events_url":"https://api.github.com/users/Invoca/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Invoca/exception_handling","description":"Exception handling logger/emailer","fork":false,"url":"https://api.github.com/repos/Invoca/exception_handling","forks_url":"https://api.github.com/repos/Invoca/exception_handling/forks","keys_url":"https://api.github.com/repos/Invoca/exception_handling/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Invoca/exception_handling/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Invoca/exception_handling/teams","hooks_url":"https://api.github.com/repos/Invoca/exception_handling/hooks","issue_events_url":"https://api.github.com/repos/Invoca/exception_handling/issues/events{/number}","events_url":"https://api.github.com/repos/Invoca/exception_handling/events","assignees_url":"https://api.github.com/repos/Invoca/exception_handling/assignees{/user}","branches_url":"https://api.github.com/repos/Invoca/exception_handling/branches{/branch}","tags_url":"https://api.github.com/repos/Invoca/exception_handling/tags","blobs_url":"https://api.github.com/repos/Invoca/exception_handling/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Invoca/exception_handling/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Invoca/exception_handling/git/refs{/sha}","trees_url":"https://api.github.com/repos/Invoca/exception_handling/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Invoca/exception_handling/statuses/{sha}","languages_url":"https://api.github.com/repos/Invoca/exception_handling/languages","stargazers_url":"https://api.github.com/repos/Invoca/exception_handling/stargazers","contributors_url":"https://api.github.com/repos/Invoca/exception_handling/contributors","subscribers_url":"https://api.github.com/repos/Invoca/exception_handling/subscribers","subscription_url":"https://api.github.com/repos/Invoca/exception_handling/subscription","commits_url":"https://api.github.com/repos/Invoca/exception_handling/commits{/sha}","git_commits_url":"https://api.github.com/repos/Invoca/exception_handling/git/commits{/sha}","comments_url":"https://api.github.com/repos/Invoca/exception_handling/comments{/number}","issue_comment_url":"https://api.github.com/repos/Invoca/exception_handling/issues/comments{/number}","contents_url":"https://api.github.com/repos/Invoca/exception_handling/contents/{+path}","compare_url":"https://api.github.com/repos/Invoca/exception_handling/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Invoca/exception_handling/merges","archive_url":"https://api.github.com/repos/Invoca/exception_handling/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Invoca/exception_handling/downloads","issues_url":"https://api.github.com/repos/Invoca/exception_handling/issues{/number}","pulls_url":"https://api.github.com/repos/Invoca/exception_handling/pulls{/number}","milestones_url":"https://api.github.com/repos/Invoca/exception_handling/milestones{/number}","notifications_url":"https://api.github.com/repos/Invoca/exception_handling/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Invoca/exception_handling/labels{/name}","releases_url":"https://api.github.com/repos/Invoca/exception_handling/releases{/id}","deployments_url":"https://api.github.com/repos/Invoca/exception_handling/deployments","created_at":"2013-08-06T23:31:52Z","updated_at":"2018-07-17T22:36:38Z","pushed_at":"2018-08-28T22:00:19Z","git_url":"git://github.com/Invoca/exception_handling.git","ssh_url":"git@github.com:Invoca/exception_handling.git","clone_url":"https://github.com/Invoca/exception_handling.git","svn_url":"https://github.com/Invoca/exception_handling","homepage":"","size":279,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"Invoca:master","ref":"master","sha":"e002e18c52daadfe96714917c7c3fc40ca4f4bac","user":{"login":"Invoca","id":808155,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgwODE1NQ==","avatar_url":"https://avatars1.githubusercontent.com/u/808155?v=4","gravatar_id":"","url":"https://api.github.com/users/Invoca","html_url":"https://github.com/Invoca","followers_url":"https://api.github.com/users/Invoca/followers","following_url":"https://api.github.com/users/Invoca/following{/other_user}","gists_url":"https://api.github.com/users/Invoca/gists{/gist_id}","starred_url":"https://api.github.com/users/Invoca/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Invoca/subscriptions","organizations_url":"https://api.github.com/users/Invoca/orgs","repos_url":"https://api.github.com/users/Invoca/repos","events_url":"https://api.github.com/users/Invoca/events{/privacy}","received_events_url":"https://api.github.com/users/Invoca/received_events","type":"Organization","site_admin":false},"repo":{"id":11936991,"node_id":"MDEwOlJlcG9zaXRvcnkxMTkzNjk5MQ==","name":"exception_handling","full_name":"Invoca/exception_handling","owner":{"login":"Invoca","id":808155,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgwODE1NQ==","avatar_url":"https://avatars1.githubusercontent.com/u/808155?v=4","gravatar_id":"","url":"https://api.github.com/users/Invoca","html_url":"https://github.com/Invoca","followers_url":"https://api.github.com/users/Invoca/followers","following_url":"https://api.github.com/users/Invoca/following{/other_user}","gists_url":"https://api.github.com/users/Invoca/gists{/gist_id}","starred_url":"https://api.github.com/users/Invoca/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Invoca/subscriptions","organizations_url":"https://api.github.com/users/Invoca/orgs","repos_url":"https://api.github.com/users/Invoca/repos","events_url":"https://api.github.com/users/Invoca/events{/privacy}","received_events_url":"https://api.github.com/users/Invoca/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Invoca/exception_handling","description":"Exception handling logger/emailer","fork":false,"url":"https://api.github.com/repos/Invoca/exception_handling","forks_url":"https://api.github.com/repos/Invoca/exception_handling/forks","keys_url":"https://api.github.com/repos/Invoca/exception_handling/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Invoca/exception_handling/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Invoca/exception_handling/teams","hooks_url":"https://api.github.com/repos/Invoca/exception_handling/hooks","issue_events_url":"https://api.github.com/repos/Invoca/exception_handling/issues/events{/number}","events_url":"https://api.github.com/repos/Invoca/exception_handling/events","assignees_url":"https://api.github.com/repos/Invoca/exception_handling/assignees{/user}","branches_url":"https://api.github.com/repos/Invoca/exception_handling/branches{/branch}","tags_url":"https://api.github.com/repos/Invoca/exception_handling/tags","blobs_url":"https://api.github.com/repos/Invoca/exception_handling/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Invoca/exception_handling/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Invoca/exception_handling/git/refs{/sha}","trees_url":"https://api.github.com/repos/Invoca/exception_handling/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Invoca/exception_handling/statuses/{sha}","languages_url":"https://api.github.com/repos/Invoca/exception_handling/languages","stargazers_url":"https://api.github.com/repos/Invoca/exception_handling/stargazers","contributors_url":"https://api.github.com/repos/Invoca/exception_handling/contributors","subscribers_url":"https://api.github.com/repos/Invoca/exception_handling/subscribers","subscription_url":"https://api.github.com/repos/Invoca/exception_handling/subscription","commits_url":"https://api.github.com/repos/Invoca/exception_handling/commits{/sha}","git_commits_url":"https://api.github.com/repos/Invoca/exception_handling/git/commits{/sha}","comments_url":"https://api.github.com/repos/Invoca/exception_handling/comments{/number}","issue_comment_url":"https://api.github.com/repos/Invoca/exception_handling/issues/comments{/number}","contents_url":"https://api.github.com/repos/Invoca/exception_handling/contents/{+path}","compare_url":"https://api.github.com/repos/Invoca/exception_handling/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Invoca/exception_handling/merges","archive_url":"https://api.github.com/repos/Invoca/exception_handling/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Invoca/exception_handling/downloads","issues_url":"https://api.github.com/repos/Invoca/exception_handling/issues{/number}","pulls_url":"https://api.github.com/repos/Invoca/exception_handling/pulls{/number}","milestones_url":"https://api.github.com/repos/Invoca/exception_handling/milestones{/number}","notifications_url":"https://api.github.com/repos/Invoca/exception_handling/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Invoca/exception_handling/labels{/name}","releases_url":"https://api.github.com/repos/Invoca/exception_handling/releases{/id}","deployments_url":"https://api.github.com/repos/Invoca/exception_handling/deployments","created_at":"2013-08-06T23:31:52Z","updated_at":"2018-07-17T22:36:38Z","pushed_at":"2018-08-28T22:00:19Z","git_url":"git://github.com/Invoca/exception_handling.git","ssh_url":"git@github.com:Invoca/exception_handling.git","clone_url":"https://github.com/Invoca/exception_handling.git","svn_url":"https://github.com/Invoca/exception_handling","homepage":"","size":279,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Invoca/exception_handling/pulls/33"},"html":{"href":"https://github.com/Invoca/exception_handling/pull/33"},"issue":{"href":"https://api.github.com/repos/Invoca/exception_handling/issues/33"},"comments":{"href":"https://api.github.com/repos/Invoca/exception_handling/issues/33/comments"},"review_comments":{"href":"https://api.github.com/repos/Invoca/exception_handling/pulls/33/comments"},"review_comment":{"href":"https://api.github.com/repos/Invoca/exception_handling/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Invoca/exception_handling/pulls/33/commits"},"statuses":{"href":"https://api.github.com/repos/Invoca/exception_handling/statuses/f564ccf49208df2bbc03042a350ab67ec2942426"}},"author_association":"NONE"}}
{"actor":{"display_login":"houndci-bot"}}