rollbar 2.24.1 → 2.25.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.
package/index.d.ts CHANGED
@@ -40,6 +40,9 @@ declare namespace Rollbar {
40
40
  ) => void | Promise<TResult>;
41
41
  export type MaybeError = Error | undefined | null;
42
42
  export type Level = "debug" | "info" | "warning" | "error" | "critical";
43
+ /**
44
+ * {@link https://docs.rollbar.com/docs/rollbarjs-configuration-reference#reference}
45
+ */
43
46
  export interface Configuration {
44
47
  accessToken?: string;
45
48
  addErrorContext?: boolean;
@@ -52,7 +55,15 @@ declare namespace Rollbar {
52
55
  captureUnhandledRejections?: boolean;
53
56
  captureUsername?: boolean;
54
57
  checkIgnore?: (isUncaught: boolean, args: LogArgument[], item: object) => boolean;
58
+ /**
59
+ * `codeVersion` takes precedence over `code_version`, if provided.
60
+ * `client.javascript.code_version` takes precedence over both top level properties.
61
+ */
55
62
  codeVersion?: string;
63
+ /**
64
+ * `codeVersion` takes precedence over `code_version`, if provided.
65
+ * `client.javascript.code_version` takes precedence over both top level properties.
66
+ */
56
67
  code_version?: string;
57
68
  enabled?: boolean;
58
69
  endpoint?: string;
@@ -77,7 +88,7 @@ declare namespace Rollbar {
77
88
  nodeSourceMaps?: boolean;
78
89
  onSendCallback?: (isUncaught: boolean, args: LogArgument[], item: object) => void;
79
90
  overwriteScrubFields?: boolean;
80
- payload?: object;
91
+ payload?: Payload;
81
92
  reportLevel?: Level;
82
93
  rewriteFilenamePatterns?: string[];
83
94
  scrubFields?: string[];
@@ -89,7 +100,7 @@ declare namespace Rollbar {
89
100
  stackTraceLimit?: number;
90
101
  telemetryScrubber?: TelemetryScrubber;
91
102
  timeout?: number;
92
- transform?: (data: object, item: object) => void;
103
+ transform?: (data: object, item: object) => void | Promise<void>;
93
104
  transmit?: boolean;
94
105
  uncaughtErrorLevel?: Level;
95
106
  verbose?: boolean;
@@ -143,7 +154,7 @@ declare namespace Rollbar {
143
154
  export type LocalsType = typeof Locals;
144
155
  export type LocalsOptions = LocalsType | LocalsSettings;
145
156
  export interface LocalsSettings {
146
- locals: LocalsType,
157
+ module: LocalsType,
147
158
  enabled?: boolean;
148
159
  uncaughtOnly?: boolean;
149
160
  depth?: number;
@@ -169,4 +180,73 @@ declare namespace Rollbar {
169
180
  scrub?: ScrubType,
170
181
  truncation?: TruncationType
171
182
  }
183
+
184
+ /**
185
+ * @deprecated number is deprecated for this field
186
+ */
187
+ export type DeprecatedNumber = number;
188
+
189
+ /**
190
+ * {@link https://docs.rollbar.com/docs/rollbarjs-configuration-reference#payload-1}
191
+ */
192
+ export interface Payload {
193
+ person?: {
194
+ id: string | DeprecatedNumber;
195
+ username?: string;
196
+ email?: string;
197
+ [property: string]: any;
198
+ },
199
+ context?: any;
200
+ client?: {
201
+ javascript?: {
202
+ /**
203
+ * Version control number (i.e. git SHA) of the current revision. Used for linking filenames in stacktraces to GitHub.
204
+ * Note: for the purposes of nesting under the payload key, only code_version will correctly set the value in the final item.
205
+ * However, if you wish to set this code version at the top level of the configuration object rather than nested under
206
+ * the payload key, we will accept both codeVersion and code_version with codeVersion given preference if both happened
207
+ * to be defined. Furthermore, if code_version is nested under the payload key this will have the final preference over
208
+ * any value set at the top level.
209
+ */
210
+ code_version?: string | DeprecatedNumber;
211
+ /**
212
+ * When true, the Rollbar service will attempt to find and apply source maps to all frames in the stack trace.
213
+ * @default false
214
+ */
215
+ source_map_enabled?: boolean;
216
+ /**
217
+ * When true, the Rollbar service will attempt to apply source maps to frames even if they are missing column numbers.
218
+ * Works best when the minified javascript file is generated using newlines instead of semicolons.
219
+ * @default false
220
+ */
221
+ guess_uncaught_frames?: boolean;
222
+ [property: string]: any;
223
+ }
224
+ [property: string]: any;
225
+ },
226
+ /**
227
+ * The environment that your code is running in.
228
+ * @default undefined
229
+ */
230
+ environment?: string;
231
+ server?: {
232
+ /**
233
+ * @default master
234
+ */
235
+ branch?: string;
236
+ /**
237
+ * The hostname of the machine that rendered the page.
238
+ */
239
+ host?: string;
240
+ /**
241
+ * It is used in two different ways: `source maps`, and `source control`.
242
+ *
243
+ * If you are looking for more information on it please go to:
244
+ * {@link https://docs.rollbar.com/docs/source-maps}
245
+ * {@link https://docs.rollbar.com/docs/source-control}
246
+ */
247
+ root?: string;
248
+ [property: string]: any;
249
+ },
250
+ [property: string]: any;
251
+ }
172
252
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rollbar",
3
- "version": "2.24.1",
3
+ "version": "2.25.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "http://github.com/rollbar/rollbar.js"
@@ -11,14 +11,13 @@
11
11
  "browser": "dist/rollbar.umd.min.js",
12
12
  "types": "./index.d.ts",
13
13
  "dependencies": {
14
- "async": "~1.2.1",
14
+ "async": "~3.2.3",
15
15
  "console-polyfill": "0.3.0",
16
16
  "error-stack-parser": "^2.0.4",
17
17
  "json-stringify-safe": "~5.0.0",
18
18
  "lru-cache": "~2.2.1",
19
19
  "request-ip": "~2.0.1",
20
- "source-map": "^0.5.7",
21
- "uuid": "3.0.x"
20
+ "source-map": "^0.5.7"
22
21
  },
23
22
  "devDependencies": {
24
23
  "babel-core": "^6.26.3",
@@ -403,8 +403,10 @@ Instrumenter.prototype.instrumentNetwork = function() {
403
403
  // Test to ensure body is a Promise, which it should always be.
404
404
  if (typeof body.then === 'function') {
405
405
  body.then(function (text) {
406
- if (self.isJsonContentType(metadata.response_content_type)) {
406
+ if (text && self.isJsonContentType(metadata.response_content_type)) {
407
407
  metadata.response.body = self.scrubJson(text);
408
+ } else {
409
+ metadata.response.body = text;
408
410
  }
409
411
  });
410
412
  } else {
@@ -729,16 +731,16 @@ Instrumenter.prototype.handleCspError = function(message) {
729
731
  }
730
732
 
731
733
  Instrumenter.prototype.deinstrumentContentSecurityPolicy = function() {
732
- if (!('addEventListener' in this._window)) { return; }
734
+ if (!('addEventListener' in this._document)) { return; }
733
735
 
734
736
  this.removeListeners('contentsecuritypolicy');
735
737
  };
736
738
 
737
739
  Instrumenter.prototype.instrumentContentSecurityPolicy = function() {
738
- if (!('addEventListener' in this._window)) { return; }
740
+ if (!('addEventListener' in this._document)) { return; }
739
741
 
740
742
  var cspHandler = this.handleCspEvent.bind(this);
741
- this.addListener('contentsecuritypolicy', this._window, 'securitypolicyviolation', null, cspHandler, false);
743
+ this.addListener('contentsecuritypolicy', this._document, 'securitypolicyviolation', null, cspHandler, false);
742
744
  };
743
745
 
744
746
  Instrumenter.prototype.addListener = function(section, obj, type, altType, handler, capture) {
@@ -42,8 +42,8 @@ function addErrorContext(item) {
42
42
 
43
43
  chain.push(err);
44
44
 
45
- while (err.nested) {
46
- err = err.nested;
45
+ while (err.nested || err.cause) {
46
+ err = err.nested || err.cause;
47
47
  chain.push(err);
48
48
  }
49
49
 
package/src/defaults.js CHANGED
@@ -1,5 +1,5 @@
1
1
  module.exports = {
2
- version: '2.24.1',
2
+ version: '2.25.0',
3
3
  endpoint: 'api.rollbar.com/api/1/item/',
4
4
  logLevel: 'debug',
5
5
  reportLevel: 'debug',
@@ -64,11 +64,11 @@ function Stack(exception, skip) {
64
64
  function parse(e, skip) {
65
65
  var err = e;
66
66
 
67
- if (err.nested) {
67
+ if (err.nested || err.cause) {
68
68
  var traceChain = [];
69
69
  while (err) {
70
70
  traceChain.push(new Stack(err, skip));
71
- err = err.nested;
71
+ err = err.nested || err.cause;
72
72
 
73
73
  skip = 0; // Only apply skip value to primary error
74
74
  }
@@ -181,7 +181,7 @@ function shouldReadFrameFile(frameFilename, callback) {
181
181
  isCached = !!cache.get(frameFilename);
182
182
  isPending = !!pendingReads[frameFilename];
183
183
 
184
- callback(isValidFilename && !isCached && !isPending);
184
+ callback(null, isValidFilename && !isCached && !isPending);
185
185
  }
186
186
 
187
187
 
@@ -201,19 +201,13 @@ function readFileLines(filename, callback) {
201
201
  }
202
202
  }
203
203
 
204
-
205
- /* Older versions of node do not have fs.exists so we implement our own */
206
204
  function checkFileExists(filename, callback) {
207
205
  if (stackTrace.sourceContent(filename)) {
208
- return callback(true);
209
- }
210
- if (fs.exists !== undefined) {
211
- fs.exists(filename, callback);
212
- } else {
213
- fs.stat(filename, function (err) {
214
- callback(!err);
215
- });
206
+ return callback(null, true);
216
207
  }
208
+ fs.stat(filename, function (err) {
209
+ callback(null, !err);
210
+ });
217
211
  }
218
212
 
219
213
 
@@ -226,7 +220,9 @@ function gatherContexts(frames, callback) {
226
220
  }
227
221
  });
228
222
 
229
- async.filter(frameFilenames, shouldReadFrameFile, function (results) {
223
+ async.filter(frameFilenames, shouldReadFrameFile, function (err, results) {
224
+ if (err) return callback(err);
225
+
230
226
  var tempFileCache;
231
227
 
232
228
  tempFileCache = {};
@@ -270,7 +266,8 @@ function gatherContexts(frames, callback) {
270
266
  callback(null);
271
267
  }
272
268
 
273
- async.filter(results, checkFileExists, function (filenames) {
269
+ async.filter(results, checkFileExists, function (err, filenames) {
270
+ if (err) return callback(err);
274
271
  async.each(filenames, gatherFileData, function (err) {
275
272
  if (err) {
276
273
  return callback(err);
@@ -367,7 +364,8 @@ exports.parseStack = function (stack, options, item, callback) {
367
364
  return callback(err);
368
365
  }
369
366
  frames.reverse();
370
- async.filter(frames, function (frame, callback) { callback(!!frame); }, function (results) {
367
+ async.filter(frames, function (frame, callback) { callback(null, !!frame); }, function (err, results) {
368
+ if (err) return callback(err);
371
369
  gatherContexts(results, callback);
372
370
  });
373
371
  });
@@ -85,7 +85,7 @@ function handleItemWithError(item, options, callback) {
85
85
  var chain = [];
86
86
  do {
87
87
  errors.push(err);
88
- err = err.nested;
88
+ err = err.nested || err.cause;
89
89
  } while (err);
90
90
  item.stackInfo = chain;
91
91
 
@@ -30,6 +30,10 @@ function itemFromArgs(args) {
30
30
  return item;
31
31
  }
32
32
 
33
+ function chromeMajorVersion() {
34
+ return parseInt(navigator.userAgent.match(/Chrome\/([0-9]+)\./)[1]);
35
+ }
36
+
33
37
  describe('handleDomException', function() {
34
38
  it('should do nothing if not a DOMException', function(done) {
35
39
  var err = new Error('test');
@@ -452,6 +456,45 @@ describe('addBody', function() {
452
456
  });
453
457
  });
454
458
  });
459
+ describe('with error cause', function() {
460
+ // Error cause was introduced in Chrome 93.
461
+ if (chromeMajorVersion() < 93) return;
462
+
463
+ it('should create trace_chain', function(done) {
464
+ var causeErr = new Error('cause error');
465
+ var err = new Error('test error', { cause: causeErr});
466
+ var args = ['a message', err];
467
+ var item = itemFromArgs(args);
468
+ var options = {};
469
+ t.handleItemWithError(item, options, function(e, i) {
470
+ expect(i.stackInfo).to.be.ok();
471
+ });
472
+ t.addBody(item, options, function(e, i) {
473
+ expect(i.data.body.trace_chain.length).to.eql(2);
474
+ expect(i.data.body.trace_chain[0].exception.message).to.eql('test error');
475
+ expect(i.data.body.trace_chain[1].exception.message).to.eql('cause error');
476
+ done(e);
477
+ });
478
+ });
479
+ it('should create add error context as custom data', function(done) {
480
+ var causeErr = new Error('cause error');
481
+ causeErr.rollbarContext = { err1: 'cause context' };
482
+ var err = new Error('test error', { cause: causeErr});
483
+ err.rollbarContext = { err2: 'error context' };
484
+ var args = ['a message', err];
485
+ var item = itemFromArgs(args);
486
+ var options = { addErrorContext: true };
487
+ t.handleItemWithError(item, options, function(e, i) {
488
+ expect(i.stackInfo).to.be.ok();
489
+ });
490
+ t.addBody(item, options, function(e, i) {
491
+ expect(i.data.body.trace_chain.length).to.eql(2);
492
+ expect(i.data.custom.err1).to.eql('cause context');
493
+ expect(i.data.custom.err2).to.eql('error context');
494
+ done(e);
495
+ });
496
+ });
497
+ });
455
498
  });
456
499
 
457
500
  describe('scrubPayload', function() {
@@ -30,6 +30,22 @@ async function throwInScriptFile(rollbar, filepath, callback) {
30
30
  callback(rollbar);
31
31
  }
32
32
 
33
+ var nodeVersion = function () {
34
+ var version = process.versions.node.split('.');
35
+
36
+ return [
37
+ parseInt(version[0]),
38
+ parseInt(version[1]),
39
+ parseInt(version[2]),
40
+ ];
41
+ }();
42
+
43
+ var isMinNodeVersion = function(major, minor) {
44
+ return (
45
+ nodeVersion[0] > major || (nodeVersion[0] === major && nodeVersion[1] >= minor)
46
+ );
47
+ }
48
+
33
49
  vows.describe('transforms')
34
50
  .addBatch({
35
51
  'baseData': {
@@ -494,7 +510,42 @@ vows.describe('transforms')
494
510
  assert.equal(item.data.custom.err1, 'nested context');
495
511
  assert.equal(item.data.custom.err2, 'error context');
496
512
  }
497
- }
513
+ },
514
+ 'with an error cause': {
515
+ topic: function (options) {
516
+ var test = function() {
517
+ var x = thisVariableIsNotDefined;
518
+ };
519
+ var err;
520
+ try {
521
+ test();
522
+ } catch (e) {
523
+ err = new Error('cause message', { cause: e });
524
+ e.rollbarContext = { err1: 'cause context' };
525
+ err.rollbarContext = { err2: 'error context' };
526
+ }
527
+ var item = {
528
+ data: {body: {}},
529
+ err: err
530
+ };
531
+ t.handleItemWithError(item, options, this.callback);
532
+ },
533
+ 'should not error': function(err, item) {
534
+ assert.ifError(err);
535
+ },
536
+ 'should have the right data in the trace_chain': function(err, item) {
537
+ // Error cause was introduced in Node 16.9.
538
+ if (!isMinNodeVersion(16, 9)) return;
539
+
540
+ var trace_chain = item.stackInfo;
541
+ assert.lengthOf(trace_chain, 2);
542
+ assert.equal(trace_chain[0].exception.class, 'Error');
543
+ assert.equal(trace_chain[0].exception.message, 'cause message');
544
+ assert.equal(trace_chain[1].exception.class, 'ReferenceError');
545
+ assert.equal(item.data.custom.err1, 'cause context');
546
+ assert.equal(item.data.custom.err2, 'error context');
547
+ }
548
+ },
498
549
  }
499
550
  }
500
551
  }