rollbar 2.24.0 → 2.25.1

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) => 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.0",
3
+ "version": "2.25.1",
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",
@@ -66,7 +65,6 @@
66
65
  "karma-sourcemap-loader": "^0.3.5",
67
66
  "karma-webpack": "^4.0.2",
68
67
  "mocha": "^7.1.2",
69
- "mootools": "^1.5.1",
70
68
  "natives": "^1.1.6",
71
69
  "nock": "^11.9.1",
72
70
  "node-libs-browser": "^0.5.2",
@@ -78,7 +76,7 @@
78
76
  "strict-loader": "^1.2.0",
79
77
  "time-grunt": "^1.0.0",
80
78
  "vows": "^0.8.3",
81
- "webpack": "^4.41.5"
79
+ "webpack": "^4.46.0"
82
80
  },
83
81
  "optionalDependencies": {
84
82
  "decache": "^3.0.5"
package/src/api.js CHANGED
@@ -47,7 +47,12 @@ function Api(options, transport, urllib, truncation, jsonBackup) {
47
47
  Api.prototype.postItem = function(data, callback) {
48
48
  var transportOptions = helpers.transportOptions(this.transportOptions, 'POST');
49
49
  var payload = helpers.buildPayload(this.accessToken, data, this.jsonBackup);
50
- this.transport.post(this.accessToken, transportOptions, payload, callback);
50
+ var self = this;
51
+
52
+ // ensure the network request is scheduled after the current tick.
53
+ setTimeout(function() {
54
+ self.transport.post(self.accessToken, transportOptions, payload, callback);
55
+ }, 0);
51
56
  };
52
57
 
53
58
  /**
@@ -62,9 +62,16 @@ function setupShim(window, options) {
62
62
  globals.captureUnhandledRejections(window, handler, true);
63
63
  }
64
64
 
65
+ function pageTelemetryEnabled(ai) {
66
+ if (typeof ai === 'object' && (ai.page === undefined || ai.page)) {
67
+ return true;
68
+ }
69
+ return false;
70
+ }
71
+
65
72
  var ai = options.autoInstrument;
66
73
  if (options.enabled !== false) {
67
- if (ai === undefined || ai === true || (typeof ai === 'object' && ai.network)) {
74
+ if (ai === undefined || ai === true || pageTelemetryEnabled(ai)) {
68
75
  if (window.addEventListener) {
69
76
  window.addEventListener('load', handler.captureLoad.bind(handler));
70
77
  window.addEventListener('DOMContentLoaded', handler.captureDomContentLoaded.bind(handler));
@@ -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.0',
2
+ version: '2.25.1',
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
 
package/src/utility.js CHANGED
@@ -398,6 +398,37 @@ function wrapCallback(logger, f) {
398
398
  };
399
399
  }
400
400
 
401
+ function nonCircularClone(obj) {
402
+ var seen = [obj];
403
+
404
+ function clone(obj, seen) {
405
+ var value, name, newSeen, result = {};
406
+
407
+ try {
408
+ for (name in obj) {
409
+ value = obj[name];
410
+
411
+ if (value && (isType(value, 'object') || isType(value, 'array'))) {
412
+ if (seen.includes(value)) {
413
+ result[name] = 'Removed circular reference: ' + typeName(value);
414
+ } else {
415
+ newSeen = seen.slice();
416
+ newSeen.push(value);
417
+ result[name] = clone(value, newSeen);
418
+ }
419
+ continue;
420
+ }
421
+
422
+ result[name] = value;
423
+ }
424
+ } catch (e) {
425
+ result = 'Failed cloning custom data: ' + e.message;
426
+ }
427
+ return result;
428
+ }
429
+ return clone(obj, seen);
430
+ }
431
+
401
432
  function createItem(args, logger, notifier, requestKeys, lambdaContext) {
402
433
  var message, err, custom, callback, request;
403
434
  var arg;
@@ -455,10 +486,12 @@ function createItem(args, logger, notifier, requestKeys, lambdaContext) {
455
486
  }
456
487
  }
457
488
 
489
+ // if custom is an array this turns it into an object with integer keys
490
+ if (custom) custom = nonCircularClone(custom);
491
+
458
492
  if (extraArgs.length > 0) {
459
- // if custom is an array this turns it into an object with integer keys
460
- custom = merge(custom);
461
- custom.extraArgs = extraArgs;
493
+ if (!custom) custom = nonCircularClone({});
494
+ custom.extraArgs = nonCircularClone(extraArgs);
462
495
  }
463
496
 
464
497
  var item = {
@@ -503,7 +536,7 @@ function addErrorContext(item, errors) {
503
536
  try {
504
537
  for (var i = 0; i < errors.length; ++i) {
505
538
  if (errors[i].hasOwnProperty('rollbarContext')) {
506
- custom = merge(custom, errors[i].rollbarContext);
539
+ custom = merge(custom, nonCircularClone(errors[i].rollbarContext));
507
540
  contextAdded = true;
508
541
  }
509
542
  }