sentry-raven 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.craft.yml +15 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
  4. data/.github/pull_request_template.md +16 -0
  5. data/.github/workflows/test.yml +92 -0
  6. data/.github/workflows/zeus_upload.yml +32 -0
  7. data/.gitignore +3 -0
  8. data/.rubocop.yml +50 -12
  9. data/.scripts/bump-version.sh +9 -0
  10. data/{changelog.md → CHANGELOG.md} +147 -1
  11. data/CONTRIBUTING.md +71 -0
  12. data/Gemfile +20 -25
  13. data/README.md +26 -16
  14. data/lib/raven/backtrace.rb +9 -5
  15. data/lib/raven/base.rb +6 -2
  16. data/lib/raven/breadcrumbs.rb +1 -1
  17. data/lib/raven/breadcrumbs/{activesupport.rb → active_support_logger.rb} +9 -3
  18. data/lib/raven/breadcrumbs/logger.rb +2 -92
  19. data/lib/raven/breadcrumbs/sentry_logger.rb +73 -0
  20. data/lib/raven/cli.rb +10 -21
  21. data/lib/raven/client.rb +9 -4
  22. data/lib/raven/configuration.rb +86 -10
  23. data/lib/raven/context.rb +13 -8
  24. data/lib/raven/core_ext/object/deep_dup.rb +57 -0
  25. data/lib/raven/core_ext/object/duplicable.rb +153 -0
  26. data/lib/raven/event.rb +27 -15
  27. data/lib/raven/helpers/deprecation_helper.rb +17 -0
  28. data/lib/raven/instance.rb +9 -4
  29. data/lib/raven/integrations/delayed_job.rb +13 -14
  30. data/lib/raven/integrations/rack-timeout.rb +7 -4
  31. data/lib/raven/integrations/rack.rb +3 -2
  32. data/lib/raven/integrations/rails.rb +13 -3
  33. data/lib/raven/integrations/rails/active_job.rb +6 -4
  34. data/lib/raven/integrations/rails/backtrace_cleaner.rb +29 -0
  35. data/lib/raven/integrations/rails/overrides/debug_exceptions_catcher.rb +2 -2
  36. data/lib/raven/integrations/sidekiq.rb +4 -78
  37. data/lib/raven/integrations/sidekiq/cleanup_middleware.rb +13 -0
  38. data/lib/raven/integrations/sidekiq/context_filter.rb +42 -0
  39. data/lib/raven/integrations/sidekiq/error_handler.rb +38 -0
  40. data/lib/raven/interface.rb +2 -2
  41. data/lib/raven/interfaces/stack_trace.rb +1 -1
  42. data/lib/raven/linecache.rb +5 -2
  43. data/lib/raven/logger.rb +3 -2
  44. data/lib/raven/processor/cookies.rb +16 -6
  45. data/lib/raven/processor/post_data.rb +2 -0
  46. data/lib/raven/processor/removecircularreferences.rb +3 -1
  47. data/lib/raven/processor/sanitizedata.rb +65 -17
  48. data/lib/raven/processor/utf8conversion.rb +2 -0
  49. data/lib/raven/transports.rb +4 -0
  50. data/lib/raven/transports/http.rb +5 -5
  51. data/lib/raven/utils/exception_cause_chain.rb +1 -0
  52. data/lib/raven/utils/real_ip.rb +1 -1
  53. data/lib/raven/version.rb +2 -2
  54. data/lib/sentry-raven-without-integrations.rb +6 -1
  55. data/lib/sentry_raven_without_integrations.rb +1 -0
  56. metadata +20 -5
  57. data/.travis.yml +0 -43
