rollbar 2.10.0 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +7 -2
  3. data/CHANGELOG.md +20 -0
  4. data/README.md +73 -16
  5. data/docs/configuration.md +10 -0
  6. data/gemfiles/rails30.gemfile +2 -0
  7. data/gemfiles/rails31.gemfile +2 -0
  8. data/gemfiles/rails32.gemfile +2 -0
  9. data/gemfiles/rails40.gemfile +2 -0
  10. data/gemfiles/rails41.gemfile +2 -0
  11. data/gemfiles/rails42.gemfile +2 -0
  12. data/gemfiles/rails50.gemfile +2 -0
  13. data/gemfiles/ruby_1_8_and_1_9_2.gemfile +43 -0
  14. data/lib/rollbar.rb +139 -353
  15. data/lib/rollbar/configuration.rb +4 -0
  16. data/lib/rollbar/item.rb +225 -0
  17. data/lib/rollbar/item/backtrace.rb +97 -0
  18. data/lib/rollbar/js.rb +0 -28
  19. data/lib/rollbar/language_support.rb +10 -0
  20. data/lib/rollbar/{js/middleware.rb → middleware/js.rb} +3 -4
  21. data/lib/rollbar/plugin.rb +63 -0
  22. data/lib/rollbar/plugins.rb +41 -0
  23. data/lib/rollbar/{active_job.rb → plugins/active_job.rb} +0 -0
  24. data/lib/rollbar/plugins/basic_socket.rb +16 -0
  25. data/lib/rollbar/plugins/delayed_job.rb +12 -0
  26. data/lib/rollbar/plugins/delayed_job/job_data.rb +16 -0
  27. data/lib/rollbar/{delayed_job.rb → plugins/delayed_job/plugin.rb} +1 -17
  28. data/lib/rollbar/plugins/goalie.rb +46 -0
  29. data/lib/rollbar/plugins/rack.rb +16 -0
  30. data/lib/rollbar/plugins/rails.rb +77 -0
  31. data/lib/rollbar/{rails → plugins/rails}/controller_methods.rb +0 -0
  32. data/lib/rollbar/plugins/rails/railtie30.rb +17 -0
  33. data/lib/rollbar/plugins/rails/railtie32.rb +18 -0
  34. data/lib/rollbar/plugins/rails/railtie_mixin.rb +33 -0
  35. data/lib/rollbar/plugins/rake.rb +45 -0
  36. data/lib/rollbar/plugins/sidekiq.rb +35 -0
  37. data/lib/rollbar/{sidekiq.rb → plugins/sidekiq/plugin.rb} +0 -18
  38. data/lib/rollbar/plugins/thread.rb +13 -0
  39. data/lib/rollbar/plugins/validations.rb +33 -0
  40. data/lib/rollbar/request_data_extractor.rb +30 -18
  41. data/lib/rollbar/scrubbers/params.rb +4 -2
  42. data/lib/rollbar/scrubbers/url.rb +30 -28
  43. data/lib/rollbar/util.rb +10 -0
  44. data/lib/rollbar/version.rb +1 -1
  45. data/spec/controllers/home_controller_spec.rb +4 -3
  46. data/spec/dummyapp/app/models/post.rb +9 -0
  47. data/spec/dummyapp/app/models/user.rb +2 -0
  48. data/spec/dummyapp/config/initializers/rollbar.rb +1 -0
  49. data/spec/fixtures/plugins/dummy1.rb +5 -0
  50. data/spec/fixtures/plugins/dummy2.rb +5 -0
  51. data/spec/rollbar/item_spec.rb +635 -0
  52. data/spec/rollbar/logger_proxy_spec.rb +4 -0
  53. data/spec/rollbar/{js/middleware_spec.rb → middleware/js_spec.rb} +32 -3
  54. data/spec/rollbar/plugin_spec.rb +147 -0
  55. data/spec/rollbar/{active_job_spec.rb → plugins/active_job_spec.rb} +0 -1
  56. data/spec/rollbar/{delayed_job → plugins/delayed_job}/job_data.rb +0 -0
  57. data/spec/rollbar/{delayed_job_spec.rb → plugins/delayed_job_spec.rb} +3 -6
  58. data/spec/rollbar/{middleware/rack/builder_spec.rb → plugins/rack_spec.rb} +2 -1
  59. data/spec/rollbar/{js/frameworks/rails_spec.rb → plugins/rails_js_spec.rb} +1 -1
  60. data/spec/rollbar/{rake_spec.rb → plugins/rake_spec.rb} +2 -1
  61. data/spec/rollbar/{sidekiq_spec.rb → plugins/sidekiq_spec.rb} +2 -1
  62. data/spec/rollbar/plugins/validations_spec.rb +43 -0
  63. data/spec/rollbar/plugins_spec.rb +68 -0
  64. data/spec/rollbar/request_data_extractor_spec.rb +56 -10
  65. data/spec/rollbar/scrubbers/params_spec.rb +13 -10
  66. data/spec/rollbar/scrubbers/url_spec.rb +17 -12
  67. data/spec/rollbar/sidekig/clear_scope_spec.rb +2 -1
  68. data/spec/rollbar/util_spec.rb +61 -0
  69. data/spec/rollbar_bc_spec.rb +10 -10
  70. data/spec/rollbar_spec.rb +57 -706
  71. data/spec/spec_helper.rb +8 -0
  72. data/spec/support/notifier_helpers.rb +1 -0
  73. data/spec/support/rollbar_api.rb +57 -0
  74. metadata +57 -33
  75. data/lib/rollbar/active_record_extension.rb +0 -14
  76. data/lib/rollbar/core_ext/basic_socket.rb +0 -7
  77. data/lib/rollbar/core_ext/thread.rb +0 -9
  78. data/lib/rollbar/goalie.rb +0 -33
  79. data/lib/rollbar/js/frameworks.rb +0 -6
  80. data/lib/rollbar/js/frameworks/rails.rb +0 -49
  81. data/lib/rollbar/js/version.rb +0 -5
  82. data/lib/rollbar/rack.rb +0 -9
  83. data/lib/rollbar/railtie.rb +0 -46
  84. data/lib/rollbar/rake.rb +0 -40
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a45a6459fbc4fdc48b10d24d8f789ac3dc6c712a
4
- data.tar.gz: a6391231fe97e651db01a382a214c3f9cf002310
3
+ metadata.gz: 548fb68e7c723f07871b11f17bd587b828d52d28
4
+ data.tar.gz: 8709dde8c12f7d291bc9511dc0749a9cba5376bd
5
5
  SHA512:
