sentry-raven 2.1.3 → 3.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +5 -5
  2. data/.craft.yml +19 -0
  3. data/.scripts/bump-version.rb +5 -0
  4. data/CHANGELOG.md +703 -0
  5. data/Gemfile +37 -0
  6. data/Makefile +3 -0
  7. data/README.md +116 -18
  8. data/Rakefile +30 -0
  9. data/exe/raven +32 -0
  10. data/lib/raven/backtrace.rb +16 -6
  11. data/lib/raven/base.rb +17 -4
  12. data/lib/raven/breadcrumbs/{activesupport.rb → active_support_logger.rb} +9 -3
  13. data/lib/raven/breadcrumbs/logger.rb +2 -92
  14. data/lib/raven/breadcrumbs/sentry_logger.rb +73 -0
  15. data/lib/raven/breadcrumbs.rb +3 -1
  16. data/lib/raven/cli.rb +31 -43
  17. data/lib/raven/client.rb +39 -17
  18. data/lib/raven/configuration.rb +277 -37
  19. data/lib/raven/context.rb +17 -11
  20. data/lib/raven/core_ext/object/deep_dup.rb +57 -0
  21. data/lib/raven/core_ext/object/duplicable.rb +153 -0
  22. data/lib/raven/event.rb +172 -233
  23. data/lib/raven/helpers/deprecation_helper.rb +17 -0
  24. data/lib/raven/instance.rb +51 -25
  25. data/lib/raven/integrations/delayed_job.rb +18 -18
  26. data/lib/raven/integrations/rack-timeout.rb +11 -5
  27. data/lib/raven/integrations/rack.rb +36 -19
  28. data/lib/raven/integrations/rails/active_job.rb +52 -20
  29. data/lib/raven/integrations/rails/backtrace_cleaner.rb +29 -0
  30. data/lib/raven/integrations/rails/controller_transaction.rb +13 -0
  31. data/lib/raven/integrations/rails/overrides/debug_exceptions_catcher.rb +2 -2
  32. data/lib/raven/integrations/rails.rb +24 -8
  33. data/lib/raven/integrations/rake.rb +6 -1
  34. data/lib/raven/integrations/sidekiq/cleanup_middleware.rb +13 -0
  35. data/lib/raven/integrations/sidekiq/error_handler.rb +38 -0
  36. data/lib/raven/integrations/sidekiq.rb +6 -57
  37. data/lib/raven/interface.rb +2 -2
  38. data/lib/raven/interfaces/exception.rb +0 -2
  39. data/lib/raven/interfaces/http.rb +0 -2
  40. data/lib/raven/interfaces/message.rb +1 -1
  41. data/lib/raven/interfaces/single_exception.rb +0 -2
  42. data/lib/raven/interfaces/stack_trace.rb +19 -27
  43. data/lib/raven/linecache.rb +34 -17
  44. data/lib/raven/logger.rb +11 -18
  45. data/lib/raven/processor/cookies.rb +27 -7
  46. data/lib/raven/processor/http_headers.rb +18 -5
  47. data/lib/raven/processor/post_data.rb +16 -3
  48. data/lib/raven/processor/removecircularreferences.rb +12 -8
  49. data/lib/raven/processor/removestacktrace.rb +17 -6
  50. data/lib/raven/processor/sanitizedata.rb +88 -29
  51. data/lib/raven/processor/utf8conversion.rb +39 -14
  52. data/lib/raven/processor.rb +1 -1
  53. data/lib/raven/transports/http.rb +29 -21
  54. data/lib/raven/transports/stdout.rb +20 -0
  55. data/lib/raven/transports.rb +4 -8
  56. data/lib/raven/utils/context_filter.rb +42 -0
  57. data/lib/raven/utils/deep_merge.rb +6 -12
  58. data/lib/raven/utils/exception_cause_chain.rb +20 -0
  59. data/lib/raven/utils/real_ip.rb +1 -1
  60. data/lib/raven/utils/request_id.rb +16 -0
  61. data/lib/raven/version.rb +2 -2
  62. data/lib/sentry-raven-without-integrations.rb +6 -1
  63. data/lib/sentry_raven_without_integrations.rb +1 -0
  64. data/sentry-raven.gemspec +28 -0
  65. metadata +37 -103
  66. data/lib/raven/error.rb +0 -4