@@ -0,0 +1,71 @@
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
+ # Contributing
9
+
10
+ You can contribute this project in the following ways:
11
+
12
+ - File a [bug report] or propose a feature
13
+ - Open a PR for bug fixes or implementing requested features
14
+ - Give feedback to opened issues/pull requests
15
+ - Test the latest version - `gem 'sentry-raven', github: 'getsentry/raven-ruby'`
16
+ - Contribute documentation in the [document repo]
17
+
18
+
19
+ And if you have any questions, please feel free to reach out on [Discord].
20
+
21
+
22
+ [bug report]: https://github.com/getsentry/raven-ruby/issues/new?template=bug_report.md
23
+ [document repo]: https://github.com/getsentry/sentry-docs
24
+ [Discord]: https://discord.gg/Ww9hbqr
25
+
26
+ ## How To Contribute
27
+
28
+ ### Running Tests
29
+
30
+ #### RAILS_VERSION
31
+
32
+ Because this SDK supports multiple versions of Rails, or even without Rails, you might want to run your test against different versions of Rails.
33
+
34
+ You can do this by changing the `RAILS_VERSION` environment variable:
35
+
36
+
37
+ ```
38
+ $ echo RAILS_VERSION=6.0
39
+ $ bundle update # this is necessary if you're switching between Rails versions
40
+ $ bundle exec rake
41
+ ```
42
+
43
+ If not specified, it runs tests against `Rails 5.2`.
44
+
45
+ And if you don't want to run the Rails related test cases, you can use `RAILS_VERSION=0`
46
+
47
+ ```
48
+ $ RAILS_VERSION=0 bundle exec rake # runs without Rails related test cases
49
+ ```
50
+
51
+ ### Testing Your Change Against Example Rails Apps
52
+
53
+ We have a few example apps for different Rails versions under the `/examples` folder. You can use them to perform an end-to-end testing on your changes (just remember to change the DSN to your project's).
54
+
55
+ At this moment, we recommend testing against the [Rails 6 example](https://github.com/getsentry/raven-ruby/tree/master/examples/rails-6.0) first. Please read its readme to see what kind of testing you can perform with it.
56
+
57
+
58
+ ## Making a release
59
+
60
+ Install and use `craft`: https://github.com/getsentry/craft
61
+
62
+ Make sure the `CHANGELOG.md` is update and latest `master` contains all changes.
63
+
64
+ Run:
65
+
66
+ ```bash
67
+ craft prepare x.x.x
68
+ ```
69
+
70
+ Where `x.x.x` stands for the version you want to release.
71
+ Afterwards reach out to an employee of Sentry, they will cut a release by running the `publish` process of `craft`.
data/Gemfile CHANGED
@@ -2,37 +2,32 @@ source "https://rubygems.org/"
2
2
 
3
3
  gemspec
4
4
 
5
- if ENV["RAILS_VERSION"] && (ENV["RAILS_VERSION"].to_i == 4)
6
- gem "rails", "< 5"
7
- gem "rspec-rails", "> 3"
8
- elsif ENV["RAILS_VERSION"] && (ENV["RAILS_VERSION"].to_i == 0)
9
- # no-op. No Rails.
10
- else
11
- gem "rails", "< 6"
12
- gem "rspec-rails", "> 3"
13
- end
5
+ rails_version = ENV["RAILS_VERSION"]
6
+ rails_version = "5.2" if rails_version.nil?
14
7
 
15
- if RUBY_VERSION < '2.0'
16
- gem "mime-types", "< 3.0.0"
17
- gem "nokogiri", "~> 1.6.8"
18
- gem "rack", "~> 1.6.8"
19
- gem "sidekiq", "< 3.2"
20
- gem "rack-timeout", "0.3.0"
21
- else
22
- gem "rack"
23
- gem "sidekiq"
24
- gem "rack-timeout"
8
+ if rails_version.to_f != 0
9
+ gem "rails", "~> #{rails_version}"
10
+ gem "rspec-rails", "~> 4.0"
25
11
  end
12
+
13
+ gem "sidekiq"
14
+
15
+ gem "rack"
16
+ gem "rack-timeout"
17
+
26
18
  gem "pry"
27
- gem "pry-coolline"
28
19
  gem "benchmark-ips"
29
- gem "benchmark-ipsa" if RUBY_VERSION > '2.0'
20
+ gem "benchmark_driver"
21
+ gem "benchmark-ipsa"
22
+ gem "benchmark-memory"
30
23
  gem "ruby-prof", platform: :mri
31
24
  gem "rake", "> 12"
32
- gem "rubocop", "~> 0.41.1" # Last version that supported 1.9, upgrade to 0.50 after we drop 1.9
33
- gem "rspec", "> 3"
34
- gem "capybara" # rspec system tests
25
+ gem "rubocop", "~> 0.81.0"
26
+ gem "rspec", "~> 3.9.0"
27
+ gem "capybara", "~> 3.15.0" # rspec system tests
35
28
  gem "puma" # rspec system tests
36
29
 
37
30
  gem "timecop"
38
- gem "test-unit", platform: :mri if RUBY_VERSION > '2.2'
31
+ gem "test-unit"
32
+ gem "simplecov"
33
+ gem "codecov"
data/README.md CHANGED
@@ -8,7 +8,8 @@
8
8
  # Raven-Ruby, the Ruby Client for Sentry
9
9
 
10
10
  [![Gem Version](https://img.shields.io/gem/v/sentry-raven.svg)](https://rubygems.org/gems/sentry-raven)
11
- [![Build Status](https://img.shields.io/travis/getsentry/raven-ruby/master.svg)](https://travis-ci.org/getsentry/raven-ruby)
11
+ ![Build Status](https://github.com/getsentry/raven-ruby/workflows/Test/badge.svg)
12
+ [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/raven-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/raven-ruby/branch/master)
12
13
  [![Gem](https://img.shields.io/gem/dt/sentry-raven.svg)](https://rubygems.org/gems/sentry-raven/)
13
14
  [![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)
14
15
 
@@ -19,7 +20,7 @@ The official Ruby-language client and integration layer for the [Sentry](https:/
19
20
 
20
21
  ## Requirements
21
22
 
22
- 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).
23
+ 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.
23
24
 
24
25
  ## Getting Started
25
26
 
@@ -29,7 +30,7 @@ We test on Ruby 2.3, 2.4, 2.5, 2.6 and 2.7 at the latest patchlevel/teeny versio
29
30
  gem "sentry-raven"
30
31
  ```
31
32
 
32
- ### Raven only runs when SENTRY_DSN is set
33
+ ### Raven only runs when Sentry DSN is set
33
34
 
34
35
  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!
35
36
 
@@ -38,7 +39,7 @@ Raven will capture and send exceptions to the Sentry server whenever its DSN is
38
39
  export SENTRY_DSN=http://public@example.com/project-id
39
40
  ```
40
41
  ```ruby
41
- # Or you can configure the client in the code (not recommended - keep your DSN secret!)
42
+ # Or you can configure the client in the code.
42
43
  Raven.configure do |config|
43
44
  config.dsn = 'http://public@example.com/project-id'
44
45
  end
@@ -48,11 +49,11 @@ end
48
49
 
49
50
  **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).
50
51
 
51
- 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/)
52
+ 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/config/)
52
53
 
53
54
  ### Usage
54
55
 
55
- **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.
56
+ **If you use Rails, you're already done - no more configuration required!** Check [Integrations](https://docs.sentry.io/platforms/ruby/integrations/) for more details on other gems Sentry integrates with automatically.
56
57
 
57
58
  Otherwise, Raven supports two methods of capturing exceptions:
58
59
 
@@ -104,26 +105,35 @@ end
104
105
  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.
105
106
 
106
107
  ```ruby
107
- config.transport_failure_callback = lambda { |event|
108
- AdminMailer.email_admins("Oh god, it's on fire!", event).deliver_later
108
+ config.transport_failure_callback = lambda { |event, error|
109
+ AdminMailer.email_admins("Oh god, it's on fire because #{error.message}!", event).deliver_later
109
110
  }
110
111
  ```
111
112
 
112
113
  #### Context
113
114
 
114
- 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.
115
-
116
- There are three primary methods for providing request context:
115
+ 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:
117
116
 
118
117
  ```ruby
119
- # bind the logged in user
120
118
  Raven.user_context email: 'foo@example.com'
121
119
 
122
- # tag the request with something interesting
123
- Raven.tags_context interesting: 'yes'
120
+ Raven.tags.merge!(interesting: 'yes')
121
+
122
+ Raven.extra.merge!(additional_info: 'foo')
123
+ ```
124
+
125
+ You can also use `tags_context` and `extra_context` to provide scoped information:
126
+
127
+ ```ruby
128
+ Raven.tags_context(interesting: 'yes') do
129
+ # the `interesting: 'yes'` tag will only present in the requests sent inside the block
130
+ Raven.capture_exception(exception)
131
+ end
124
132
 
125
- # provide a bit of additional context
126
- Raven.extra_context happiness: 'very'
133
+ Raven.extra_context(additional_info: 'foo') do
134
+ # same as above, the `additional_info` will only present in this request
135
+ Raven.capture_exception(exception)
136
+ end
127
137
  ```
128
138
 
129
139
  For more information, see [Context](https://docs.sentry.io/clients/ruby/context/).
@@ -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,16 +7,16 @@ module Raven
5
7
  class Backtrace
6
8
  # Handles backtrace parsing line by line
7
9
  class Line
8
- RB_EXTENSION = ".rb".freeze
10
+ RB_EXTENSION = ".rb"
9
11
  # regexp (optional leading X: on windows, or JRuby9000 class-prefix)
10
12
  RUBY_INPUT_FORMAT = /
11
13
  ^ \s* (?: [a-zA-Z]: | uri:classloader: )? ([^:]+ | <.*>):
12
14
  (\d+)
13
15
  (?: :in \s `([^']+)')?$
14
- /x
16
+ /x.freeze
15
17
 
16
18
  # org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
17
- JAVA_INPUT_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/
19
+ JAVA_INPUT_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/.freeze
18
20
 
19
21
  # The file portion of the line (such as app/models/user.rb)
20
22
  attr_reader :file
@@ -74,7 +76,7 @@ module Raven
74
76
 
75
77
  def self.in_app_pattern
76
78
  @in_app_pattern ||= begin
77
- project_root = Raven.configuration.project_root && Raven.configuration.project_root.to_s
79
+ project_root = Raven.configuration.project_root&.to_s
78
80
  Regexp.new("^(#{project_root}/)?#{Raven.configuration.app_dirs_pattern || APP_DIRS_PATTERN}")
79
81
  end
80
82
  end
@@ -84,7 +86,7 @@ module Raven
84
86
  attr_writer :file, :number, :method, :module_name
85
87
  end
86
88
 
87
- APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test)/
89
+ APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test)/.freeze
88
90
 
89
91
  # holder for an Array of Backtrace::Line instances
90
92
  attr_reader :lines
@@ -92,6 +94,8 @@ module Raven
92
94
  def self.parse(backtrace, opts = {})
93
95
  ruby_lines = backtrace.is_a?(Array) ? backtrace : backtrace.split(/\n\s*/)
94
96
 
97
+ ruby_lines = opts[:configuration].backtrace_cleanup_callback.call(ruby_lines) if opts[:configuration]&.backtrace_cleanup_callback
98
+
95
99
  filters = opts[:filters] || []
96
100
  filtered_lines = ruby_lines.to_a.map do |line|
97
101
  filters.reduce(line) do |nested_line, proc|
@@ -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'
@@ -85,12 +87,13 @@ module Raven
85
87
 
86
88
  def load_integration(integration)
87
89
  require "raven/integrations/#{integration}"
88
- rescue Exception => error
89
- logger.warn "Unable to load raven/integrations/#{integration}: #{error}"
90
+ rescue Exception => e
91
+ logger.warn "Unable to load raven/integrations/#{integration}: #{e}"
90
92
  end
91
93
 
92
94
  def safely_prepend(module_name, opts = {})
93
95
  return if opts[:to].nil? || opts[:from].nil?
96
+
94
97
  if opts[:to].respond_to?(:prepend, true)
95
98
  opts[:to].send(:prepend, opts[:from].const_get(module_name))
96
99
  else
@@ -101,6 +104,7 @@ module Raven
101
104
  def sys_command(command)
102
105
  result = `#{command} 2>&1` rescue nil
103
106
  return if result.nil? || result.empty? || ($CHILD_STATUS && $CHILD_STATUS.exitstatus != 0)
107
+
104
108
  result.strip
105
109
  end
106
110
  end
@@ -64,7 +64,7 @@ module Raven
64
64
  end
65
65
 
66
66
  def empty?
67
- !members.any?
67
+ members.none?
68
68
  end
69
69
 
70
70
  def to_hash
@@ -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.to_s.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
+ )