6
- metadata.gz: 75910ee630569144378fdc9bbb3039e514273e335b4b1fca19be9f02ad60158414e396a75e3ee01b05bc3053dd5efed95bb1a3a111357a03ee22c42a41539d69
7
- data.tar.gz: 45fe74d97b172e168127fac6478d9eeca7e155018a95cc4df7c01aa6823868156297fddedef3da6df93404532604f64d174c2ce28cf2a551dafccf977f3e1873
6
+ metadata.gz: ce5a7b20e794752c03d21b479867b0a445eeb905dc23980bad4840beffd010de2c3f884e60eec0a5e4fef019288a6cc498a574aaf5a5161c9c54c8824982ab5d
7
+ data.tar.gz: c71dab677825a633bed1dd7aefba302fb1f87ed0e78fa309ca5a0af31e574982c9cc4310967935b8acfe25bf7c361184ffb0afe10ba5f2998de9d337a43f5221
data/.travis.yml CHANGED
@@ -7,8 +7,6 @@ before_install:
7
7
  - gem update --system 2.1.11
8
8
  - gem --version
9
9
  rvm:
10
- - 1.8.7
11
- - 1.9.2
12
10
  - 1.9.3
13
11
  - 2.0.0
14
12
  - 2.1.0
@@ -32,6 +30,13 @@ gemfile:
32
30
  - gemfiles/rails42.gemfile
33
31
  - gemfiles/rails50.gemfile
34
32
  matrix:
33
+ include:
34
+ - rvm: 1.8.7
35
+ gemfile: gemfiles/ruby_1_8_and_1_9_2.gemfile
36
+ jdk: openjdk6
37
+ - rvm: 1.9.2
38
+ gemfile: gemfiles/ruby_1_8_and_1_9_2.gemfile
39
+ jdk: openjdk6
35
40
  allow_failures:
36
41
  - rvm: ruby-head
37
42
  - rvm: jruby-18mode
data/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Change Log
2
2
 