data/Gemfile ADDED
@@ -0,0 +1,37 @@
1
+ source "https://rubygems.org/"
2
+
3
+ gemspec
4
+
5
+ rails_version = ENV["RAILS_VERSION"]
6
+ rails_version = "5.2" if rails_version.nil?
7
+
8
+ if rails_version.to_f != 0
9
+ gem "rails", "~> #{rails_version}"
10
+ gem "rspec-rails", "~> 4.0"
11
+ end
12
+
13
+ gem "delayed_job"
14
+ gem "sidekiq"
15
+
16
+ gem "rack"
17
+ gem "rack-timeout"
18
+
19
+ # TODO: Remove this if https://github.com/jruby/jruby/issues/6547 is addressed
20
+ gem "i18n", "<= 1.8.7"
21
+
22
+ gem "pry"
23
+ gem "benchmark-ips"
24
+ gem "benchmark_driver"
25
+ gem "benchmark-ipsa"
26
+ gem "benchmark-memory"
27
+ gem "ruby-prof", platform: :mri
28
+ gem "rake", "> 12"
29
+ gem "rubocop", "~> 0.81.0"
30
+ gem "rspec", "~> 3.9.0"
31
+ gem "capybara", "~> 3.15.0" # rspec system tests
32
+ gem "puma" # rspec system tests
33
+
34
+ gem "timecop"
35
+ gem "test-unit"
36
+ gem "simplecov"
37
+ gem "codecov", "<= 0.2.12"
data/Makefile ADDED
@@ -0,0 +1,3 @@
1
+ build:
2
+ bundle install
3
+ gem build sentry-raven.gemspec
data/README.md CHANGED
@@ -1,13 +1,44 @@
1
- # Raven-Ruby
1
+ <p align="center">
2
+ <a href="https://sentry.io" target="_blank" align="center">
3
+ <img src="https://sentry-brand.storage.googleapis.com/sentry-logo-black.png" width="280">
4
+ </a>
5
+ <br>
6
+ </p>
7
+
8
+ # Raven-Ruby, the Ruby Client for Sentry
9
+
10
+ ### 🚧 Migrating To The New SDK 🚧
11
+
12
+ We've released our new Ruby SDK, [sentry-ruby](https://github.com/getsentry/sentry-ruby/tree/master/sentry-ruby). Here are the benefits of migrating to it:
13
+
14
+ - **Unified Interfaces With Other SDKs:** The design of `sentry-raven` is outdated compared with our modern Sentry SDKs. If you also use other Sentry SDKs, such as Sentry's JavaScript SDK for your frontend application, you'll notice that their interfaces are quite different from the one provided for `sentry-raven`. The new `sentry-ruby` SDK provides a more consistent user experience across all different platforms.
15
+
16
+ - **Performance Monitoring:** The Sentry Ruby SDK includes [performance monitoring](https://docs.sentry.io/product/performance/), which you can enable if you haven't already as ([discussed here](https://docs.sentry.io/platforms/ruby/performance/)).
17
+
18
+ - **Future Support:** `sentry-raven` has entered maintenance mode, which means it won't receive any new feature supports or aggressive bug fixes.
19
+
20
+ - **Better Extensibility:** Unlike `sentry-raven`, `sentry-ruby` is built with extensibility in mind and will allow the community to build extensions for different integrations/features.
21
+
22
+ If you're interested in the migration, please also read our [migration guide](https://docs.sentry.io/platforms/ruby/migration/) for more information.
23
+
24
+ ---
25
+
2
26
 
3
27
  [![Gem Version](https://img.shields.io/gem/v/sentry-raven.svg)](https://rubygems.org/gems/sentry-raven)
4
- [![Build Status](https://img.shields.io/travis/getsentry/raven-ruby/master.svg)](https://travis-ci.org/getsentry/raven-ruby)
28
+ ![Build Status](https://github.com/getsentry/raven-ruby/workflows/Test/badge.svg)
29
+ [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master)
30
+ [![Gem](https://img.shields.io/gem/dt/sentry-raven.svg)](https://rubygems.org/gems/sentry-raven/)
31
+ [![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=sentry-raven&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=sentry-raven&package-manager=bundler&version-scheme=semver)
32
+
33
+
34
+ [Documentation](https://docs.sentry.io/clients/ruby/) | [Bug Tracker](https://github.com/getsentry/raven-ruby/issues) | [Forum](https://forum.sentry.io/) | IRC: irc.freenode.net, #sentry
35
+
36
+ The official Ruby-language client and integration layer for the [Sentry](https://github.com/getsentry/sentry) error reporting API.
5
37
 
6
- A client and integration layer for the [Sentry](https://github.com/getsentry/sentry) error reporting API.
7
38
 
8
39
  ## Requirements
9
40
 
10
- We test on Ruby 1.9, 2.2 and 2.3 at the latest patchlevel/teeny version. Our Rails integration works with Rails 4.2+. JRuby support is experimental - check TravisCI to see if the build is passing or failing.
41
+ We test on Ruby 2.3, 2.4, 2.5, 2.6 and 2.7 at the latest patchlevel/teeny version. We also support JRuby 9.0. Our Rails integration works with Rails 4.2+, including Rails 5 and Rails 6.
11
42
 
12
43
  ## Getting Started
13
44
 
@@ -17,30 +48,30 @@ We test on Ruby 1.9, 2.2 and 2.3 at the latest patchlevel/teeny version. Our Rai
17
48
  gem "sentry-raven"
18
49
  ```
19
50
 
20
- ### Raven only runs when SENTRY_DSN is set
51
+ ### Raven only runs when Sentry DSN is set
21
52
 
22
53
  Raven will capture and send exceptions to the Sentry server whenever its DSN is set. This makes environment-based configuration easy - if you don't want to send errors in a certain environment, just don't set the DSN in that environment!
23
54
 
24
55
  ```bash
25
56
  # Set your SENTRY_DSN environment variable.
26
- export SENTRY_DSN=http://public:secret@example.com/project-id
57
+ export SENTRY_DSN=http://public@example.com/project-id
27
58
  ```
28
59
  ```ruby
29
- # Or you can configure the client in the code (not recommended - keep your DSN secret!)
60
+ # Or you can configure the client in the code.
30
61
  Raven.configure do |config|
31
- config.dsn = 'http://public:secret@example.com/project-id'
62
+ config.dsn = 'http://public@example.com/project-id'
32
63
  end
33
64
  ```
34
65
 
35
- ### Raven doesn't report some kinds of data by default.
66
+ ### Raven doesn't report some kinds of data by default
36
67
 
37
- Raven ignores some exceptions by default - most of these are related to 404s or controller actions not being found. [For a complete list, see the `IGNORE_DEFAULT` constant](https://github.com/getsentry/raven-ruby/blob/master/lib/raven/configuration.rb).
68
+ **Raven ignores some exceptions by default** - most of these are related to 404s or controller actions not being found. [For a complete list, see the `IGNORE_DEFAULT` constant](https://github.com/getsentry/raven-ruby/blob/master/lib/raven/configuration.rb).
38
69
 
39
- Raven doesn't report POST data or cookies by default. In addition, it will attempt to remove any obviously sensitive data, such as credit card or Social Security numbers. For more information about how Sentry processes your data, [check out the documentation on the `processors` config setting.](https://docs.getsentry.com/hosted/clients/ruby/config/)
70
+ Raven doesn't report POST data or cookies by default. In addition, it will attempt to remove any obviously sensitive data, such as credit card or Social Security numbers. For more information about how Sentry processes your data, [check out the documentation on the `processors` config setting.](https://docs.sentry.io/platforms/ruby/configuration/options/)
40
71
 
41
- ### Call
72
+ ### Usage
42
73
 
43
- If you use Rails, you're already done - no more configuration required! Check [Integrations](https://docs.getsentry.com/hosted/clients/ruby/integrations/) for more details on other gems Sentry integrates with automatically.
74
+ **If you use Rails, you're already done - no more configuration required!** Check [Integrations](https://docs.sentry.io/platforms/ruby/configuration/integrations/) for more details on other gems Sentry integrates with automatically.
44
75
 
45
76
  Otherwise, Raven supports two methods of capturing exceptions:
46
77
 
@@ -57,10 +88,77 @@ rescue ZeroDivisionError => exception
57
88
  end
58
89
  ```
59
90
 
91
+ ### More configuration
92
+
93
+ You're all set - but there's a few more settings you may want to know about too!
94
+
95
+ #### async
96
+
97
+ When an error or message occurs, the notification is immediately sent to Sentry. Raven can be configured to send asynchronously:
98
+
99
+ ```ruby
100
+ config.async = lambda { |event|
101
+ Thread.new { Raven.send_event(event) }
102
+ }
103
+ ```
104
+
105
+ Using a thread to send events will be adequate for truly parallel Ruby platforms such as JRuby, though the benefit on MRI/CRuby will be limited. If the async callback raises an exception, Raven will attempt to send synchronously.
106
+
107
+ Note that the naive example implementation has a major drawback - it can create an infinite number of threads. We recommend creating a background job, using your background job processor, that will send Sentry notifications in the background.
108
+
109
+ ```ruby
110
+ config.async = lambda { |event| SentryJob.perform_later(event) }
111
+
112
+ class SentryJob < ActiveJob::Base
113
+ queue_as :default
114
+
115
+ def perform(event)
116
+ Raven.send_event(event)
117
+ end
118
+ end
119
+ ```
120
+
121
+ #### transport_failure_callback
122
+
123
+ If Raven fails to send an event to Sentry for any reason (either the Sentry server has returned a 4XX or 5XX response), this Proc or lambda will be called.
124
+
125
+ ```ruby
126
+ config.transport_failure_callback = lambda { |event, error|
127
+ AdminMailer.email_admins("Oh god, it's on fire because #{error.message}!", event).deliver_later
128
+ }
129
+ ```
130
+
131
+ #### Context
132
+
133
+ Much of the usefulness of Sentry comes from additional context data with the events. Raven makes this very convenient by providing methods to set thread local context data that is then submitted automatically with all events:
134
+
135
+ ```ruby
136
+ Raven.user_context email: 'foo@example.com'
137
+
138
+ Raven.tags_context interesting: 'yes'
139
+
140
+ Raven.extra_context additional_info: 'foo'
141
+ ```
142
+
143
+ You can also use `tags_context` and `extra_context` to provide scoped information:
144
+
145
+ ```ruby
146
+ Raven.tags_context(interesting: 'yes') do
147
+ # the `interesting: 'yes'` tag will only present in the requests sent inside the block
148
+ Raven.capture_exception(exception)
149
+ end
150
+
151
+ Raven.extra_context(additional_info: 'foo') do
152
+ # same as above, the `additional_info` will only present in this request
153
+ Raven.capture_exception(exception)
154
+ end
155
+ ```
156
+
157
+ For more information, see [Context](https://docs.sentry.io/platforms/ruby/enriching-events/context/).
158
+
60
159
  ## More Information
61
160
 
62
- * [Documentation](https://docs.getsentry.com/hosted/clients/ruby/)
63
- * [Bug Tracker](https://github.com/getsentry/raven-ruby/issues>)
64
- * [Code](https://github.com/getsentry/raven-ruby>)
65
- * [Mailing List](https://groups.google.com/group/getsentry>)
66
- * [IRC](irc://irc.freenode.net/sentry>) (irc.freenode.net, #sentry)
161
+ * [Documentation](https://docs.sentry.io/clients/ruby/)
162
+ * [Bug Tracker](https://github.com/getsentry/raven-ruby/issues)
163
+ * [Forum](https://forum.sentry.io/)
164
+ - [Discord](https://discord.gg/ez5KZN7)
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ require 'rake'
2
+ require 'raven'
3
+ require 'rubygems/package_task'
4
+ require 'bundler/gem_tasks'
5
+
6
+ gemspec = Gem::Specification.load(Dir['*.gemspec'].first)
7
+
8
+ Gem::PackageTask.new(gemspec).define
9
+
10
+ begin
11
+ require 'rubygems'
12
+ require 'rspec/core/rake_task'
13
+
14
+ require 'rubocop/rake_task'
15
+ RuboCop::RakeTask.new(:rubocop) do |task|
16
+ task.patterns = ['lib/**/*.rb','spec/**/*.rb',]
17
+ task.options << '--display-cop-names'
18
+ end
19
+
20
+ RSpec::Core::RakeTask.new(:spec) do |spec|
21
+ spec.pattern = 'spec/**/*_spec.rb'
22
+ end
23
+
24
+ rescue LoadError
25
+ task :spec do
26
+ abort "Rspec is not available. bundle install to run unit tests"
27
+ end
28
+ end
29
+
30
+ task :default => [:rubocop, :spec]
data/exe/raven ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "raven"
4
+ require "raven/cli"
5
+ require "optparse"
6
+
7
+ parser = OptionParser.new do |opt|
8
+ opt.banner = "Usage: raven COMMAND [OPTIONS]"
9
+ opt.separator ""
10
+ opt.separator "Commands"
11
+ opt.separator " test: send a test event"
12
+ opt.separator ""
13
+ opt.separator "Options"
14
+
15
+ opt.on("-h", "--help", "help") do
16
+ puts parser
17
+ end
18
+ end
19
+
20
+ parser.parse!
21
+
22
+ case ARGV[0]
23
+ when "test"
24
+ dsn = ARGV[1] if ARGV.length > 1
25
+ if !dsn
26
+ puts "Usage: raven test <dsn>"
27
+ else
28
+ Raven::CLI.test(dsn)
29
+ end
30
+ else
31
+ puts parser
32
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## Inspired by Rails' and Airbrake's backtrace parsers.
2
4
 
3
5
  module Raven
@@ -5,11 +7,16 @@ module Raven
5
7
  class Backtrace
6
8
  # Handles backtrace parsing line by line
7
9
  class Line
8
- # regexp (optionnally allowing leading X: for windows support)
9
- RUBY_INPUT_FORMAT = /^((?:[a-zA-Z]:)?[^:]+|<.*>):(\d+)(?::in `([^']+)')?$/
10
+ RB_EXTENSION = ".rb"
11
+ # regexp (optional leading X: on windows, or JRuby9000 class-prefix)
12
+ RUBY_INPUT_FORMAT = /
13
+ ^ \s* (?: [a-zA-Z]: | uri:classloader: )? ([^:]+ | <.*>):
14
+ (\d+)
15
+ (?: :in \s `([^']+)')?$
16
+ /x.freeze
10
17
 
11
18
  # org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
12
- JAVA_INPUT_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/
19
+ JAVA_INPUT_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/.freeze
13
20
 
14
21
  # The file portion of the line (such as app/models/user.rb)
15
22
  attr_reader :file
@@ -30,6 +37,7 @@ module Raven
30
37
  ruby_match = unparsed_line.match(RUBY_INPUT_FORMAT)
31
38
  if ruby_match
32
39
  _, file, number, method = ruby_match.to_a
40
+ file.sub!(/\.class$/, RB_EXTENSION)
33
41
  module_name = nil
34
42
  else
35
43
  java_match = unparsed_line.match(JAVA_INPUT_FORMAT)
@@ -68,7 +76,7 @@ module Raven
68
76
 
69
77
  def self.in_app_pattern
70
78
  @in_app_pattern ||= begin
71
- project_root = Raven.configuration.project_root && Raven.configuration.project_root.to_s
79
+ project_root = Raven.configuration.project_root&.to_s
72
80
  Regexp.new("^(#{project_root}/)?#{Raven.configuration.app_dirs_pattern || APP_DIRS_PATTERN}")
73
81
  end
74
82
  end
@@ -78,7 +86,7 @@ module Raven
78
86
  attr_writer :file, :number, :method, :module_name
79
87
  end
80
88
 
81
- APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test)/
89
+ APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test)/.freeze
82
90
 
83
91
  # holder for an Array of Backtrace::Line instances
84
92
  attr_reader :lines
@@ -86,6 +94,8 @@ module Raven
86
94
  def self.parse(backtrace, opts = {})
87
95
  ruby_lines = backtrace.is_a?(Array) ? backtrace : backtrace.split(/\n\s*/)
88
96
 
97
+ ruby_lines = opts[:configuration].backtrace_cleanup_callback.call(ruby_lines) if opts[:configuration]&.backtrace_cleanup_callback
98
+
89
99
  filters = opts[:filters] || []
90
100
  filtered_lines = ruby_lines.to_a.map do |line|
91
101
  filters.reduce(line) do |nested_line, proc|
@@ -105,7 +115,7 @@ module Raven
105
115
  end
106
116
 
107
117
  def inspect
108
- "<Backtrace: " + lines.map(&inspect).join(", ") + ">"
118
+ "<Backtrace: " + lines.map(&:inspect).join(", ") + ">"
109
119
  end
110
120
 
111
121
  def to_s
data/lib/raven/base.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require 'raven/version'
2
+ require "raven/helpers/deprecation_helper"
3
+ require 'raven/core_ext/object/deep_dup'
2
4
  require 'raven/backtrace'
3
5
  require 'raven/breadcrumbs'
4
6
  require 'raven/processor'
@@ -12,14 +14,19 @@ require 'raven/configuration'
12
14
  require 'raven/context'
13
15
  require 'raven/client'
14
16
  require 'raven/event'
17
+ require 'raven/linecache'
15
18
  require 'raven/logger'
16
19
  require 'raven/interfaces/message'
17
20
  require 'raven/interfaces/exception'
18
21
  require 'raven/interfaces/single_exception'
19
22
  require 'raven/interfaces/stack_trace'
20
23
  require 'raven/interfaces/http'
24
+ require 'raven/transports'
25
+ require 'raven/transports/http'
21
26
  require 'raven/utils/deep_merge'
22
27
  require 'raven/utils/real_ip'
28
+ require 'raven/utils/request_id'
29
+ require 'raven/utils/exception_cause_chain'
23
30
  require 'raven/instance'
24
31
 
25
32
  require 'forwardable'
@@ -28,6 +35,9 @@ require 'English'
28
35
  module Raven
29
36
  AVAILABLE_INTEGRATIONS = %w(delayed_job railties sidekiq rack rack-timeout rake).freeze
30
37
 
38
+ class Error < StandardError
39
+ end
40
+
31
41
  class << self
32
42
  extend Forwardable
33
43
 
@@ -78,12 +88,13 @@ module Raven
78
88
 
79
89
  def load_integration(integration)
80
90
  require "raven/integrations/#{integration}"
81
- rescue Exception => error
82
- logger.warn "Unable to load raven/integrations/#{integration}: #{error}"
91
+ rescue Exception => e
92
+ logger.warn "Unable to load raven/integrations/#{integration}: #{e}"
83
93
  end
84
94
 
85
95
  def safely_prepend(module_name, opts = {})
86
96
  return if opts[:to].nil? || opts[:from].nil?
97
+
87
98
  if opts[:to].respond_to?(:prepend, true)
88
99
  opts[:to].send(:prepend, opts[:from].const_get(module_name))
89
100
  else
@@ -92,8 +103,10 @@ module Raven
92
103
  end
93
104
 
94
105
  def sys_command(command)
95
- result = `#{command}` rescue nil
96
- result.strip if result != "" && result
106
+ result = `#{command} 2>&1` rescue nil
107
+ return if result.nil? || result.empty? || ($CHILD_STATUS && $CHILD_STATUS.exitstatus != 0)
108
+
109
+ result.strip
97
110
  end
98
111
  end
99
112
  end
@@ -1,6 +1,7 @@
1
1
  module Raven
2
- module ActiveSupportBreadcrumbs
3
- class << self
2
+ module Breadcrumbs
3
+ module ActiveSupportLogger
4
+ class << self
4
5
  def add(name, started, _finished, _unique_id, data)
5
6
  Raven.breadcrumbs.record do |crumb|
6
7
  crumb.data = data
@@ -10,10 +11,15 @@ module Raven
10
11
  end
11
12
 
12
13
  def inject
13
- ActiveSupport::Notifications.subscribe(/.*/) do |name, started, finished, unique_id, data|
14
+ @subscriber = ::ActiveSupport::Notifications.subscribe(/.*/) do |name, started, finished, unique_id, data|
14
15
  add(name, started, finished, unique_id, data)
15
16
  end
16
17
  end
18
+
19
+ def detach
20
+ ::ActiveSupport::Notifications.unsubscribe(@subscriber)
21
+ end
22
+ end
17
23
  end
18
24
  end
19
25
  end
@@ -1,93 +1,3 @@
1
- require 'logger'
1
+ DeprecationHelper.deprecate_old_breadcrumbs_configuration(:sentry_logger)
2
2
 
3
- module Raven
4
- module BreadcrumbLogger
5
- LEVELS = {
6
- ::Logger::DEBUG => 'debug',
7
- ::Logger::INFO => 'info',
8
- ::Logger::WARN => 'warn',
9
- ::Logger::ERROR => 'error',
10
- ::Logger::FATAL => 'fatal'
11
- }.freeze
12
-
13
- EXC_FORMAT = /^([a-zA-Z0-9]+)\:\s(.*)$/
14
-
15
- def self.parse_exception(message)
16
- lines = message.split(/\n\s*/)
17
- # TODO: wat
18
- return nil unless lines.length > 2
19
-
20
- match = lines[0].match(EXC_FORMAT)
21
- return nil unless match
22
-
23
- _, type, value = match.to_a
24
- [type, value]
25
- end
26
-
27
- def add(*args)
28
- add_breadcrumb(*args)
29
- super
30
- end
31
-
32
- def add_breadcrumb(severity, message = nil, progname = nil)
33
- message = progname if message.nil? # see Ruby's Logger docs for why
34
- return if ignored_logger?(progname)
35
- return if message.nil? || message == ""
36
-
37
- # some loggers will add leading/trailing space as they (incorrectly, mind you)
38
- # think of logging as a shortcut to std{out,err}
39
- message = message.strip
40
-
41
- last_crumb = Raven.breadcrumbs.peek
42
- # try to avoid dupes from logger broadcasts
43
- if last_crumb.nil? || last_crumb.message != message
44
- error = Raven::BreadcrumbLogger.parse_exception(message)
45
- # TODO(dcramer): we need to filter out the "currently captured error"
46
- if error
47
- Raven.breadcrumbs.record do |crumb|
48
- crumb.level = Raven::BreadcrumbLogger::LEVELS.fetch(severity, nil)
49
- crumb.category = progname || 'error'
50
- crumb.type = 'error'
51
- crumb.data = {
52
- :type => error[0],
53
- :value => error[1]
54
- }
55
- end
56
- else
57
- Raven.breadcrumbs.record do |crumb|
58
- crumb.level = Raven::BreadcrumbLogger::LEVELS.fetch(severity, nil)
59
- crumb.category = progname || 'logger'
60
- crumb.message = message
61
- end
62
- end
63
- end
64
- end
65
-
66
- private
67
-
68
- def ignored_logger?(progname)
69
- progname == "sentry" ||
70
- Raven.configuration.exclude_loggers.include?(progname)
71
- end
72
- end
73
- module OldBreadcrumbLogger
74
- def self.included(base)
75
- base.class_eval do
76
- include Raven::BreadcrumbLogger
77
- alias_method :add_without_raven, :add
78
- alias_method :add, :add_with_raven
79
- end
80
- end
81
-
82
- def add_with_raven(*args)
83
- add_breadcrumb(*args)
84
- add_without_raven(*args)
85
- end
86
- end
87
- end
88
-
89
- Raven.safely_prepend(
90
- "BreadcrumbLogger",
91
- :from => Raven,
92
- :to => ::Logger
93
- )
3
+ require "raven/breadcrumbs/sentry_logger"
@@ -0,0 +1,73 @@
1
+ require 'logger'
2
+
3
+ module Raven
4
+ module Breadcrumbs
5
+ module SentryLogger
6
+ LEVELS = {
7
+ ::Logger::DEBUG => 'debug',
8
+ ::Logger::INFO => 'info',
9
+ ::Logger::WARN => 'warn',
10
+ ::Logger::ERROR => 'error',
11
+ ::Logger::FATAL => 'fatal'
12
+ }.freeze
13
+
14
+ def add(*args)
15
+ add_breadcrumb(*args)
16
+ super
17
+ end
18
+
19
+ def add_breadcrumb(severity, message = nil, progname = nil)
20
+ message = progname if message.nil? # see Ruby's Logger docs for why
21
+ return if ignored_logger?(progname)
22
+ return if message.nil? || message == ""
23
+
24
+ # some loggers will add leading/trailing space as they (incorrectly, mind you)
25
+ # think of logging as a shortcut to std{out,err}
26
+ message = message.to_s.strip
27
+
28
+ last_crumb = Raven.breadcrumbs.peek
29
+ # try to avoid dupes from logger broadcasts
30
+ if last_crumb.nil? || last_crumb.message != message
31
+ Raven.breadcrumbs.record do |crumb|
32
+ crumb.level = Raven::Breadcrumbs::SentryLogger::LEVELS.fetch(severity, nil)
33
+ crumb.category = progname || 'logger'
34
+ crumb.message = message
35
+ crumb.type =
36
+ if severity >= 3
37
+ "error"
38
+ else
39
+ crumb.level
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def ignored_logger?(progname)
48
+ progname == "sentry" ||
49
+ Raven.configuration.exclude_loggers.include?(progname)
50
+ end
51
+ end
52
+ module OldBreadcrumbsSentryLogger
53
+ def self.included(base)
54
+ base.class_eval do
55
+ include Raven::Breadcrumbs::SentryLogger
56
+ alias_method :add_without_raven, :add
57
+ alias_method :add, :add_with_raven
58
+ end
59
+ end
60
+
61
+ def add_with_raven(*args)
62
+ add_breadcrumb(*args)
63
+ add_without_raven(*args)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ Raven.safely_prepend(
70
+ "Breadcrumbs::SentryLogger",
71
+ :from => Raven,
72
+ :to => ::Logger
73
+ )
@@ -28,6 +28,8 @@ module Raven
28
28
  class BreadcrumbBuffer
29
29
  include Enumerable
30
30
 
31
+ attr_accessor :buffer
32
+
31
33
  def self.current
32
34
  Thread.current[:sentry_breadcrumbs] ||= new
33
35
  end
@@ -62,7 +64,7 @@ module Raven
62
64
  end
63
65
 
64
66
  def empty?
65
- !members.any?
67
+ members.none?
66
68
  end
67
69
 
68
70
  def to_hash