rollbar 2.22.0 → 2.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df81cd3613655a5f61ef196c3f0818e100d3ac457161f6b3f592d4ac5f34d101
4
- data.tar.gz: 0a3409744f161bafb52e73d125846d63c27424a3372037751245dba70903ecc8
3
+ metadata.gz: c1848033c2fc853846ba902fbe4dc6095ad17a6e27595a3937484a6036154b76
4
+ data.tar.gz: a42d4a1274624ea5991b66b0df1ce7031d699390c5dcf574b98d8fe03ea5519d
5
5
  SHA512:
6
- metadata.gz: 0670e3497effa8c1b305456ec2990661dee667fb954ec46eb8cf2bb29fa3730da090b219185e1e17533bf9deb6233c5bac0fd81fbcd82edd1b983c11224d0a9b
7
- data.tar.gz: 18c1300e29ea410e43118c5e6fea05172430a5dec50b1070655e876b49fc29335b919ced5a0b1576d5ac86e3d93b027db29f1db93d26b4b18c211404081c14b3
6
+ metadata.gz: 5d71b0e452e917b566e48a292368a242404c2d26e91c011f641f1fb7bde2b05ee8bd88a9af6d595bf6581cea17d5d4a996af63104c4ea55a19de564760b4f7f3
7
+ data.tar.gz: b7ec97dfa2625823709eba27b5252706fce661877b9e4338595228c901e5766ab9752a5103a87f929d7af8ae9c687a978f7630d93d0aee5611ab58e5771ccd2c
data/.rubocop.yml CHANGED
@@ -1,3 +1,5 @@
1
+ require: rubocop-performance
2
+
1
3
  AllCops:
2
4
  Exclude:
3
5
  - 'vendor/**/*'
@@ -66,3 +68,137 @@ Style/FrozenStringLiteralComment:
66
68
  # If we do this, it will be in its own PR. It requires adding these magic comments
67
69
  # throughout the project, in order to prepare for a future Ruby 3.x.
68
70
  Enabled: false
71
+
72
+ Style/SafeNavigation:
73
+ # Not available in Ruby < 2.3.
74
+ Enabled: false
75
+
76
+ #
77
+ # Performance cops are opt in, and `Enabled: true` is always required.
78
+ # Full list is here: https://github.com/rubocop-hq/rubocop-performance/tree/master/lib/rubocop/cop/performance
79
+ # For travis builds, Codacy will see and use these directives.
80
+ #
81
+ Performance/Caller:
82
+ Enabled: true
83
+ Exclude:
84
+ - spec/**/*
85
+
86
+ Performance/CaseWhenSplat:
87
+ Enabled: true
88
+ Exclude:
89
+ - spec/**/*
90
+
91
+ Performance/Casecmp:
92
+ Enabled: true
93
+ Exclude:
94
+ - spec/**/*
95
+
96
+ Performance/ChainArrayAllocation:
97
+ Enabled: true
98
+ Exclude:
99
+ - spec/**/*
100
+
101
+ Performance/CompareWithBlock:
102
+ Enabled: true
103
+ Exclude:
104
+ - spec/**/*
105
+
106
+ Performance/Count:
107
+ Enabled: true
108
+ Exclude:
109
+ - spec/**/*
110
+
111
+ Performance/Detect:
112
+ Enabled: true
113
+ Exclude:
114
+ - spec/**/*
115
+
116
+ Performance/DoubleStartEndWith:
117
+ Enabled: true
118
+ Exclude:
119
+ - spec/**/*
120
+
121
+ Performance/EndWith:
122
+ Enabled: true
123
+ Exclude:
124
+ - spec/**/*
125
+
126
+ Performance/FixedSize:
127
+ Enabled: true
128
+ Exclude:
129
+ - spec/**/*
130
+
131
+ Performance/FlatMap:
132
+ Enabled: true
133
+ Exclude:
134
+ - spec/**/*
135
+
136
+ Performance/InefficientHashSearch:
137
+ Enabled: true
138
+ Exclude:
139
+ - spec/**/*
140
+
141
+ Performance/OpenStruct:
142
+ Enabled: true
143
+ Exclude:
144
+ - spec/**/*
145
+
146
+ Performance/RangeInclude:
147
+ Enabled: true
148
+ Exclude:
149
+ - spec/**/*
150
+
151
+ Performance/RedundantBlockCall:
152
+ Enabled: true
153
+ Exclude:
154
+ - spec/**/*
155
+
156
+ Performance/RedundantMatch:
157
+ Enabled: true
158
+ Exclude:
159
+ - spec/**/*
160
+
161
+ Performance/RedundantMerge:
162
+ Enabled: true
163
+ Exclude:
164
+ - spec/**/*
165
+
166
+ Performance/RegexpMatch:
167
+ Enabled: true
168
+ Exclude:
169
+ - spec/**/*
170
+
171
+ Performance/ReverseEach:
172
+ Enabled: true
173
+ Exclude:
174
+ - spec/**/*
175
+
176
+ Performance/Size:
177
+ Enabled: true
178
+ Exclude:
179
+ - spec/**/*
180
+
181
+ Performance/StartWith:
182
+ Enabled: true
183
+ Exclude:
184
+ - spec/**/*
185
+
186
+ Performance/StringReplacement:
187
+ Enabled: true
188
+ Exclude:
189
+ - spec/**/*
190
+
191
+ Performance/TimesMap:
192
+ Enabled: true
193
+ Exclude:
194
+ - spec/**/*
195
+
196
+ Performance/UnfreezeString:
197
+ Enabled: true
198
+ Exclude:
199
+ - spec/**/*
200
+
201
+ Performance/UriDefaultParser:
202
+ Enabled: true
203
+ Exclude:
204
+ - spec/**/*
data/.travis.yml CHANGED
@@ -3,12 +3,6 @@ dist: trusty
3
3
  services:
4
4
  - redis-server
5
5
  language: ruby
6
- # Broken bundler on travis CI - https://github.com/bundler/bundler/issues/2784
7
- before_install:
8
- - gem update --system 2.7.7
9
- - gem --version
10
- - gem install bundler -v 1.6.1
11
- - bundle --version
12
6
 
13
7
  rvm:
14
8
  - 1.9.3
@@ -18,8 +12,8 @@ rvm:
18
12
  - 2.3.8
19
13
  - 2.4.5
20
14
  - 2.5.3
21
- - 2.6.0
22
- - 2.6.3
15
+ - 2.6.5
16
+ - 2.7.0
23
17
  - rbx
24
18
  # Travis's own rvm installer is failing on JRuby builds, TODO: reenable when fixed.
25
19
  # - jruby-9.1.9.0
@@ -73,9 +67,6 @@ matrix:
73
67
  allow_failures:
74
68
  - rvm: ruby-head
75
69
  - rvm: jruby-head
76
- # Ruby 2.6.x is still being eveluated and may have test failures
77
- - rvm: 2.6.0
78
- - rvm: 2.6.3
79
70
  # oraclejdk9 has a dependency issue that needs to be investigated
80
71
  - jdk: oraclejdk9
81
72
 
@@ -124,17 +115,17 @@ matrix:
124
115
  jdk: oraclejdk8
125
116
  - rvm: 2.5.3
126
117
  jdk: oraclejdk9
127
- - rvm: 2.6.0
118
+ - rvm: 2.6.5
128
119
  jdk: openjdk8
129
- - rvm: 2.6.0
120
+ - rvm: 2.6.5
130
121
  jdk: oraclejdk8
131
- - rvm: 2.6.0
122
+ - rvm: 2.6.5
132
123
  jdk: oraclejdk9
133
- - rvm: 2.6.3
124
+ - rvm: 2.7.0
134
125
  jdk: openjdk8
135
- - rvm: 2.6.3
126
+ - rvm: 2.7.0
136
127
  jdk: oraclejdk8
137
- - rvm: 2.6.3
128
+ - rvm: 2.7.0
138
129
  jdk: oraclejdk9
139
130
 
140
131
  - rvm: ruby-head
@@ -184,11 +175,14 @@ matrix:
184
175
  gemfile: gemfiles/rails52.gemfile
185
176
  - rvm: 2.1.0