3
+ ## 2.11.0
4
+
5
+ New features:
6
+
7
+ - Rollbar.js support wit SecureHeaders 2.0. See [#448](https://github.com/rollbar/rollbar-gem/pull/448).
8
+ - Inject extensions in ActiveModel::Validations instead of ActiveRecord::Base. See [#445](https://github.com/rollbar/rollbar-gem/pull/445).
9
+
10
+ Bug fixes:
11
+
12
+ - Fix URL scrubbing and change to a functional object. See [#454](https://github.com/rollbar/rollbar-gem/pull/454).
13
+ - Allow any argument for BasicSocket#as_json. See [#455](https://github.com/rollbar/rollbar-gem/pull/455).
14
+ - Retry request on network timeouts. See [#453](https://github.com/rollbar/rollbar-gem/pull/453).
15
+
16
+ Refactors and others:
17
+
18
+ - Refactor Item payload building. See [#452](https://github.com/rollbar/rollbar-gem/pull/454).
19
+ - Mock the requests to Rollbar API. See [#450](https://github.com/rollbar/rollbar-gem/pull/450).
20
+ - Add plugins architecture. See [#438](https://github.com/rollbar/rollbar-gem/pull/438).
21
+ - Add TOC for README.md. See [#444](https://github.com/rollbar/rollbar-gem/pull/444).
22
+
3
23
  ## 2.10.0
4
24
 
5
25
  New features:
data/README.md CHANGED
@@ -1,11 +1,68 @@
1
- # Rollbar notifier for Ruby [![Build Status](https://api.travis-ci.org/rollbar/rollbar-gem.svg?branch=v2.10.0)](https://travis-ci.org/rollbar/rollbar-gem/branches)
1
+ # Rollbar [![Build Status](https://api.travis-ci.org/rollbar/rollbar-gem.svg?branch=v2.11.0)](https://travis-ci.org/rollbar/rollbar-gem/branches)
2
2
 
3
3
  <!-- RemoveNext -->
4
4
  [Rollbar](https://rollbar.com) is an error tracking service for Ruby and other languages. The Rollbar service will alert you of problems with your code and help you understand them in a ways never possible before. We love it and we hope you will too.
5
5
 
6
6
  This is the Ruby library for Rollbar. It will instrument many kinds of Ruby applications automatically at the framework level. You can also make direct calls to send exceptions and messages to Rollbar.
7
7
 
8
- <!-- Sub:[TOC] -->
8
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
9
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
10
+ ## Table of Contents
11
+
12
+ - [Getting Started](#getting-started)
13
+ - [Rails](#rails)
14
+ - [Rack](#rack)
15
+ - [Plain Ruby](#plain-ruby)
16
+ - [Integration with Rollbar.js](#integration-with-rollbarjs)
17
+ - [Test your installation](#test-your-installation)
18
+ - [Usage](#usage)
19
+ - [Uncaught exceptions](#uncaught-exceptions)
20
+ - [Caught exceptions and messages](#caught-exceptions-and-messages)
21
+ - [Reporting form validation errors](#reporting-form-validation-errors)
22
+ - [Advanced usage](#advanced-usage)
23
+ - [Person tracking](#person-tracking)
24
+ - [Person tracking with Rack applications](#person-tracking-with-rack-applications)
25
+ - [Special note about reporting within a request](#special-note-about-reporting-within-a-request)
26
+ - [Data sanitization (scrubbing)](#data-sanitization-scrubbing)
27
+ - [Including additional runtime data](#including-additional-runtime-data)
28
+ - [Exception level filters](#exception-level-filters)
29
+ - [Before process hook](#before-process-hook)
30
+ - [Transform hook](#transform-hook)
31
+ - [The Scope](#the-scope)
32
+ - [Silencing exceptions at runtime](#silencing-exceptions-at-runtime)
33
+ - [Sending backtrace without rescued exceptions](#sending-backtrace-without-rescued-exceptions)
34
+ - [ActiveJob integration](#activejob-integration)
35
+ - [Delayed::Job](#delayedjob)
36
+ - [Asynchronous reporting](#asynchronous-reporting)
37
+ - [girl_friday](#girl_friday)
38
+ - [sucker_punch](#sucker_punch)
39
+ - [Sidekiq](#sidekiq)
40
+ - [Resque](#resque)
41
+ - [DelayedJob](#delayedjob)
42
+ - [Threading](#threading)
43
+ - [Other handlers](#other-handlers)
44
+ - [Failover handlers](#failover-handlers)
45
+ - [Logger interface](#logger-interface)
46
+ - [Using with rollbar-agent](#using-with-rollbar-agent)
47
+ - [Rails booting process](#rails-booting-process)
48
+ - [Rails runner command](#rails-runner-command)
49
+ - [Deploy Tracking with Capistrano](#deploy-tracking-with-capistrano)
50
+ - [Capistrano 3](#capistrano-3)
51
+ - [Capistrano 2](#capistrano-2)
52
+ - [Counting specific gems as in-project code](#counting-specific-gems-as-in-project-code)
53
+ - [Goalie](#goalie)
54
+ - [Resque](#resque-1)
55
+ - [SSL](#ssl)
56
+ - [Using with Zeus](#using-with-zeus)
57
+ - [Configuration options](#configuration-options)
58
+ - [Backwards Compatibility](#backwards-compatibility)
59
+ - [Known Issues](#known-issues)
60
+ - [Supported Language/Framework Versions](#supported-languageframework-versions)
61
+ - [Help / Support](#help--support)
62
+ - [Contributing](#contributing)
63
+
64
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
65
+
9
66
 
10
67
  ## Getting Started
11
68
 
@@ -31,7 +88,7 @@ gem 'oj', '~> 2.12.14'
31
88
 
32
89
  and then `bundle install` again.
33
90
 
34
- ### If using Rails
91
+ ### Rails
35
92
 
36
93
  Run the following command from your Rails root:
37
94
 
@@ -62,7 +119,7 @@ $ heroku config:add ROLLBAR_ACCESS_TOKEN=POST_SERVER_ITEM_ACCESS_TOKEN
62
119
  That's all you need to use Rollbar with Rails.
63
120
 
64
121
 
65
- ### If using Rack
122
+ ### Rack
66
123
 
67
124
  Initialize Rollbar with your access token somewhere during startup:
68
125
 
@@ -99,7 +156,7 @@ class MyApp < Sinatra::Base
99
156
  end
100
157
  ```
101
158
 
102
- ### If using Plain Ruby
159
+ ### Plain Ruby
103
160
 
104
161
  Rollbar isn't dependent on Rack or Rails for most of its functionality. In a regular script, assuming you've
105
162
  installed the rollbar gem:
@@ -561,7 +618,7 @@ end
561
618
 
562
619
  If you need to customize the reporting write your own `rescue_from` handler instead of using the `Rollbar::ActiveJob` module.
563
620
 
564
- ## Delayed::Job integration
621
+ ## Delayed::Job
565
622
 
566
623
  If `delayed_job` is defined, Rollbar will automatically install a plugin that reports any uncaught exceptions that occur in jobs.
567
624
 
@@ -590,7 +647,7 @@ Only versions >= 3.0 of delayed_job are supported.
590
647
 
591
648
  By default, all messages are reported synchronously. You can enable asynchronous reporting with [girl_friday](https://github.com/mperham/girl_friday), [sucker_punch](https://github.com/brandonhilkert/sucker_punch), [Sidekiq](https://github.com/mperham/sidekiq), [Resque](https://github.com/resque/resque), [DelayedJob](https://github.com/collectiveidea/delayed_job) or using threading.
592
649
 
593
- ### Using girl_friday
650
+ ### girl_friday
594
651
 
595
652
  Add the following in ```config/initializers/rollbar.rb```:
596
653
 
@@ -600,7 +657,7 @@ config.use_async = true
600
657
 
601
658
  Asynchronous reporting falls back to Threading if girl_friday is not installed.
602
659
 
603
- ### Using sucker_punch
660
+ ### sucker_punch
604
661
 
605
662
  Add the following in ```config/initializers/rollbar.rb```:
606
663
 
@@ -608,7 +665,7 @@ Add the following in ```config/initializers/rollbar.rb```:
608
665
  config.use_sucker_punch
609
666
  ```
610
667
 
611
- ### Using Sidekiq
668
+ ### Sidekiq
612
669
 
613
670
  Add the following in ```config/initializers/rollbar.rb```:
614
671
 
@@ -641,7 +698,7 @@ For every errored job a new report will be sent to Rollbar API, also for errored
641
698
  config.sidekiq_threshold = 3 # Start reporting from 3 retries jobs
642
699
  ```
643
700
 
644
- ### Using Resque
701
+ ### Resque
645
702
 
646
703
  Add the following in ```config/initializers/rollbar.rb```:
647
704
 
@@ -661,7 +718,7 @@ Now you can just start a new Resque worker processing jobs in that queue:
661
718
  $ QUEUE=my_queue bundle exec resque:work
662
719
  ```
663
720
 
664
- ### Using DelayedJob
721
+ ### DelayedJob
665
722
 
666
723
  Add the following in ```config/initializers/rollbar.rb```:
667
724
 
@@ -669,7 +726,7 @@ Add the following in ```config/initializers/rollbar.rb```:
669
726
  config.use_delayed_job
670
727
  ```
671
728
 
672
- ### Using threading
729
+ ### Threading
673
730
 
674
731
  Add the following in ```config/initializers/rollbar.rb```:
675
732
 
@@ -677,7 +734,7 @@ Add the following in ```config/initializers/rollbar.rb```:
677
734
  config.use_thread
678
735
  ```
679
736
 
680
- ### Using another handler
737
+ ### Other handlers
681
738
 
682
739
  You can supply your own handler using ```config.async_handler```. The object to set for `async_handler` should respond to `#call` and receive the payload. The handler should schedule the payload for later processing (i.e. with a delayed_job, in a resque queue, etc.) and should itself return immediately. For example:
683
740
 
@@ -690,7 +747,7 @@ config.async_handler = Proc.new { |payload|
690
747
 
691
748
  Make sure you pass ```payload``` to ```Rollbar.process_from_async_handler``` in your own implementation.
692
749
 
693
- ## Failover handlers
750
+ ### Failover handlers
694
751
 
695
752
  If you are using `async_handler` to process asynchronous the error it's possible that the handler fails before it calls `Rollbar.process_payload`. For example, for the Resque handler, the Redis connection could fail so the job is finally not processed.
696
753
 
@@ -831,12 +888,12 @@ Rollbar.configure do |config |
831
888
  end
832
889
  ```
833
890
 
834
- ## Using with Goalie
891
+ ## Goalie
835
892
 
836
893
  If you're using [Goalie](https://github.com/obvio171/goalie) for custom error pages, you may need to explicitly add ```require 'goalie'``` to ```config/application.rb``` (in addition to ```require 'goalie/rails'```) so that the monkeypatch will work. (This will be obvious if it is needed because your app won't start up: you'll see a cryptic error message about ```Goalie::CustomErrorPages.render_exception``` not being defined.)
837
894
 
838
895
 
839
- ## Using with Resque
896
+ ## Resque
840
897
 
841
898
  Check out [resque-rollbar](https://github.com/dimko/resque-rollbar) for using Rollbar as a failure backend for Resque.
842
899
 
@@ -180,12 +180,22 @@ Rollbar load the traces before sending them.
180
180
  Set to `false` to skip automatic bundling of job metadata like queue, job class
181
181
  name, and job options.
182
182
 
183
+ ### open_timeout
184
+
185
+ **Default** `3`
186
+
183
187
  ### request_timeout
184
188
 
185
189
  **Default** `3`
186
190
 
187
191
  Set the request timeout for sending POST data to Rollbar.
188
192
 
193
+ ### net_retries
194
+
195
+ **Default** `3`
196
+
197
+ Sets the number of retries cause timeouts on the POST request.
198
+
189
199
  ### root
190
200
 
191
201
  Set the server root, all stack frames outside that root are considered
@@ -40,4 +40,6 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0')
40
40
  gem 'mime-types', '< 3.0'
41
41
  end
42
42
 
43
+ gem 'webmock', :require => false
44
+
43
45
  gemspec :path => '../'
@@ -38,4 +38,6 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0')
38
38
  gem 'mime-types', '< 3.0'
39
39
  end
40
40
 
41
+ gem 'webmock', :require => false
42
+
41
43
  gemspec :path => "../"
@@ -40,4 +40,6 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0')
40
40
  gem 'mime-types', '< 3.0'
41
41
  end
42
42
 
43
+ gem 'webmock', :require => false
44
+
43
45
  gemspec :path => "../"
@@ -40,4 +40,6 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0')
40
40
  gem 'mime-types', '< 3.0'
41
41
  end
42
42
 
43
+ gem 'webmock', :require => false
44
+
43
45
  gemspec :path => "../"
@@ -38,4 +38,6 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0')
38
38
  gem 'mime-types', '< 3.0'
39
39
  end
40
40
 
41
+ gem 'webmock', :require => false
42
+
41
43
  gemspec :path => "../"
@@ -38,4 +38,6 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0')
38
38
  gem 'mime-types', '< 3.0'
39
39
  end
40
40
 
41
+ gem 'webmock', :require => false
42
+
41
43
  gemspec :path => "../"
@@ -44,4 +44,6 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0')
44
44
  gem 'mime-types', '< 3.0'
45
45
  end
46
46
 
47
+ gem 'webmock', :require => false
48
+
47
49
  gemspec :path => '../'
@@ -0,0 +1,43 @@
1
+ require 'rubygems/version'
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ is_jruby = defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) && 'jruby' == RUBY_ENGINE)
6
+
7
+ gem 'sqlite3', :platform => [:ruby, :mswin, :mingw]
8
+ gem 'jruby-openssl', :platform => :jruby
9
+ gem 'activerecord-jdbcsqlite3-adapter', :platform => :jruby
10
+ gem 'appraisal', '= 1.0.2'
11
+ gem 'rubysl', '~> 2.0', :platform => :rbx
12
+ gem 'racc', :platform => :rbx
13
+ gem 'minitest', :platform => :rbx
14
+ gem 'rubysl-test-unit', :platform => :rbx
15
+ gem 'rubinius-developer_tools', :platform => :rbx
16
+ gem 'rails', '3.0.20'
17
+ gem 'hitimes', '< 1.2.2'
18
+ gem 'rake', '< 11'
19
+ gem 'rspec-rails', '>= 2.14.0'
20
+ gem 'celluloid', '< 0.17.0' if RUBY_VERSION == '1.9.2'
21
+
22
+ gem 'oj', '~> 2.12.14' unless is_jruby
23
+ gem 'sidekiq', '>= 2.13.0' if RUBY_VERSION != '1.8.7'
24
+
25
+ if RUBY_VERSION.start_with?('1.9')
26
+ gem 'sucker_punch', '~> 1.0'
27
+ elsif RUBY_VERSION.start_with?('2')
28
+ gem 'sucker_punch', '~> 2.0'
29
+ end
30
+
31
+ gem 'sinatra'
32
+ gem 'resque'
33
+ gem 'delayed_job', :require => false
34
+ gem 'redis'
35
+ gem 'database_cleaner', '~> 1.0.0'
36
+ gem 'genspec', '>= 0.2.8'
37
+ gem 'girl_friday', '>= 0.11.1'
38
+
39
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0')
40
+ gem 'mime-types', '< 3.0'
41
+ end
42
+
43
+ gemspec :path => '../'
data/lib/rollbar.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'net/protocol'
1
2
  require 'net/https'
2
3
  require 'socket'
3
4
  require 'thread'
@@ -10,23 +11,25 @@ rescue LoadError
10
11
  end
11
12
 
12
13
  require 'rollbar/version'
14
+ require 'rollbar/plugins'
13
15
  require 'rollbar/json'
14
16
  require 'rollbar/js'
15
17
  require 'rollbar/configuration'
18
+ require 'rollbar/item'
16
19
  require 'rollbar/encoding'
17
20
  require 'rollbar/logger_proxy'
18
21
  require 'rollbar/exception_reporter'
19
22
  require 'rollbar/util'
20
- require 'rollbar/railtie' if defined?(Rails::VERSION) && Rails::VERSION::MAJOR >= 3
21
23
  require 'rollbar/delay/girl_friday' if defined?(GirlFriday)
22
24
  require 'rollbar/delay/thread'
23
25
  require 'rollbar/truncation'
24
26
  require 'rollbar/exceptions'
25
27
  require 'rollbar/lazy_store'
28
+ require 'rollbar/language_support'
26
29
 
27
30
  module Rollbar
28
31
  PUBLIC_NOTIFIER_METHODS = %w(debug info warn warning error critical log logger
29
- process_payload process_from_async_handler scope send_failsafe log_info log_debug
32
+ process_item process_from_async_handler scope send_failsafe log_info log_debug
30
33
  log_warning log_error silenced)
31
34
 
32
35
  class Notifier
@@ -175,20 +178,20 @@ module Rollbar
175
178
  log('critical', *args)
176
179
  end
177
180
 
178
- def process_payload(payload)
181
+ def process_item(item)
179
182
  if configuration.write_to_file
180
183
  if configuration.use_async
181
184
  @file_semaphore.synchronize {
182
- write_payload(payload)
185
+ write_item(item)
183
186
  }
184
187
  else
185
- write_payload(payload)
188
+ write_item(item)
186
189
  end
187
190
  else
188
- send_payload(payload)
191
+ send_item(item)
189
192
  end
190
193
  rescue => e
191
- log_error("[Rollbar] Error processing the payload: #{e.class}, #{e.message}. Payload: #{payload.inspect}")
194
+ log_error("[Rollbar] Error processing the item: #{e.class}, #{e.message}. Item: #{item.payload.inspect}")
192
195
  raise e
193
196
  end
194
197
 
@@ -216,9 +219,13 @@ module Rollbar
216
219
  # Using Rollbar.silenced we avoid the above behavior but Sidekiq
217
220
  # will have a chance to retry the original job.
218
221
  def process_from_async_handler(payload)
222
+ payload = Rollbar::JSON.load(payload) if payload.is_a?(String)
223
+
224
+ item = Item.build_with(payload)
225
+
219
226
  Rollbar.silenced do
220
227
  begin
221
- process_payload(payload)
228
+ process_item(item)
222
229
  rescue => e
223
230
  report_internal_error(e)
224
231
 
@@ -227,13 +234,41 @@ module Rollbar
227
234
  end
228
235
  end
229
236
 
230
- def custom_data
231
- data = configuration.custom_data_method.call
232
- Rollbar::Util.deep_copy(data)
233
- rescue => e
234
- return {} if configuration.safely?
237
+ def send_failsafe(message, exception)
238
+ exception_reason = failsafe_reason(message, exception)
239
+
240
+ log_error "[Rollbar] Sending failsafe response due to #{exception_reason}"
241
+
242
+ body = failsafe_body(exception_reason)
243
+
244
+ failsafe_data = {
245
+ :level => 'error',
246
+ :environment => configuration.environment.to_s,
247
+ :body => {
248
+ :message => {
249
+ :body => body
250
+ }
251
+ },
252
+ :notifier => {
253
+ :name => 'rollbar-gem',
254
+ :version => VERSION
255
+ },
256
+ :internal => true,
257
+ :failsafe => true
258
+ }
235
259
 
236
- report_custom_data_error(e)
260
+ failsafe_payload = {
261
+ 'access_token' => configuration.access_token,
262
+ 'data' => failsafe_data
263
+ }
264
+
265
+ begin
266
+ schedule_item(Item.build_with(failsafe_payload))
267
+ rescue => e
268
+ log_error "[Rollbar] Error sending failsafe : #{e}"
269
+ end
270
+
271
+ failsafe_payload
237
272
  end
238
273
 
239
274
  private
@@ -309,22 +344,19 @@ module Rollbar
309
344
 
310
345
  def report(level, message, exception, extra)
311
346
  unless message || exception || extra
312
- log_error "[Rollbar] Tried to send a report with no message, exception or extra data."
347
+ log_error '[Rollbar] Tried to send a report with no message, exception or extra data.'
348
+
313
349
  return 'error'
314
350
  end
315
351
 
316
- payload = build_payload(level, message, exception, extra)
317
- data = payload['data']
352
+ item = build_item(level, message, exception, extra)
318
353
 
319
- if data[:person]
320
- person_id = data[:person][configuration.person_id_method.to_sym]
321
- return 'ignored' if configuration.ignored_person_ids.include?(person_id)
322
- end
354
+ return 'ignored' if item.ignored?
323
355
 
324
- schedule_payload(payload)
356
+ schedule_item(item)
325
357
 
358
+ data = item['data']
326
359
  log_instance_link(data)
327
-
328
360
  Rollbar.last_report = data
329
361
 
330
362
  data
@@ -337,21 +369,21 @@ module Rollbar
337
369
  log_error "[Rollbar] Reporting internal error encountered while sending data to Rollbar."
338
370
 
339
371
  begin
340
- payload = build_payload('error', nil, exception, {:internal => true})
372
+ item = build_item('error', nil, exception, {:internal => true})
341
373
  rescue => e
342
- send_failsafe("build_payload in exception_data", e)
374
+ send_failsafe("build_item in exception_data", e)
343
375
  return
344
376
  end
345
377
 
346
378
  begin
347
- process_payload(payload)
379
+ process_item(item)
348
380
  rescue => e
349
- send_failsafe("error in process_payload", e)
381
+ send_failsafe("error in process_item", e)
350
382
  return
351
383
  end
352
384
 
353
385
  begin
354
- log_instance_link(payload['data'])
386
+ log_instance_link(item['data'])
355
387
  rescue => e
356
388
  send_failsafe("error logging instance link", e)
357
389
  return
@@ -360,212 +392,31 @@ module Rollbar
360
392
 
361
393
  ## Payload building functions
362
394
 
363
- def build_payload(level, message, exception, extra)
364
- environment = configuration.environment
365
- environment = 'unspecified' if environment.nil? || environment.empty?
366
-
367
- data = {
368
- :timestamp => Time.now.to_i,
369
- :environment => environment,
370
- :level => level,
371
- :language => 'ruby',
372
- :framework => configuration.framework,
373
- :server => server_data,
374
- :notifier => {
375
- :name => 'rollbar-gem',
376
- :version => VERSION
377
- }
378
- }
379
-
380
- data[:body] = build_payload_body(message, exception, extra)
381
- data[:project_package_paths] = configuration.project_gem_paths if configuration.project_gem_paths
382
- data[:code_version] = configuration.code_version if configuration.code_version
383
- data[:uuid] = SecureRandom.uuid if defined?(SecureRandom) && SecureRandom.respond_to?(:uuid)
384
-
385
- Rollbar::Util.deep_merge(data, configuration.payload_options)
386
- Rollbar::Util.deep_merge(data, scope_object)
387
-
388
- # Our API doesn't allow null context values, so just delete
389
- # the key if value is nil.
390
- data.delete(:context) unless data[:context]
391
-
392
- payload = {
393
- 'access_token' => configuration.access_token,
394
- 'data' => data
395
- }
396
-
397
- enforce_valid_utf8(payload)
398
-
399
- call_transform(:level => level,
400
- :exception => exception,
401
- :message => message,
402
- :extra => extra,
403
- :payload => payload)
404
-
405
- payload
406
- end
407
-
408
- def call_transform(options)
395
+ def build_item(level, message, exception, extra)
409
396
  options = {
410
- :level => options[:level],
397
+ :level => level,
398
+ :message => message,
399
+ :exception => exception,
400
+ :extra => extra,
401
+ :configuration => configuration,
402
+ :logger => logger,
411
403
  :scope => scope_object,
412
- :exception => options[:exception],
413
- :message => options[:message],
414
- :extra => options[:extra],
415
- :payload => options[:payload]
416
- }
417
- handlers = configuration.transform
418
-
419
- handlers.each do |handler|
420
- begin
421
- handler.call(options)
422
- rescue => e
423
- log_error("[Rollbar] Error calling the `transform` hook: #{e}")
424
-
425
- break
426
- end
427
- end
428
- end
429
-
430
- def build_payload_body(message, exception, extra)
431
- extra = Rollbar::Util.deep_merge(custom_data, extra || {}) if custom_data_method?
432
-
433
- if exception
434
- build_payload_body_exception(message, exception, extra)
435
- else
436
- build_payload_body_message(message, extra)
437
- end
438
- end
439
-
440
- def custom_data_method?
441
- !!configuration.custom_data_method
442
- end
443
-
444
- def report_custom_data_error(e)
445
- data = safely.error(e)
446
-
447
- return {} unless data.is_a?(Hash) && data[:uuid]
448
-
449
- uuid_url = uuid_rollbar_url(data)
450
-
451
- { :_error_in_custom_data_method => uuid_url }
452
- end
453
-
454
- def build_payload_body_exception(message, exception, extra)
455
- traces = trace_chain(exception)
456
-
457
- traces[0][:exception][:description] = message if message
458
- traces[0][:extra] = extra if extra
459
-
460
- if traces.size > 1
461
- { :trace_chain => traces }
462
- elsif traces.size == 1
463
- { :trace => traces[0] }
464
- end
465
- end
466
-
467
- def trace_data(exception)
468
- frames = exception_backtrace(exception).map do |frame|
469
- # parse the line
470
- match = frame.match(/(.*):(\d+)(?::in `([^']+)')?/)
471
-
472
- if match
473
- { :filename => match[1], :lineno => match[2].to_i, :method => match[3] }
474
- else
475
- { :filename => "<unknown>", :lineno => 0, :method => frame }
476
- end
477
- end
478
-
479
- # reverse so that the order is as rollbar expects
480
- frames.reverse!
481
-
482
- {
483
- :frames => frames,
484
- :exception => {
485
- :class => exception.class.name,
486
- :message => exception.message
487
- }
488
- }
489
- end
490
-
491
- # Returns the backtrace to be sent to our API. There are 3 options:
492
- #
493
- # 1. The exception received has a backtrace, then that backtrace is returned.
494
- # 2. configuration.populate_empty_backtraces is disabled, we return [] here
495
- # 3. The user has configuration.populate_empty_backtraces is enabled, then:
496
- #
497
- # We want to send the caller as backtrace, but the first lines of that array
498
- # are those from the user's Rollbar.error line until this method. We want
499
- # to remove those lines.
500
- def exception_backtrace(exception)
501
- return exception.backtrace if exception.backtrace.respond_to?( :map )
502
- return [] unless configuration.populate_empty_backtraces
503
-
504
- caller_backtrace = caller
505
- caller_backtrace.shift while caller_backtrace[0].include?(rollbar_lib_gem_dir)
506
- caller_backtrace
507
- end
508
-
509
- def rollbar_lib_gem_dir
510
- Gem::Specification.find_by_name('rollbar').gem_dir + '/lib'
511
- end
512
-
513
- def trace_chain(exception)
514
- traces = [trace_data(exception)]
515
- visited = [exception]
516
-
517
- while exception.respond_to?(:cause) && (cause = exception.cause) && cause.is_a?(Exception) && !visited.include?(cause)
518
- traces << trace_data(cause)
519
- visited << cause
520
- exception = cause
521
- end
522
-
523
- traces
524
- end
525
-
526
- def build_payload_body_message(message, extra)
527
- result = { :body => message || 'Empty message'}
528
- result[:extra] = extra if extra
529
-
530
- { :message => result }
531
- end
532
-
533
- def server_data
534
- data = {
535
- :host => Socket.gethostname
404
+ :notifier => self
536
405
  }
537
- data[:root] = configuration.root.to_s if configuration.root
538
- data[:branch] = configuration.branch if configuration.branch
539
- data[:pid] = Process.pid
540
406
 
541
- data
542
- end
407
+ item = Item.new(options)
408
+ item.build
543
409
 
544
- def enforce_valid_utf8(payload)
545
- normalizer = lambda { |object| Encoding.encode(object) }
546
-
547
- Rollbar::Util.iterate_and_update(payload, normalizer)
548
- end
549
-
550
- # Walks the entire payload and truncates string values that
551
- # are longer than the byte_threshold
552
- def truncate_payload(payload, byte_threshold)
553
- truncator = proc do |value|
554
- if value.is_a?(String) && value.bytesize > byte_threshold
555
- Rollbar::Util.truncate(value, byte_threshold)
556
- else
557
- value
558
- end
559
- end
560
-
561
- Rollbar::Util.iterate_and_update(payload, truncator)
410
+ item
562
411
  end
563
412
 
564
413
  ## Delivery functions
565
414
 
566
- def send_payload_using_eventmachine(payload)
567
- body = dump_payload(payload)
568
- headers = { 'X-Rollbar-Access-Token' => payload['access_token'] }
415
+ def send_item_using_eventmachine(item)
416
+ body = item.dump
417
+ return unless body
418
+
419
+ headers = { 'X-Rollbar-Access-Token' => item['access_token'] }
569
420
  req = EventMachine::HttpRequest.new(configuration.endpoint).post(:body => body, :head => headers)
570
421
 
571
422
  req.callback do
@@ -583,19 +434,25 @@ module Rollbar
583
434
  end
584
435
  end
585
436
 
586
- def send_payload(payload)
587
- log_info '[Rollbar] Sending payload'
588
- payload = Rollbar::JSON.load(payload) if payload.is_a?(String)
437
+ def send_item(item)
438
+ log_info '[Rollbar] Sending item'
589
439
 
590
440
  if configuration.use_eventmachine
591
- send_payload_using_eventmachine(payload)
441
+ send_item_using_eventmachine(item)
592
442
  return
593
443
  end
594
444
 
595
- body = dump_payload(payload)
445
+ body = item.dump
446
+ return unless body
596
447
 
597
448
  uri = URI.parse(configuration.endpoint)
449
+
450
+ handle_response(do_post(uri, body, item['access_token']))
451
+ end
452
+
453
+ def do_post(uri, body, access_token)
598
454
  http = Net::HTTP.new(uri.host, uri.port)
455
+ http.open_timeout = configuration.open_timeout
599
456
  http.read_timeout = configuration.request_timeout
600
457
 
601
458
  if uri.scheme == 'https'
@@ -606,10 +463,34 @@ module Rollbar
606
463
  end
607
464
 
608
465
  request = Net::HTTP::Post.new(uri.request_uri)
466
+
609
467
  request.body = body
610
- request.add_field('X-Rollbar-Access-Token', payload['access_token'])
611
- response = http.request(request)
468
+ request.add_field('X-Rollbar-Access-Token', access_token)
469
+
470
+ handle_net_retries { http.request(request) }
471
+ end
472
+
473
+ def handle_net_retries
474
+ return yield if skip_retries?
612
475
 
476
+ retries = configuration.net_retries - 1
477
+
478
+ begin
479
+ yield
480
+ rescue *LanguageSupport.timeout_exceptions
481
+ raise if retries <= 0
482
+
483
+ retries -= 1
484
+
485
+ retry
486
+ end
487
+ end
488
+
489
+ def skip_retries?
490
+ Rollbar::LanguageSupport.ruby_18? || Rollbar::LanguageSupport.ruby_19?
491
+ end
492
+
493
+ def handle_response(response)
613
494
  if response.code == '200'
614
495
  log_info '[Rollbar] Success'
615
496
  else
@@ -626,20 +507,21 @@ module Rollbar
626
507
  end
627
508
  end
628
509
 
629
- def write_payload(payload)
510
+ def write_item(item)
630
511
  if configuration.use_async
631
512
  @file_semaphore.synchronize {
632
- do_write_payload(payload)
513
+ do_write_item(item)
633
514
  }
634
515
  else
635
- do_write_payload(payload)
516
+ do_write_item(item)
636
517
  end
637
518
  end
638
519
 
639
- def do_write_payload(payload)
640
- log_info '[Rollbar] Writing payload to file'
520
+ def do_write_item(item)
521
+ log_info '[Rollbar] Writing item to file'
641
522
 
642
- body = dump_payload(payload)
523
+ body = item.dump
524
+ return unless body
643
525
 
644
526
  begin
645
527
  unless @file
@@ -654,43 +536,6 @@ module Rollbar
654
536
  end
655
537
  end
656
538
 
657
- def send_failsafe(message, exception)
658
- exception_reason = failsafe_reason(message, exception)
659
-
660
- log_error "[Rollbar] Sending failsafe response due to #{exception_reason}"
661
-
662
- body = failsafe_body(exception_reason)
663
-
664
- failsafe_data = {
665
- :level => 'error',
666
- :environment => configuration.environment.to_s,
667
- :body => {
668
- :message => {
669
- :body => body
670
- }
671
- },
672
- :notifier => {
673
- :name => 'rollbar-gem',
674
- :version => VERSION
675
- },
676
- :internal => true,
677
- :failsafe => true
678
- }
679
-
680
- failsafe_payload = {
681
- 'access_token' => configuration.access_token,
682
- 'data' => failsafe_data
683
- }
684
-
685
- begin
686
- schedule_payload(failsafe_payload)
687
- rescue => e
688
- log_error "[Rollbar] Error sending failsafe : #{e}"
689
- end
690
-
691
- failsafe_payload
692
- end
693
-
694
539
  def failsafe_reason(message, exception)
695
540
  body = ''
696
541
 
@@ -721,15 +566,15 @@ module Rollbar
721
566
  "Failsafe from rollbar-gem. #{reason}"
722
567
  end
723
568
 
724
- def schedule_payload(payload)
725
- return if payload.nil?
569
+ def schedule_item(item)
570
+ return unless item
726
571
 
727
- log_info '[Rollbar] Scheduling payload'
572
+ log_info '[Rollbar] Scheduling item'
728
573
 
729
574
  if configuration.use_async
730
- process_async_payload(payload)
575
+ process_async_item(item)
731
576
  else
732
- process_payload(payload)
577
+ process_item(item)
733
578
  end
734
579
  end
735
580
 
@@ -739,49 +584,34 @@ module Rollbar
739
584
  Rollbar::Delay::Thread
740
585
  end
741
586
 
742
- def process_async_payload(payload)
587
+ def process_async_item(item)
743
588
  configuration.async_handler ||= default_async_handler
744
- configuration.async_handler.call(payload)
589
+ configuration.async_handler.call(item.payload)
745
590
  rescue => e
746
591
  if configuration.failover_handlers.empty?
747
592
  log_error '[Rollbar] Async handler failed, and there are no failover handlers configured. See the docs for "failover_handlers"'
748
593
  return
749
594
  end
750
595
 
751
- async_failover(payload)
596
+ async_failover(item)
752
597
  end
753
598
 
754
- def async_failover(payload)
599
+ def async_failover(item)
755
600
  log_warning '[Rollbar] Primary async handler failed. Trying failovers...'
756
601
 
757
602
  failover_handlers = configuration.failover_handlers
758
603
 
759
604
  failover_handlers.each do |handler|
760
605
  begin
761
- handler.call(payload)
606
+ handler.call(item.payload)
762
607
  rescue
763
608
  next unless handler == failover_handlers.last
764
609
 
765
- log_error "[Rollbar] All failover handlers failed while processing payload: #{Rollbar::JSON.dump(payload)}"
610
+ log_error "[Rollbar] All failover handlers failed while processing item: #{Rollbar::JSON.dump(item.payload)}"
766
611
  end
767
612
  end
768
613
  end
769
614
 
770
- def dump_payload(payload)
771
- # Ensure all keys are strings since we can receive the payload inline or
772
- # from an async handler job, which can be serialized.
773
- stringified_payload = Rollbar::Util::Hash.deep_stringify_keys(payload)
774
- result = Truncation.truncate(stringified_payload)
775
- return result unless Truncation.truncate?(result)
776
-
777
- original_size = Rollbar::JSON.dump(payload).bytesize
778
- final_size = result.bytesize
779
- send_failsafe("Could not send payload due to it being too large after truncating attempts. Original size: #{original_size} Final size: #{final_size}", nil)
780
- log_error "[Rollbar] Payload too large to be sent: #{Rollbar::JSON.dump(payload)}"
781
-
782
- nil
783
- end
784
-
785
615
  ## Logging
786
616
  %w(debug info warn error).each do |level|
787
617
  define_method(:"log_#{level}") do |message|
@@ -793,15 +623,11 @@ module Rollbar
793
623
 
794
624
  def log_instance_link(data)
795
625
  if data[:uuid]
796
- uuid_url = uuid_rollbar_url(data)
626
+ uuid_url = Util.uuid_rollbar_url(data, configuration)
797
627
  log_info "[Rollbar] Details: #{uuid_url} (only available if report was successful)"
798
628
  end
799
629
  end
800
630
 
801
- def uuid_rollbar_url(data)
802
- "#{configuration.web_base}/instance/uuid?uuid=#{data[:uuid]}"
803
- end
804
-
805
631
  def logger
806
632
  @logger ||= LoggerProxy.new(configuration.logger)
807
633
  end
@@ -812,6 +638,8 @@ module Rollbar
812
638
 
813
639
  def_delegators :notifier, *PUBLIC_NOTIFIER_METHODS
814
640
 
641
+ attr_writer :plugins
642
+
815
643
  # Similar to configure below, but used only internally within the gem
816
644
  # to configure it without initializing any of the third party hooks
817
645
  def preconfigure
@@ -826,7 +654,7 @@ module Rollbar
826
654
 
827
655
  yield(configuration)
828
656
 
829
- prepare
657
+ plugins.load!
830
658
  reset_notifier!
831
659
  end
832
660
 
@@ -854,52 +682,8 @@ module Rollbar
854
682
  configuration.safely?
855
683
  end
856
684
 
857
- def prepare
858
- prepare_js
859
- require_hooks
860
- require_core_extensions
861
- end
862
-
863
- def prepare_js
864
- ::Rollbar::Js.prepare if configuration.js_enabled
865
- end
866
-
867
- def require_hooks
868
- return if configuration.disable_monkey_patch
869
- wrap_delayed_worker
870
-
871
- if defined?(ActiveRecord)
872
- require 'active_record/version'
873
- require 'rollbar/active_record_extension' if ActiveRecord::VERSION::MAJOR >= 3
874
- end
875
-
876
- require 'rollbar/sidekiq' if defined?(Sidekiq)
877
- require 'rollbar/active_job' if defined?(ActiveJob)
878
- require 'rollbar/goalie' if defined?(Goalie)
879
- require 'rollbar/rack' if defined?(Rack) unless configuration.disable_rack_monkey_patch
880
- require 'rollbar/rake' if defined?(Rake)
881
- end
882
-
883
- def require_core_extensions
884
- # This monkey patch is always needed in order
885
- # to use Rollbar.scoped
886
- require 'rollbar/core_ext/thread'
887
-
888
- return if configuration.disable_core_monkey_patch
889
-
890
- # Needed to avoid active_support (< 4.1.0) bug serializing JSONs
891
- require 'rollbar/core_ext/basic_socket' if monkey_patch_socket?
892
- end
893
-
894
- def monkey_patch_socket?
895
- defined?(ActiveSupport::VERSION::STRING)
896
- end
897
-
898
- def wrap_delayed_worker
899
- return unless defined?(Delayed) && defined?(Delayed::Worker) && configuration.delayed_job_enabled
900
-
901
- require 'rollbar/delayed_job'
902
- Rollbar::Delayed.wrap_worker
685
+ def plugins
686
+ @plugins ||= Rollbar::Plugins.new
903
687
  end
904
688
 
905
689
  def notifier
@@ -984,3 +768,5 @@ module Rollbar
984
768
  end
985
769
  end
986
770
  end
771
+
772
+ Rollbar.plugins.require_all