186
177
  gemfile: gemfiles/rails60.gemfile
187
- # MRI 2.2.2 supports Rails 3.2.x and higher
178
+ # MRI 2.2.2 supports Rails 3.2.x and higher, except Rails 5.2.4 and higher*
179
+ # * ActionDispatch 5.2.4 uses Ruby 3.x safe navigation operator.
188
180
  - rvm: 2.2.2
189
181
  gemfile: gemfiles/rails30.gemfile
190
182
  - rvm: 2.2.2
191
183
  gemfile: gemfiles/rails31.gemfile
184
+ - rvm: 2.2.2
185
+ gemfile: gemfiles/rails52.gemfile
192
186
  # MRI 2.3.x supports Rails 4.0.x and higher
193
187
  - rvm: 2.3.8
194
188
  gemfile: gemfiles/rails30.gemfile
@@ -222,30 +216,39 @@ matrix:
222
216
  gemfile: gemfiles/rails40.gemfile
223
217
  - rvm: 2.5.3
224
218
  gemfile: gemfiles/rails41.gemfile
225
- - rvm: 2.6.0
219
+ - rvm: 2.6.5
226
220
  gemfile: gemfiles/rails30.gemfile
227
- - rvm: 2.6.0
221
+ - rvm: 2.6.5
228
222
  gemfile: gemfiles/rails31.gemfile
229
- - rvm: 2.6.0
223
+ - rvm: 2.6.5
230
224
  gemfile: gemfiles/rails32.gemfile
231
- - rvm: 2.6.0
225
+ - rvm: 2.6.5
232
226
  gemfile: gemfiles/rails40.gemfile
233
- - rvm: 2.6.0
227
+ - rvm: 2.6.5
234
228
  gemfile: gemfiles/rails41.gemfile
235
- - rvm: 2.6.0
229
+ - rvm: 2.6.5
236
230
  gemfile: gemfiles/rails42.gemfile
237
- - rvm: 2.6.3
231
+ # Rails 6.x tries to be compatible with Ruby 2.7, though
232
+ # it still throws a lot of warnings. No point testing earlier
233
+ # Rails with Ruby 2.7.
234
+ - rvm: 2.7.0
238
235
  gemfile: gemfiles/rails30.gemfile
239
- - rvm: 2.6.3
236
+ - rvm: 2.7.0
240
237
  gemfile: gemfiles/rails31.gemfile
241
- - rvm: 2.6.3
238
+ - rvm: 2.7.0
242
239
  gemfile: gemfiles/rails32.gemfile
243
- - rvm: 2.6.3
240
+ - rvm: 2.7.0
244
241
  gemfile: gemfiles/rails40.gemfile
245
- - rvm: 2.6.3
242
+ - rvm: 2.7.0
246
243
  gemfile: gemfiles/rails41.gemfile
247
- - rvm: 2.6.3
244
+ - rvm: 2.7.0
248
245
  gemfile: gemfiles/rails42.gemfile
246
+ - rvm: 2.7.0
247
+ gemfile: gemfiles/rails50.gemfile
248
+ - rvm: 2.7.0
249
+ gemfile: gemfiles/rails51.gemfile
250
+ - rvm: 2.7.0
251
+ gemfile: gemfiles/rails52.gemfile
249
252
  # JRuby JDBC Adapter is only compatible with Rails >= 5.x
250
253
  - rvm: jruby-9.1.9.0
251
254
  gemfile: gemfiles/rails30.gemfile
data/Gemfile CHANGED
@@ -46,6 +46,7 @@ end
46
46
 
47
47
  if RUBY_VERSION.start_with?('1.9')
48
48
  gem 'capistrano', '<= 3.4.1', :require => false
49
+ gem 'json', '1.8.6'
49
50
  gem 'shoryuken', '>= 4.0.0', '<= 4.0.2'
50
51
  gem 'sucker_punch', '~> 1.0'
51
52
  elsif RUBY_VERSION.start_with?('2')
@@ -73,6 +74,7 @@ gem 'girl_friday', '>= 0.11.1'
73
74
  gem 'redis'
74
75
  gem 'resque', '< 2.0.0'
75
76
  gem 'rubocop', :require => false
77
+ gem 'rubocop-performance', :require => false
76
78
  gem 'sinatra'
77
79
  gem 'webmock', :require => false
78
80
  gemspec
@@ -1 +1 @@
1
- !function(r){var e={};function o(n){if(e[n])return e[n].exports;var t=e[n]={i:n,l:!1,exports:{}};return r[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.m=r,o.c=e,o.d=function(r,e,n){o.o(r,e)||Object.defineProperty(r,e,{enumerable:!0,get:n})},o.r=function(r){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(r,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(r,"__esModule",{value:!0})},o.t=function(r,e){if(1&e&&(r=o(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var t in r)o.d(n,t,function(e){return r[e]}.bind(null,t));return n},o.n=function(r){var e=r&&r.__esModule?function(){return r.default}:function(){return r};return o.d(e,"a",e),e},o.o=function(r,e){return Object.prototype.hasOwnProperty.call(r,e)},o.p="",o(o.s=0)}([function(r,e,o){var n=o(1),t=o(4);_rollbarConfig=_rollbarConfig||{},_rollbarConfig.rollbarJsUrl=_rollbarConfig.rollbarJsUrl||"https://cdnjs.cloudflare.com/ajax/libs/rollbar.js/2.12.2/rollbar.min.js",_rollbarConfig.async=void 0===_rollbarConfig.async||_rollbarConfig.async;var a=n.setupShim(window,_rollbarConfig),l=t(_rollbarConfig);window.rollbar=n.Rollbar,a.loadFull(window,document,!_rollbarConfig.async,_rollbarConfig,l)},function(r,e,o){var n=o(2);function t(r){return function(){try{return r.apply(this,arguments)}catch(r){try{console.error("[Rollbar]: Internal error",r)}catch(r){}}}}var a=0;function l(r,e){this.options=r,this._rollbarOldOnError=null;var o=a++;this.shimId=function(){return o},"undefined"!=typeof window&&window._rollbarShims&&(window._rollbarShims[o]={handler:e,messages:[]})}var i=o(3),s=function(r,e){return new l(r,e)},d=function(r){return new i(s,r)};function c(r){return t(function(){var e=Array.prototype.slice.call(arguments,0),o={shim:this,method:r,args:e,ts:new Date};window._rollbarShims[this.shimId()].messages.push(o)})}l.prototype.loadFull=function(r,e,o,n,a){var l=!1,i=e.createElement("script"),s=e.getElementsByTagName("script")[0],d=s.parentNode;i.crossOrigin="",i.src=n.rollbarJsUrl,o||(i.async=!0),i.onload=i.onreadystatechange=t(function(){if(!(l||this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState)){i.onload=i.onreadystatechange=null;try{d.removeChild(i)}catch(r){}l=!0,function(){var e;if(void 0===r._rollbarDidLoad){e=new Error("rollbar.js did not load");for(var o,n,t,l,i=0;o=r._rollbarShims[i++];)for(o=o.messages||[];n=o.shift();)for(t=n.args||[],i=0;i<t.length;++i)if("function"==typeof(l=t[i])){l(e);break}}"function"==typeof a&&a(e)}()}}),d.insertBefore(i,s)},l.prototype.wrap=function(r,e,o){try{var n;if(n="function"==typeof e?e:function(){return e||{}},"function"!=typeof r)return r;if(r._isWrap)return r;if(!r._rollbar_wrapped&&(r._rollbar_wrapped=function(){o&&"function"==typeof o&&o.apply(this,arguments);try{return r.apply(this,arguments)}catch(o){var e=o;throw e&&("string"==typeof e&&(e=new String(e)),e._rollbarContext=n()||{},e._rollbarContext._wrappedSource=r.toString(),window._rollbarWrappedError=e),e}},r._rollbar_wrapped._isWrap=!0,r.hasOwnProperty))for(var t in r)r.hasOwnProperty(t)&&(r._rollbar_wrapped[t]=r[t]);return r._rollbar_wrapped}catch(e){return r}};for(var p="log,debug,info,warn,warning,error,critical,global,configure,handleUncaughtException,handleAnonymousErrors,handleUnhandledRejection,captureEvent,captureDomContentLoaded,captureLoad".split(","),u=0;u<p.length;++u)l.prototype[p[u]]=c(p[u]);r.exports={setupShim:function(r,e){if(r){var o=e.globalAlias||"Rollbar";if("object"==typeof r[o])return r[o];r._rollbarShims={},r._rollbarWrappedError=null;var a=new d(e);return t(function(){e.captureUncaught&&(a._rollbarOldOnError=r.onerror,n.captureUncaughtExceptions(r,a,!0),e.wrapGlobalEventHandlers&&n.wrapGlobals(r,a,!0)),e.captureUnhandledRejections&&n.captureUnhandledRejections(r,a,!0);var t=e.autoInstrument;return!1!==e.enabled&&(void 0===t||!0===t||"object"==typeof t&&t.network)&&r.addEventListener&&(r.addEventListener("load",a.captureLoad.bind(a)),r.addEventListener("DOMContentLoaded",a.captureDomContentLoaded.bind(a))),r[o]=a,a})()}},Rollbar:d}},function(r,e){function o(r,e,o){if(e.hasOwnProperty&&e.hasOwnProperty("addEventListener")){for(var n=e.addEventListener;n._rollbarOldAdd&&n.belongsToShim;)n=n._rollbarOldAdd;var t=function(e,o,t){n.call(this,e,r.wrap(o),t)};t._rollbarOldAdd=n,t.belongsToShim=o,e.addEventListener=t;for(var a=e.removeEventListener;a._rollbarOldRemove&&a.belongsToShim;)a=a._rollbarOldRemove;var l=function(r,e,o){a.call(this,r,e&&e._rollbar_wrapped||e,o)};l._rollbarOldRemove=a,l.belongsToShim=o,e.removeEventListener=l}}r.exports={captureUncaughtExceptions:function(r,e,o){if(r){var n;if("function"==typeof e._rollbarOldOnError)n=e._rollbarOldOnError;else if(r.onerror){for(n=r.onerror;n._rollbarOldOnError;)n=n._rollbarOldOnError;e._rollbarOldOnError=n}e.handleAnonymousErrors();var t=function(){var o=Array.prototype.slice.call(arguments,0);!function(r,e,o,n){r._rollbarWrappedError&&(n[4]||(n[4]=r._rollbarWrappedError),n[5]||(n[5]=r._rollbarWrappedError._rollbarContext),r._rollbarWrappedError=null);var t=e.handleUncaughtException.apply(e,n);o&&o.apply(r,n),"anonymous"===t&&(e.anonymousErrorsPending+=1)}(r,e,n,o)};o&&(t._rollbarOldOnError=n),r.onerror=t}},captureUnhandledRejections:function(r,e,o){if(r){"function"==typeof r._rollbarURH&&r._rollbarURH.belongsToShim&&r.removeEventListener("unhandledrejection",r._rollbarURH);var n=function(r){var o,n,t;try{o=r.reason}catch(r){o=void 0}try{n=r.promise}catch(r){n="[unhandledrejection] error getting `promise` from event"}try{t=r.detail,!o&&t&&(o=t.reason,n=t.promise)}catch(r){}o||(o="[unhandledrejection] error getting `reason` from event"),e&&e.handleUnhandledRejection&&e.handleUnhandledRejection(o,n)};n.belongsToShim=o,r._rollbarURH=n,r.addEventListener("unhandledrejection",n)}},wrapGlobals:function(r,e,n){if(r){var t,a,l="EventTarget,Window,Node,ApplicationCache,AudioTrackList,ChannelMergerNode,CryptoOperation,EventSource,FileReader,HTMLUnknownElement,IDBDatabase,IDBRequest,IDBTransaction,KeyOperation,MediaController,MessagePort,ModalWindow,Notification,SVGElementInstance,Screen,TextTrack,TextTrackCue,TextTrackList,WebSocket,WebSocketWorker,Worker,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload".split(",");for(t=0;t<l.length;++t)r[a=l[t]]&&r[a].prototype&&o(e,r[a].prototype,n)}}}},function(r,e){function o(r,e){this.impl=r(e,this),this.options=e,function(r){for(var e=function(r){return function(){var e=Array.prototype.slice.call(arguments,0);if(this.impl[r])return this.impl[r].apply(this.impl,e)}},o="log,debug,info,warn,warning,error,critical,global,configure,handleUncaughtException,handleAnonymousErrors,handleUnhandledRejection,_createItem,wrap,loadFull,shimId,captureEvent,captureDomContentLoaded,captureLoad".split(","),n=0;n<o.length;n++)r[o[n]]=e(o[n])}(o.prototype)}o.prototype._swapAndProcessMessages=function(r,e){var o,n,t;for(this.impl=r(this.options);o=e.shift();)n=o.method,t=o.args,this[n]&&"function"==typeof this[n]&&("captureDomContentLoaded"===n||"captureLoad"===n?this[n].apply(this,[t[0],o.ts]):this[n].apply(this,t));return this},r.exports=o},function(r,e){r.exports=function(r){return function(e){if(!e&&!window._rollbarInitialized){for(var o,n,t=(r=r||{}).globalAlias||"Rollbar",a=window.rollbar,l=function(r){return new a(r)},i=0;o=window._rollbarShims[i++];)n||(n=o.handler),o.handler._swapAndProcessMessages(l,o.messages);window[t]=n,window._rollbarInitialized=!0}}}}]);
1
+ !function(r){var e={};function o(n){if(e[n])return e[n].exports;var t=e[n]={i:n,l:!1,exports:{}};return r[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.m=r,o.c=e,o.d=function(r,e,n){o.o(r,e)||Object.defineProperty(r,e,{enumerable:!0,get:n})},o.r=function(r){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(r,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(r,"__esModule",{value:!0})},o.t=function(r,e){if(1&e&&(r=o(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var t in r)o.d(n,t,function(e){return r[e]}.bind(null,t));return n},o.n=function(r){var e=r&&r.__esModule?function(){return r.default}:function(){return r};return o.d(e,"a",e),e},o.o=function(r,e){return Object.prototype.hasOwnProperty.call(r,e)},o.p="",o(o.s=0)}([function(r,e,o){var n=o(1),t=o(4);_rollbarConfig=_rollbarConfig||{},_rollbarConfig.rollbarJsUrl=_rollbarConfig.rollbarJsUrl||"https://cdnjs.cloudflare.com/ajax/libs/rollbar.js/2.12.3/rollbar.min.js",_rollbarConfig.async=void 0===_rollbarConfig.async||_rollbarConfig.async;var a=n.setupShim(window,_rollbarConfig),l=t(_rollbarConfig);window.rollbar=n.Rollbar,a.loadFull(window,document,!_rollbarConfig.async,_rollbarConfig,l)},function(r,e,o){var n=o(2);function t(r){return function(){try{return r.apply(this,arguments)}catch(r){try{console.error("[Rollbar]: Internal error",r)}catch(r){}}}}var a=0;function l(r,e){this.options=r,this._rollbarOldOnError=null;var o=a++;this.shimId=function(){return o},"undefined"!=typeof window&&window._rollbarShims&&(window._rollbarShims[o]={handler:e,messages:[]})}var i=o(3),s=function(r,e){return new l(r,e)},d=function(r){return new i(s,r)};function c(r){return t(function(){var e=Array.prototype.slice.call(arguments,0),o={shim:this,method:r,args:e,ts:new Date};window._rollbarShims[this.shimId()].messages.push(o)})}l.prototype.loadFull=function(r,e,o,n,a){var l=!1,i=e.createElement("script"),s=e.getElementsByTagName("script")[0],d=s.parentNode;i.crossOrigin="",i.src=n.rollbarJsUrl,o||(i.async=!0),i.onload=i.onreadystatechange=t(function(){if(!(l||this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState)){i.onload=i.onreadystatechange=null;try{d.removeChild(i)}catch(r){}l=!0,function(){var e;if(void 0===r._rollbarDidLoad){e=new Error("rollbar.js did not load");for(var o,n,t,l,i=0;o=r._rollbarShims[i++];)for(o=o.messages||[];n=o.shift();)for(t=n.args||[],i=0;i<t.length;++i)if("function"==typeof(l=t[i])){l(e);break}}"function"==typeof a&&a(e)}()}}),d.insertBefore(i,s)},l.prototype.wrap=function(r,e,o){try{var n;if(n="function"==typeof e?e:function(){return e||{}},"function"!=typeof r)return r;if(r._isWrap)return r;if(!r._rollbar_wrapped&&(r._rollbar_wrapped=function(){o&&"function"==typeof o&&o.apply(this,arguments);try{return r.apply(this,arguments)}catch(o){var e=o;throw e&&("string"==typeof e&&(e=new String(e)),e._rollbarContext=n()||{},e._rollbarContext._wrappedSource=r.toString(),window._rollbarWrappedError=e),e}},r._rollbar_wrapped._isWrap=!0,r.hasOwnProperty))for(var t in r)r.hasOwnProperty(t)&&(r._rollbar_wrapped[t]=r[t]);return r._rollbar_wrapped}catch(e){return r}};for(var p="log,debug,info,warn,warning,error,critical,global,configure,handleUncaughtException,handleAnonymousErrors,handleUnhandledRejection,captureEvent,captureDomContentLoaded,captureLoad".split(","),u=0;u<p.length;++u)l.prototype[p[u]]=c(p[u]);r.exports={setupShim:function(r,e){if(r){var o=e.globalAlias||"Rollbar";if("object"==typeof r[o])return r[o];r._rollbarShims={},r._rollbarWrappedError=null;var a=new d(e);return t(function(){e.captureUncaught&&(a._rollbarOldOnError=r.onerror,n.captureUncaughtExceptions(r,a,!0),e.wrapGlobalEventHandlers&&n.wrapGlobals(r,a,!0)),e.captureUnhandledRejections&&n.captureUnhandledRejections(r,a,!0);var t=e.autoInstrument;return!1!==e.enabled&&(void 0===t||!0===t||"object"==typeof t&&t.network)&&r.addEventListener&&(r.addEventListener("load",a.captureLoad.bind(a)),r.addEventListener("DOMContentLoaded",a.captureDomContentLoaded.bind(a))),r[o]=a,a})()}},Rollbar:d}},function(r,e){function o(r,e,o){if(e.hasOwnProperty&&e.hasOwnProperty("addEventListener")){for(var n=e.addEventListener;n._rollbarOldAdd&&n.belongsToShim;)n=n._rollbarOldAdd;var t=function(e,o,t){n.call(this,e,r.wrap(o),t)};t._rollbarOldAdd=n,t.belongsToShim=o,e.addEventListener=t;for(var a=e.removeEventListener;a._rollbarOldRemove&&a.belongsToShim;)a=a._rollbarOldRemove;var l=function(r,e,o){a.call(this,r,e&&e._rollbar_wrapped||e,o)};l._rollbarOldRemove=a,l.belongsToShim=o,e.removeEventListener=l}}r.exports={captureUncaughtExceptions:function(r,e,o){if(r){var n;if("function"==typeof e._rollbarOldOnError)n=e._rollbarOldOnError;else if(r.onerror){for(n=r.onerror;n._rollbarOldOnError;)n=n._rollbarOldOnError;e._rollbarOldOnError=n}e.handleAnonymousErrors();var t=function(){var o=Array.prototype.slice.call(arguments,0);!function(r,e,o,n){r._rollbarWrappedError&&(n[4]||(n[4]=r._rollbarWrappedError),n[5]||(n[5]=r._rollbarWrappedError._rollbarContext),r._rollbarWrappedError=null);var t=e.handleUncaughtException.apply(e,n);o&&o.apply(r,n),"anonymous"===t&&(e.anonymousErrorsPending+=1)}(r,e,n,o)};o&&(t._rollbarOldOnError=n),r.onerror=t}},captureUnhandledRejections:function(r,e,o){if(r){"function"==typeof r._rollbarURH&&r._rollbarURH.belongsToShim&&r.removeEventListener("unhandledrejection",r._rollbarURH);var n=function(r){var o,n,t;try{o=r.reason}catch(r){o=void 0}try{n=r.promise}catch(r){n="[unhandledrejection] error getting `promise` from event"}try{t=r.detail,!o&&t&&(o=t.reason,n=t.promise)}catch(r){}o||(o="[unhandledrejection] error getting `reason` from event"),e&&e.handleUnhandledRejection&&e.handleUnhandledRejection(o,n)};n.belongsToShim=o,r._rollbarURH=n,r.addEventListener("unhandledrejection",n)}},wrapGlobals:function(r,e,n){if(r){var t,a,l="EventTarget,Window,Node,ApplicationCache,AudioTrackList,ChannelMergerNode,CryptoOperation,EventSource,FileReader,HTMLUnknownElement,IDBDatabase,IDBRequest,IDBTransaction,KeyOperation,MediaController,MessagePort,ModalWindow,Notification,SVGElementInstance,Screen,TextTrack,TextTrackCue,TextTrackList,WebSocket,WebSocketWorker,Worker,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload".split(",");for(t=0;t<l.length;++t)r[a=l[t]]&&r[a].prototype&&o(e,r[a].prototype,n)}}}},function(r,e){function o(r,e){this.impl=r(e,this),this.options=e,function(r){for(var e=function(r){return function(){var e=Array.prototype.slice.call(arguments,0);if(this.impl[r])return this.impl[r].apply(this.impl,e)}},o="log,debug,info,warn,warning,error,critical,global,configure,handleUncaughtException,handleAnonymousErrors,handleUnhandledRejection,_createItem,wrap,loadFull,shimId,captureEvent,captureDomContentLoaded,captureLoad".split(","),n=0;n<o.length;n++)r[o[n]]=e(o[n])}(o.prototype)}o.prototype._swapAndProcessMessages=function(r,e){var o,n,t;for(this.impl=r(this.options);o=e.shift();)n=o.method,t=o.args,this[n]&&"function"==typeof this[n]&&("captureDomContentLoaded"===n||"captureLoad"===n?this[n].apply(this,[t[0],o.ts]):this[n].apply(this,t));return this},r.exports=o},function(r,e){r.exports=function(r){return function(e){if(!e&&!window._rollbarInitialized){for(var o,n,t=(r=r||{}).globalAlias||"Rollbar",a=window.rollbar,l=function(r){return new a(r)},i=0;o=window._rollbarShims[i++];)n||(n=o.handler),o.handler._swapAndProcessMessages(l,o.messages);window[t]=n,window._rollbarInitialized=!0}}}}]);
@@ -129,6 +129,7 @@ An array of backup handlers if the async handlers fails. Each should respond to
129
129
 
130
130
  For use with `write_to_file`. Indicates location of the rollbar log file being
131
131
  tracked by [rollbar-agent](https://github.com/rollbar/rollbar-agent).
132
+ Enable `files_with_pid_name_enabled` if you want to have different files for each process(only works if extension `rollbar`)
132
133
 
133
134
  ### framework
134
135
 
@@ -27,6 +27,10 @@ platforms :rbx do
27
27
  gem 'rubysl', '~> 2.0' unless RUBY_VERSION.start_with?('1')
28
28
  end
29
29
 
30
+ if RUBY_VERSION < '2.0.0'
31
+ gem 'json', '1.8.6'
32
+ end
33
+
30
34
  if RUBY_VERSION < '2.2.2'
31
35
  gem 'sidekiq', '~> 2.13.0'
32
36
  else
@@ -15,7 +15,7 @@ is_jruby = defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) && 'jruby' == RUBY_
15
15
  gem 'appraisal'
16
16
  gem 'activerecord-jdbcsqlite3-adapter', :platform => :jruby
17
17
  gem 'jruby-openssl', :platform => :jruby
18
- gem 'rails', '6.0.0.rc1'
18
+ gem 'rails', '6.0.2.1'
19
19
  gem 'sqlite3', '~> 1.4', :platform => [:ruby, :mswin, :mingw]
20
20
 
21
21
  gem 'rspec-core', '~> 3.8.0'
@@ -39,7 +39,7 @@ module Rails
39
39
  end
40
40
 
41
41
  def eval_runner
42
- if Rails.version >= '5.1.0'
42
+ if Gem::Version.new(Rails.version) >= Gem::Version.new('5.1.0')
43
43
  rails5_runner
44
44
  else
45
45
  legacy_runner
@@ -55,6 +55,8 @@ module Rails
55
55
  end
56
56
 
57
57
  def rails5_runner
58
+ require 'rails/command'
59
+
58
60
  Rails::Command.invoke 'runner', ARGV
59
61
  end
60
62
 
@@ -17,13 +17,13 @@ module Rollbar
17
17
  attr_accessor :disable_monkey_patch
18
18
  attr_accessor :disable_rack_monkey_patch
19
19
  attr_accessor :disable_core_monkey_patch
20
+ attr_accessor :enable_error_context
20
21
  attr_accessor :dj_threshold
21
22
  attr_accessor :enabled
22
23
  attr_accessor :endpoint
23
24
  attr_accessor :environment
24
25
  attr_accessor :exception_level_filters
25
26
  attr_accessor :failover_handlers
26
- attr_accessor :filepath
27
27
  attr_accessor :framework
28
28
  attr_accessor :ignored_person_ids
29
29
  attr_accessor :host
@@ -57,15 +57,23 @@ module Rollbar
57
57
  attr_reader :transform
58
58
  attr_accessor :verify_ssl_peer
59
59
  attr_accessor :use_async
60
+ attr_accessor :async_json_payload
60
61
  attr_reader :use_eventmachine
61
62
  attr_accessor :web_base
62
- attr_accessor :write_to_file
63
63
  attr_reader :send_extra_frame_data
64
64
  attr_accessor :use_exception_level_filters_default
65
65
  attr_accessor :proxy
66
66
  attr_accessor :raise_on_error
67
67
  attr_accessor :transmit
68
68
  attr_accessor :log_payload
69
+ attr_accessor :backtrace_cleaner
70
+
71
+ attr_accessor :write_to_file
72
+ attr_accessor :filepath
73
+ attr_accessor :files_with_pid_name_enabled
74
+ attr_accessor :files_processed_enabled
75
+ attr_accessor :files_processed_duration # seconds
76
+ attr_accessor :files_processed_size # bytes
69
77
 
70
78
  attr_reader :project_gem_paths
71
79
  attr_accessor :configured_options
@@ -87,6 +95,7 @@ module Rollbar
87
95
  @disable_monkey_patch = false
88
96
  @disable_core_monkey_patch = false
89
97
  @disable_rack_monkey_patch = false
98
+ @enable_error_context = true
90
99
  @dj_threshold = 0
91
100
  @enabled = nil # set to true when configure is called
92
101
  @endpoint = DEFAULT_ENDPOINT
@@ -118,7 +127,7 @@ module Rollbar
118
127
  :api_key, :access_token, :accessToken, :session_id]
119
128
  @scrub_user = true
120
129
  @scrub_password = true
121
- @randomize_scrub_length = true
130
+ @randomize_scrub_length = false
122
131
  @scrub_whitelist = []
123
132
  @uncaught_exception_level = 'error'
124
133
  @scrub_headers = ['Authorization']
@@ -126,10 +135,10 @@ module Rollbar
126
135
  @safely = false
127
136
  @transform = []
128
137
  @use_async = false
138
+ @async_json_payload = false
129
139
  @use_eventmachine = false
130
140
  @verify_ssl_peer = true
131
141
  @web_base = DEFAULT_WEB_BASE
132
- @write_to_file = false
133
142
  @send_extra_frame_data = :none
134
143
  @project_gem_paths = []
135
144
  @use_exception_level_filters_default = false
@@ -139,11 +148,18 @@ module Rollbar
139
148
  @log_payload = false
140
149
  @collect_user_ip = true
141
150
  @anonymize_user_ip = false
151
+ @backtrace_cleaner = nil
142
152
  @hooks = {
143
153
  :on_error_response => nil, # params: response
144
154
  :on_report_internal_error => nil # params: exception
145
155
  }
146
156
 
157
+ @write_to_file = false
158
+ @files_with_pid_name_enabled = false
159
+ @files_processed_enabled = false
160
+ @files_processed_duration = 60
161
+ @files_processed_size = 5 * 1000 * 1000
162
+
147
163
  @configured_options = ConfiguredOptions.new(self)
148
164
  end
149
165
 
@@ -232,9 +248,10 @@ module Rollbar
232
248
  value.is_a?(Hash) ? use_sidekiq(value) : use_sidekiq
233
249
  end
234
250
 
235
- def use_thread
251
+ def use_thread(options = {})
236
252
  require 'rollbar/delay/thread'
237
253
  @use_async = true
254
+ Rollbar::Delay::Thread.options = options
238
255
  @async_handler = Rollbar::Delay::Thread
239
256
  end
240
257
 
@@ -261,7 +278,10 @@ module Rollbar
261
278
  found = Gem::Specification.each.select { |spec| name === spec.name }
262
279
  puts "[Rollbar] No gems found matching #{name.inspect}" if found.empty?
263
280
  found
264
- end.flatten.uniq.map(&:gem_dir)
281
+ end
282
+ @project_gem_paths.flatten!
283
+ @project_gem_paths.uniq!
284
+ @project_gem_paths.map!(&:gem_dir)
265
285
  end
266
286
 
267
287
  def before_process=(*handler)
@@ -12,13 +12,9 @@ module Rollbar
12
12
 
13
13
  def queue
14
14
  @queue ||= queue_class.new(nil, :size => 5) do |payload|
15
- begin
16
- Rollbar.process_from_async_handler(payload)
17
- rescue StandardError
18
- # According to https://github.com/mperham/girl_friday/wiki#error-handling
19
- # we reraise the exception so it can be handled some way
20
- raise
21
- end
15
+ Rollbar.process_from_async_handler(payload)
16
+
17
+ # Do not rescue. GirlFriday will call the error handler.
22
18
  end
23
19
  end
24
20
  end
@@ -24,9 +24,8 @@ module Rollbar
24
24
 
25
25
  def perform(payload)
26
26
  Rollbar.process_from_async_handler(payload)
27
- rescue StandardError
28
- # Raise the exception so Resque can track the errored job
29
- raise
27
+
28
+ # Do not rescue. Resque will call the error handler.
30
29
  end
31
30
  end
32
31
  end
@@ -17,10 +17,8 @@ module Rollbar
17
17
 
18
18
  def perform(*args)
19
19
  Rollbar.process_from_async_handler(*args)
20
- rescue StandardError
21
- # Raise the exception so Sidekiq can track the errored job
22
- # and retry it
23
- raise
20
+
21
+ # Do not rescue. Sidekiq will call the error handler.
24
22
  end
25
23
  end
26
24
  end
@@ -33,7 +33,7 @@ module Rollbar
33
33
 
34
34
  def perform(*args)
35
35
  Rollbar.process_from_async_handler(*args)
36
- rescue StandardError
36
+
37
37
  # SuckerPunch can configure an exception handler with:
38
38
  #
39
39
  # SuckerPunch.exception_handler { # do something here }
@@ -41,9 +41,8 @@ module Rollbar
41
41
  # This is just passed to Celluloid.exception_handler which will
42
42
  # push the reiceved block to an array of handlers, by default empty, [].
43
43
  #
44
- # We reraise the exception here casue it's safe and users could have defined
45
- # their own exception handler for SuckerPunch
46
- raise
44
+
45
+ # Do not rescue. SuckerPunch will call the error handler.
47
46
  end
48
47
  end
49
48
  end
@@ -9,7 +9,10 @@ module Rollbar
9
9
  Error = Class.new(StandardError)
10
10
  TimeoutError = Class.new(Error)
11
11
 
12
+ DEFAULT_PRIORITY = 1
13
+
12
14
  class << self
15
+ attr_writer :options
13
16
  attr_reader :reaper
14
17
 
15
18
  def call(payload)
@@ -20,6 +23,10 @@ module Rollbar
20
23
  thread
21
24
  end
22
25
 
26
+ def options
27
+ @options || {}
28
+ end
29
+
23
30
  private
24
31
 
25
32
  def threads
@@ -61,9 +68,16 @@ module Rollbar
61
68
  end
62
69
  end # class << self
63
70
 
71
+ def priority
72
+ self.class.options[:priority] || DEFAULT_PRIORITY
73
+ end
74
+
64
75
  def call(payload)
76
+ priority = self.priority
77
+
65
78
  ::Thread.new do
66
79
  begin
80
+ ::Thread.current.priority = priority
67
81
  Rollbar.process_from_async_handler(payload)
68
82
  rescue StandardError
69
83
  # Here we swallow the exception:
@@ -3,7 +3,6 @@ module Rollbar
3
3
  class Encoder
4
4
  ALL_ENCODINGS = [::Encoding::UTF_8, ::Encoding::ISO_8859_1, ::Encoding::ASCII_8BIT, ::Encoding::US_ASCII].freeze
5
5
  ASCII_ENCODINGS = [::Encoding::US_ASCII, ::Encoding::ASCII_8BIT, ::Encoding::ISO_8859_1].freeze
6
- ENCODING_OPTIONS = { :invalid => :replace, :undef => :replace, :replace => '' }.freeze
7
6
  UTF8 = 'UTF-8'.freeze
8
7
  BINARY = 'binary'.freeze
9
8
 
@@ -21,7 +20,13 @@ module Rollbar
21
20
  encoded_value = if encoding == ::Encoding::UTF_8 && value.valid_encoding?
22
21
  value
23
22
  else
24
- force_encoding(value).encode(*encoding_args(value))
23
+ force_encoding(value).encode(
24
+ *encoding_args(value),
25
+ # Ruby 2.7 requires this to look like keyword args,
26
+ # and Ruby 1.9.3 doesn't understand keyword args, so
27
+ # don't use hash rockets here and both will be happy.
28
+ invalid: :replace, undef: :replace, replace: '' # rubocop:disable Style/HashSyntax
29
+ )
25
30
  end
26
31
 
27
32
  object.is_a?(Symbol) ? encoded_value.to_sym : encoded_value
@@ -54,7 +59,6 @@ module Rollbar
54
59
  def encoding_args(value)
55
60
  args = [UTF8]
56
61
  args << BINARY if ASCII_ENCODINGS.include?(value.encoding)
57
- args << ENCODING_OPTIONS
58
62
 
59
63
  args
60
64
  end
data/lib/rollbar/item.rb CHANGED
@@ -109,6 +109,11 @@ module Rollbar
109
109
  # the risk just to send this diagnostic object. In versions < 4.1, ActiveSupport hooks
110
110
  # Ruby's JSON.generate so deeply there's no workaround.
111
111
  'not serialized in ActiveSupport < 4.1'
112
+ elsif configuration.use_async && !configuration.async_json_payload
113
+ # The setting allows serialization to be performed by each handler,
114
+ # and this usually means it is actually performed by ActiveSupport,
115
+ # which cannot safely serialize this key.
116
+ 'not serialized when async_json_payload is not set'
112
117
  else
113
118
  scrub(configuration.configured_options.configured)
114
119
  end
@@ -178,13 +183,19 @@ module Rollbar
178
183
  end
179
184
 
180
185
  def build_extra
186
+ merged_extra = Util.deep_merge(scrub(extra), scrub(error_context))
187
+
181
188
  if custom_data_method? && !Rollbar::Util.method_in_stack(:custom_data, __FILE__)
182
- Util.deep_merge(scrub(custom_data), scrub(extra) || {})
189
+ Util.deep_merge(scrub(custom_data), merged_extra)
183
190
  else
184
- scrub(extra)
191
+ merged_extra.empty? ? nil : merged_extra # avoid putting an empty {} in the payload.
185
192
  end
186
193
  end
187
194
 
195
+ def error_context
196
+ exception.respond_to?(:rollbar_context) && exception.rollbar_context
197
+ end
198
+
188
199
  def scrub(data)
189
200
  return data unless data.is_a? Hash
190
201
 
@@ -55,7 +55,7 @@ module Rollbar
55
55
  current_exception = exception
56
56
 
57
57
  while current_exception.respond_to?(:cause) && (cause = current_exception.cause) && cause.is_a?(Exception) && !visited.include?(cause)
58
- traces << trace_data(cause)
58
+ traces.unshift(trace_data(cause))
59
59
  visited << cause
60
60
  current_exception = cause
61
61
  end
@@ -74,10 +74,20 @@ module Rollbar
74
74
  end
75
75
 
76
76
  def map_frames(current_exception)
77
- exception_backtrace(current_exception).map do |frame|
77
+ frames = cleaned_backtrace(current_exception).map do |frame|
78
78
  Rollbar::Item::Frame.new(self, frame,
79
79
  :configuration => configuration).to_h
80
- end.reverse
80
+ end
81
+ frames.reverse!
82
+ end
83
+
84
+ def cleaned_backtrace(current_exception)
85
+ normalized_backtrace = exception_backtrace(current_exception)
86
+ if configuration.backtrace_cleaner
87
+ configuration.backtrace_cleaner.clean(normalized_backtrace)
88
+ else
89
+ normalized_backtrace
90
+ end
81
91
  end
82
92
 
83
93
  # Returns the backtrace to be sent to our API. There are 3 options:
@@ -97,6 +97,8 @@ module Rollbar
97
97
  end
98
98
 
99
99
  def locals_data(filename, lineno)
100
+ return unless configuration.locals[:enabled]
101
+
100
102
  ::Rollbar::Item::Locals.locals_for_location(filename, lineno)
101
103
  end
102
104
 
@@ -1,5 +1,6 @@
1
1
  require 'rollbar/notifier'
2
2
  require 'rollbar/scrubbers/params'
3
+ require 'rollbar/util'
3
4
 
4
5
  module Rollbar
5
6
  class Item
@@ -39,8 +40,51 @@ module Rollbar
39
40
  end
40
41
  end
41
42
 
43
+ # Prepare objects to be handled by the payload serializer.
44
+ #
45
+ # Hashes and Arrays are traversed. Then all types execpt strings and
46
+ # immediates are exported using #inspect. Sending the object itself to the
47
+ # serializer can result in large recursive expansions, especially in Rails
48
+ # environments with ActiveRecord, ActiveSupport, etc. on the stack.
49
+ # Other export options could be #to_s, #to_h, and #as_json. Several of these
50
+ # will omit the class name, or are not implemented for many types.
51
+ #
52
+ # #inspect has the advantage that it is specifically intended for debugging
53
+ # output. If the user wants more or different information in the payload
54
+ # about a specific type, #inspect is the correct place to implement it.
55
+ # Likewise the default implementation should be oriented toward usefulness
56
+ # in debugging.
57
+ #
58
+ # Because #inspect outputs a string, it can be handled well by the string
59
+ # truncation strategy for large payloads.
60
+ #
42
61
  def prepare_value(value)
43
- value.to_s
62
+ return simple_value?(value) ? value : value.inspect unless value.is_a?(Hash) || value.is_a?(Array)
63
+
64
+ cloned_value = ::Rollbar::Util.deep_copy(value)
65
+ ::Rollbar::Util.iterate_and_update_with_block(cloned_value) do |v|
66
+ simple_value?(v) ? v : v.inspect
67
+ end
68
+
69
+ cloned_value
70
+ end
71
+
72
+ def simple_classes
73
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.4.0')
74
+ [String, Symbol, Integer, Float, TrueClass, FalseClass, NilClass]
75
+ else
76
+ [String, Symbol, Fixnum, Bignum, Float, TrueClass, FalseClass, NilClass] # rubocop:disable Lint/UnifiedInteger
77
+ end
78
+ end
79
+
80
+ def simple_value?(value)
81
+ simple_classes.each do |klass|
82
+ # Use instance_of? so that subclasses and module containers will
83
+ # be treated like complex object types, not simple values.
84
+ return true if value.instance_of?(klass)
85
+ end
86
+
87
+ false
44
88
  end
45
89
 
46
90
  def scrub(hash)
@@ -83,7 +83,12 @@ module Rollbar
83
83
  response = ::Rack::Response.new(response_string, app_result[0],
84
84
  app_result[1])
85
85
 
86
- response.finish
86
+ finished = response.finish
87
+
88
+ # Rack < 2.x Response#finish returns self in array[2]. Rack >= 2.x returns self.body.
89
+ # Always return with the response object here regardless of rack version.
90
+ finished[2] = response
91
+ finished
87
92
  end
88
93
 
89
94
  def build_body_with_js(env, body, head_open_end)
@@ -19,7 +19,8 @@ module Rollbar
19
19
  attr_accessor :last_report
20
20
  attr_accessor :scope_object
21
21
 
22
- @file_semaphore = Mutex.new
22
+ MUTEX = Mutex.new
23
+ EXTENSION_REGEXP = /.rollbar\z/.freeze
23
24
 
24
25
  def initialize(parent_notifier = nil, payload_options = nil, scope = nil)
25
26
  if parent_notifier
@@ -200,18 +201,20 @@ module Rollbar
200
201
  def process_item(item)
201
202
  if configuration.write_to_file
202
203
  if configuration.use_async
203
- @file_semaphore.synchronize do
204
- write_item(item)
204
+ MUTEX.synchronize do
205
+ do_write_item(item)
205
206
  end
206
207
  else
207
- write_item(item)
208
+ do_write_item(item)
208
209
  end
209
210
  else
210
211
  send_item(item)
211
212
  end
212
213
  rescue StandardError => e
213
214
  log_error("[Rollbar] Error processing the item: #{e.class}, #{e.message}. Item: #{item.payload.inspect}")
214
- raise e
215
+ raise e unless via_failsafe?(item)
216
+
217
+ log_error('[Rollbar] Item has already failed. Not re-raising')
215
218
  end
216
219
 
217
220
  # We will reraise exceptions in this method so async queues
@@ -238,16 +241,19 @@ module Rollbar
238
241
  # Using Rollbar.silenced we avoid the above behavior but Sidekiq
239
242
  # will have a chance to retry the original job.
240
243
  def process_from_async_handler(payload)
241
- payload = Rollbar::JSON.load(payload) if payload.is_a?(String)
242
-
243
- item = Item.build_with(payload,
244
- :notifier => self,
245
- :configuration => configuration,
246
- :logger => logger)
247
-
248
244
  Rollbar.silenced do
249
245
  begin
250
- process_item(item)
246
+ if payload.is_a?(String)
247
+ # The final payload has already been built.
248
+ send_body(payload)
249
+ else
250
+ item = Item.build_with(payload,
251
+ :notifier => self,
252
+ :configuration => configuration,
253
+ :logger => logger)
254
+
255
+ process_item(item)
256
+ end
251
257
  rescue StandardError => e
252
258
  report_internal_error(e)
253
259
 
@@ -509,14 +515,18 @@ module Rollbar
509
515
 
510
516
  ## Delivery functions
511
517
 
512
- def send_item_using_eventmachine(item, uri)
513
- body = item.dump
514
- return unless body
518
+ def send_using_eventmachine(body)
519
+ uri = URI.parse(configuration.endpoint)
515
520
 
516
- headers = { 'X-Rollbar-Access-Token' => item['access_token'] }
521
+ headers = { 'X-Rollbar-Access-Token' => configuration.access_token }
517
522
  options = http_proxy_for_em(uri)
518
523
  req = EventMachine::HttpRequest.new(uri.to_s, options).post(:body => body, :head => headers)
519
524
 
525
+ eventmachine_callback(req)
526
+ eventmachine_errback(req)
527
+ end
528
+
529
+ def eventmachine_callback(req)
520
530
  req.callback do
521
531
  if req.response_header.status == 200
522
532
  log_info '[Rollbar] Success'
@@ -525,7 +535,9 @@ module Rollbar
525
535
  log_info "[Rollbar] Response: #{req.response}"
526
536
  end
527
537
  end
538
+ end
528
539
 
540
+ def eventmachine_errback(req)
529
541
  req.errback do
530
542
  log_warning "[Rollbar] Call to API failed, status code: #{req.response_header.status}"
531
543
  log_info "[Rollbar] Error's response: #{req.response}"
@@ -538,14 +550,20 @@ module Rollbar
538
550
  body = item.dump
539
551
  return unless body
540
552
 
541
- uri = URI.parse(configuration.endpoint)
542
-
543
553
  if configuration.use_eventmachine
544
- send_item_using_eventmachine(item, uri)
554
+ send_using_eventmachine(body)
545
555
  return
546
556
  end
547
557
 
548
- handle_response(do_post(uri, body, item['access_token']))
558
+ send_body(body)
559
+ end
560
+
561
+ def send_body(body)
562
+ log_info '[Rollbar] Sending json'
563
+
564
+ uri = URI.parse(configuration.endpoint)
565
+
566
+ handle_response(do_post(uri, body, configuration.access_token))
549
567
  end
550
568
 
551
569
  def do_post(uri, body, access_token)
@@ -658,27 +676,24 @@ module Rollbar
658
676
  end
659
677
  end
660
678
 
661
- def write_item(item)
662
- if configuration.use_async
663
- @file_semaphore.synchronize do
664
- do_write_item(item)
665
- end
666
- else
667
- do_write_item(item)
668
- end
669
- end
670
-
671
679
  def do_write_item(item)
672
680
  log_info '[Rollbar] Writing item to file'
673
681
 
674
682
  body = item.dump
675
683
  return unless body
676
684
 
685
+ file_name = if configuration.files_with_pid_name_enabled
686
+ configuration.filepath.gsub(EXTENSION_REGEXP, "_#{Process.pid}\\0")
687
+ else
688
+ configuration.filepath
689
+ end
690
+
677
691
  begin
678
- @file ||= File.open(configuration.filepath, 'a')
692
+ @file ||= File.open(file_name, 'a')
679
693
 
680
694
  @file.puts(body)
681
695
  @file.flush
696
+ update_file(@file, file_name)
682
697
 
683
698
  log_info '[Rollbar] Success'
684
699
  rescue IOError => e
@@ -686,6 +701,18 @@ module Rollbar
686
701
  end
687
702
  end
688
703
 
704
+ def update_file(file, file_name)
705
+ return unless configuration.files_processed_enabled
706
+
707
+ time_now = Time.now
708
+ return if configuration.files_processed_duration > time_now - file.birthtime && file.size < configuration.files_processed_size
709
+
710
+ new_file_name = file_name.gsub(EXTENSION_REGEXP, "_processed_#{time_now.to_i}\\0")
711
+ File.rename(file, new_file_name)
712
+ file.close
713
+ @file = File.open(file_name, 'a')
714
+ end
715
+
689
716
  def failsafe_reason(message, exception)
690
717
  body = ''
691
718
 
@@ -737,8 +764,11 @@ module Rollbar
737
764
  end
738
765
 
739
766
  def process_async_item(item)
767
+ # Send async payloads as JSON string when async_json_payload is set.
768
+ payload = configuration.async_json_payload ? item.dump : item.payload
769
+
740
770
  configuration.async_handler ||= default_async_handler
741
- configuration.async_handler.call(item.payload)
771
+ configuration.async_handler.call(payload)
742
772
  rescue StandardError
743
773
  if configuration.failover_handlers.empty?
744
774
  log_error '[Rollbar] Async handler failed, and there are no failover handlers configured. See the docs for "failover_handlers"'
@@ -772,5 +802,9 @@ module Rollbar
772
802
  uuid_url = Util.uuid_rollbar_url(data, configuration)
773
803
  log_info "[Rollbar] Details: #{uuid_url} (only available if report was successful)"
774
804
  end
805
+
806
+ def via_failsafe?(item)
807
+ item.payload.fetch('data', {}).fetch(:failsafe, false)
808
+ end
775
809
  end
776
810
  end
@@ -14,5 +14,9 @@ module Rollbar
14
14
  end
15
15
  end
16
16
 
17
- # Automatically add to ActionMailer::DeliveryJob
18
- ActionMailer::DeliveryJob.send(:include, Rollbar::ActiveJob) if defined?(ActionMailer::DeliveryJob)
17
+ if defined?(ActiveSupport) && ActiveSupport.respond_to?(:on_load)
18
+ ActiveSupport.on_load(:action_mailer) do
19
+ # Automatically add to ActionMailer::DeliveryJob
20
+ ActionMailer::DeliveryJob.send(:include, Rollbar::ActiveJob) if defined?(ActionMailer::DeliveryJob)
21
+ end
22
+ end
@@ -12,7 +12,13 @@ module Rollbar
12
12
  lifecycle.around(:invoke_job, &Delayed.invoke_job_callback)
13
13
  lifecycle.after(:failure) do |_, job, _, _|
14
14
  data = Rollbar::Delayed.build_job_data(job)
15
- ::Rollbar.scope(:request => data).error("Job has failed and won't be retried anymore: " + job.last_error, :use_exception_level_filters => true) if job.last_error
15
+
16
+ # DelayedJob < 4.1 doesn't provide job#error
17
+ if job.class.method_defined? :error
18
+ ::Rollbar.scope(:request => data).error(job.error, :use_exception_level_filters => true) if job.error
19
+ elsif job.last_error
20
+ ::Rollbar.scope(:request => data).error("Job has failed and won't be retried anymore: " + job.last_error, :use_exception_level_filters => true)
21
+ end
16
22
  end
17
23
  end
18
24
  end
@@ -0,0 +1,11 @@
1
+ module RollbarErrorContext
2
+ attr_accessor :rollbar_context
3
+ end
4
+
5
+ Rollbar.plugins.define('error_context') do
6
+ dependency { configuration.enable_error_context }
7
+
8
+ execute! do
9
+ StandardError.send(:include, RollbarErrorContext)
10
+ end
11
+ end
@@ -247,7 +247,12 @@ module Rollbar
247
247
  end
248
248
 
249
249
  def sensitive_headers_list
250
- Rollbar.configuration.scrub_headers || []
250
+ return [] unless Rollbar.configuration.scrub_headers && Rollbar.configuration.scrub_headers.is_a?(Array)
251
+
252
+ # Normalize into the expected matching format
253
+ Rollbar.configuration.scrub_headers.map do |header|
254
+ header.split(/[-_]/).map(&:capitalize).join('-').gsub(/^Http-/, '')
255
+ end
251
256
  end
252
257
  end
253
258
  end
@@ -6,11 +6,7 @@ module Rollbar
6
6
  if Rollbar.configuration.randomize_scrub_length
7
7
  random_filtered_value
8
8
  else
9
- '*' * (begin
10
- value.length
11
- rescue StandardError
12
- 8
13
- end)
9
+ '*' * 6
14
10
  end
15
11
  end
16
12
 
@@ -11,7 +11,7 @@ module Rollbar
11
11
  end
12
12
 
13
13
  def call(payload)
14
- new_payload = Rollbar::Util.deep_copy(payload)
14
+ new_payload = payload
15
15
  body = new_payload['data']['body']
16
16
 
17
17
  if body['trace_chain']
@@ -9,7 +9,7 @@ module Rollbar
9
9
  result.bytesize > MAX_PAYLOAD_SIZE
10
10
  end
11
11
 
12
- def select_frames(frames, range = 150)
12
+ def select_frames(frames, range = 50)
13
13
  return frames unless frames.count > range * 2
14
14
 
15
15
  frames[0, range] + frames[-range, range]
@@ -6,7 +6,7 @@ module Rollbar
6
6
  class StringsStrategy
7
7
  include ::Rollbar::Truncation::Mixin
8
8
 
9
- STRING_THRESHOLDS = [1024, 512, 256].freeze
9
+ STRING_THRESHOLDS = [1024, 512, 256, 128].freeze
10
10
 
11
11
  def self.call(payload)
12
12
  new.call(payload)
@@ -29,7 +29,9 @@ module Rollbar
29
29
 
30
30
  def truncate_strings_proc(threshold)
31
31
  proc do |value|
32
- if value.is_a?(String) && value.bytesize > threshold
32
+ # Rollbar::Util.truncate will operate on characters, not bytes,
33
+ # so use value.length, not bytesize.
34
+ if value.is_a?(String) && value.length > threshold
33
35
  Rollbar::Util.truncate(value, threshold)
34
36
  else
35
37
  value
data/lib/rollbar/util.rb CHANGED
@@ -2,6 +2,10 @@ require 'rollbar/util/hash'
2
2
 
3
3
  module Rollbar
4
4
  module Util # :nodoc:
5
+ def self.iterate_and_update_with_block(obj, &block)
6
+ iterate_and_update(obj, block)
7
+ end
8
+
5
9
  def self.iterate_and_update(obj, block, seen = {})
6
10
  return if obj.frozen? || seen[obj.object_id]
7
11
 
@@ -1,3 +1,3 @@
1
1
  module Rollbar
2
- VERSION = '2.22.0'.freeze
2
+ VERSION = '2.24.0'.freeze
3
3
  end
data/rollbar.gemspec CHANGED
@@ -13,6 +13,7 @@ Gem::Specification.new do |gem|
13
13
  gem.homepage = 'https://rollbar.com'
14
14
  gem.license = 'MIT'
15
15
  gem.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ gem.files += ['spec/support/rollbar_api.rb'] # useful helper for app spec/tests.
16
17
  gem.name = 'rollbar'
17
18
  gem.require_paths = ['lib']
18
19
  gem.required_ruby_version = '>= 1.9.3'
@@ -0,0 +1,67 @@
1
+ require 'rack/request'
2
+
3
+ class RollbarAPI
4
+ UNAUTHORIZED_ACCESS_TOKEN = 'unauthorized'.freeze
5
+
6
+ def call(env)
7
+ request = Rack::Request.new(env)
8
+ json = JSON.parse(request.body.read)
9
+
10
+ return unauthorized unless authorized?(json, request)
11
+
12
+ return bad_request(json) unless valid_data?(json, request)
13
+
14
+ success(json, request)
15
+ end
16
+
17
+ protected
18
+
19
+ def authorized?(json, _request)
20
+ json['access_token'] != UNAUTHORIZED_ACCESS_TOKEN
21
+ end
22
+
23
+ def response_headers
24
+ {
25
+ 'Content-Type' => 'application/json'
26
+ }
27
+ end
28
+
29
+ def valid_data?(json, _request)
30
+ !!json['access_token']
31
+ end
32
+
33
+ def unauthorized
34
+ [401, response_headers, [unauthorized_body]]
35
+ end
36
+
37
+ def bad_request(_json)
38
+ [400, response_headers, [bad_request_body]]
39
+ end
40
+
41
+ def success(json, request)
42
+ [200, response_headers, [success_body(json, request)]]
43
+ end
44
+
45
+ def unauthorized_body
46
+ result(1, nil, 'invalid access token')
47
+ end
48
+
49
+ def bad_request_body
50
+ result(1, nil, 'bad request')
51
+ end
52
+
53
+ def success_body(json, _request)
54
+ result(0, {
55
+ :id => rand(1_000_000),
56
+ :uuid => json['data']['uuid']
57
+ }, nil)
58
+ end
59
+
60
+ def result(err, body, message)
61
+ {
62
+ :err => err,
63
+ :result => body,
64
+ :message => message
65
+ }.to_json
66
+ end
67
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rollbar
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.22.0
4
+ version: 2.24.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rollbar, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-23 00:00:00.000000000 Z
11
+ date: 2020-02-14 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Easy and powerful exception tracking for Ruby
14
14
  email:
@@ -95,6 +95,7 @@ files:
95
95
  - lib/rollbar/plugins/delayed_job.rb
96
96
  - lib/rollbar/plugins/delayed_job/job_data.rb
97
97
  - lib/rollbar/plugins/delayed_job/plugin.rb
98
+ - lib/rollbar/plugins/error_context.rb
98
99
  - lib/rollbar/plugins/goalie.rb
99
100
  - lib/rollbar/plugins/rack.rb
100
101
  - lib/rollbar/plugins/rails.rb
@@ -133,6 +134,7 @@ files:
133
134
  - lib/tasks/benchmark.rake
134
135
  - lib/tasks/tasks.rake
135
136
  - rollbar.gemspec
137
+ - spec/support/rollbar_api.rb
136
138
  homepage: https://rollbar.com
137
139
  licenses:
138
140
  - MIT