rollbar 2.26.4 → 3.0.0-alpha.2
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/.claude/settings.local.json +3 -0
- package/.cursor/rules/guidelines.mdc +154 -0
- package/.github/workflows/ci.yml +4 -6
- package/CLAUDE.local.md +297 -0
- package/CLAUDE.md +201 -0
- package/CLAUDE.testrunner.md +470 -0
- package/Gruntfile.js +59 -16
- package/Makefile +3 -3
- package/SECURITY.md +5 -0
- package/babel.config.json +9 -0
- package/codex.md +148 -0
- package/dist/plugins/jquery.min.js +1 -1
- package/dist/rollbar.js +19332 -6596
- package/dist/rollbar.js.map +1 -1
- package/dist/rollbar.min.js +2 -1
- package/dist/rollbar.min.js.LICENSE.txt +1 -0
- package/dist/rollbar.min.js.map +1 -1
- package/dist/rollbar.named-amd.js +19332 -6596
- package/dist/rollbar.named-amd.js.map +1 -1
- package/dist/rollbar.named-amd.min.js +2 -1
- package/dist/rollbar.named-amd.min.js.LICENSE.txt +1 -0
- package/dist/rollbar.named-amd.min.js.map +1 -1
- package/dist/rollbar.noconflict.umd.js +19319 -6581
- package/dist/rollbar.noconflict.umd.js.map +1 -1
- package/dist/rollbar.noconflict.umd.min.js +2 -1
- package/dist/rollbar.noconflict.umd.min.js.LICENSE.txt +1 -0
- package/dist/rollbar.noconflict.umd.min.js.map +1 -1
- package/dist/rollbar.snippet.js +1 -1
- package/dist/rollbar.umd.js +19333 -6597
- package/dist/rollbar.umd.js.map +1 -1
- package/dist/rollbar.umd.min.js +2 -1
- package/dist/rollbar.umd.min.js.LICENSE.txt +1 -0
- package/dist/rollbar.umd.min.js.map +1 -1
- package/eslint.config.mjs +33 -0
- package/karma.conf.js +5 -14
- package/package.json +19 -20
- package/src/api.js +57 -4
- package/src/apiUtility.js +2 -3
- package/src/browser/core.js +37 -9
- package/src/browser/replay/defaults.js +70 -0
- package/src/browser/replay/recorder.js +194 -0
- package/src/browser/replay/replayMap.js +195 -0
- package/src/browser/rollbar.js +11 -7
- package/src/browser/telemetry.js +3 -3
- package/src/browser/transport/fetch.js +17 -4
- package/src/browser/transport/xhr.js +17 -1
- package/src/browser/transport.js +11 -8
- package/src/defaults.js +1 -1
- package/src/queue.js +65 -4
- package/src/react-native/rollbar.js +1 -1
- package/src/rollbar.js +52 -10
- package/src/server/rollbar.js +3 -2
- package/src/telemetry.js +76 -11
- package/src/tracing/context.js +24 -0
- package/src/tracing/contextManager.js +37 -0
- package/src/tracing/defaults.js +7 -0
- package/src/tracing/exporter.js +188 -0
- package/src/tracing/hrtime.js +98 -0
- package/src/tracing/id.js +24 -0
- package/src/tracing/session.js +55 -0
- package/src/tracing/span.js +92 -0
- package/src/tracing/spanProcessor.js +15 -0
- package/src/tracing/tracer.js +46 -0
- package/src/tracing/tracing.js +89 -0
- package/src/utility.js +34 -0
- package/test/api.test.js +57 -12
- package/test/apiUtility.test.js +5 -6
- package/test/browser.core.test.js +1 -10
- package/test/browser.domUtility.test.js +1 -1
- package/test/browser.predicates.test.js +1 -1
- package/test/browser.replay.recorder.test.js +430 -0
- package/test/browser.rollbar.test.js +58 -12
- package/test/browser.telemetry.test.js +1 -1
- package/test/browser.transforms.test.js +20 -13
- package/test/browser.transport.test.js +5 -4
- package/test/browser.url.test.js +1 -1
- package/test/fixtures/replay/index.js +20 -0
- package/test/fixtures/replay/payloads.fixtures.js +229 -0
- package/test/fixtures/replay/rrwebEvents.fixtures.js +251 -0
- package/test/fixtures/replay/rrwebSyntheticEvents.fixtures.js +328 -0
- package/test/notifier.test.js +1 -1
- package/test/predicates.test.js +1 -1
- package/test/queue.test.js +1 -1
- package/test/rateLimiter.test.js +1 -1
- package/test/react-native.rollbar.test.js +1 -1
- package/test/react-native.transforms.test.js +2 -2
- package/test/react-native.transport.test.js +3 -3
- package/test/replay/index.js +2 -0
- package/test/replay/integration/api.spans.test.js +136 -0
- package/test/replay/integration/e2e.test.js +228 -0
- package/test/replay/integration/index.js +9 -0
- package/test/replay/integration/queue.replayMap.test.js +332 -0
- package/test/replay/integration/replayMap.test.js +163 -0
- package/test/replay/integration/sessionRecording.test.js +390 -0
- package/test/replay/unit/api.postSpans.test.js +150 -0
- package/test/replay/unit/index.js +7 -0
- package/test/replay/unit/queue.replayMap.test.js +225 -0
- package/test/replay/unit/replayMap.test.js +348 -0
- package/test/replay/util/index.js +5 -0
- package/test/replay/util/mockRecordFn.js +80 -0
- package/test/server.lambda.mocha.test.mjs +172 -0
- package/test/server.locals.constructor.mocha.test.mjs +80 -0
- package/test/server.locals.error-handling.mocha.test.mjs +387 -0
- package/test/server.locals.merge.mocha.test.mjs +267 -0
- package/test/server.locals.test-utils.mjs +114 -0
- package/test/server.parser.mocha.test.mjs +87 -0
- package/test/server.predicates.mocha.test.mjs +63 -0
- package/test/server.rollbar.constructor.mocha.test.mjs +199 -0
- package/test/server.rollbar.handlers.mocha.test.mjs +253 -0
- package/test/server.rollbar.logging.mocha.test.mjs +326 -0
- package/test/server.rollbar.misc.mocha.test.mjs +44 -0
- package/test/server.rollbar.test-utils.mjs +57 -0
- package/test/server.telemetry.mocha.test.mjs +377 -0
- package/test/server.transforms.data.mocha.test.mjs +163 -0
- package/test/server.transforms.error.mocha.test.mjs +199 -0
- package/test/server.transforms.request.mocha.test.mjs +208 -0
- package/test/server.transforms.scrub.mocha.test.mjs +140 -0
- package/test/server.transforms.sourcemaps.mocha.test.mjs +122 -0
- package/test/server.transforms.test-utils.mjs +62 -0
- package/test/server.transport.mocha.test.mjs +269 -0
- package/test/telemetry.test.js +132 -1
- package/test/tracing/contextManager.test.js +28 -0
- package/test/tracing/exporter.toPayload.test.js +400 -0
- package/test/tracing/id.test.js +24 -0
- package/test/tracing/span.test.js +183 -0
- package/test/tracing/spanProcessor.test.js +73 -0
- package/test/tracing/tracing.test.js +105 -0
- package/test/transforms.test.js +2 -2
- package/test/truncation.test.js +2 -2
- package/test/utility.test.js +44 -6
- package/webpack.config.js +6 -44
- package/.eslintignore +0 -7
- package/test/server.lambda.test.js +0 -194
- package/test/server.locals.test.js +0 -1068
- package/test/server.parser.test.js +0 -78
- package/test/server.predicates.test.js +0 -91
- package/test/server.rollbar.test.js +0 -728
- package/test/server.telemetry.test.js +0 -443
- package/test/server.transforms.test.js +0 -1193
- package/test/server.transport.test.js +0 -269
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
/* globals describe */
|
|
2
|
+
/* globals it */
|
|
3
|
+
/* globals beforeEach */
|
|
4
|
+
/* globals afterEach */
|
|
5
|
+
|
|
6
|
+
import { expect } from 'chai';
|
|
7
|
+
import sinon from 'sinon';
|
|
8
|
+
import nock from 'nock';
|
|
9
|
+
import http from 'http';
|
|
10
|
+
import https from 'https';
|
|
11
|
+
import { URL } from 'url';
|
|
12
|
+
|
|
13
|
+
import Rollbar from '../src/server/rollbar.js';
|
|
14
|
+
import { mergeOptions } from '../src/server/telemetry/urlHelpers.js';
|
|
15
|
+
|
|
16
|
+
function wait(ms) {
|
|
17
|
+
return new Promise((resolve) => {
|
|
18
|
+
setTimeout(resolve, ms);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function uncaught() {
|
|
23
|
+
setTimeout(() => {
|
|
24
|
+
throw new Error('rollbar error');
|
|
25
|
+
}, 1);
|
|
26
|
+
await wait(300);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function message(rollbar) {
|
|
30
|
+
setTimeout(() => rollbar.info('rollbar info message'), 1);
|
|
31
|
+
await wait(300);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function request(transport, url, options, body) {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const req = url
|
|
37
|
+
? transport.request(url, options)
|
|
38
|
+
: transport.request(options);
|
|
39
|
+
|
|
40
|
+
req.on('response', resolve);
|
|
41
|
+
req.on('error', reject);
|
|
42
|
+
|
|
43
|
+
if (body) {
|
|
44
|
+
req.write(body);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
req.end();
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function requestWithCallback(transport, options, body) {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const req = transport.request(options, resolve);
|
|
54
|
+
|
|
55
|
+
req.on('error', reject);
|
|
56
|
+
|
|
57
|
+
if (body) {
|
|
58
|
+
req.write(body);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
req.end();
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function stubPostWithResponse(url, status, headers, body) {
|
|
66
|
+
return nock(url).post('/api/users').reply(status, body, headers);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function stubGetWithResponse(url, status, headers, body) {
|
|
70
|
+
return nock(url).get('/api/users').reply(status, body, headers);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function stubGetWithError(url) {
|
|
74
|
+
return nock(url).get('/api/users').replyWithError('dns error');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const testHeaders1 = {
|
|
78
|
+
'Content-Type': 'application/json',
|
|
79
|
+
'X-access-token': '123',
|
|
80
|
+
};
|
|
81
|
+
const testHeaders2 = { authorization: 'abc', foo: '456' };
|
|
82
|
+
const testHeaders3 = { 'content-type': 'application/json', foo: '123' };
|
|
83
|
+
const testHeaders4 = { authorization: 'abc', bar: '456' };
|
|
84
|
+
const testBody1 = 'test body 1';
|
|
85
|
+
const testBody2 = 'test body 2';
|
|
86
|
+
const testMessage1 = 'test console message';
|
|
87
|
+
const testMessage2 = 'test console error message';
|
|
88
|
+
const testMessagePart = ', extra part';
|
|
89
|
+
|
|
90
|
+
describe('telemetry', function () {
|
|
91
|
+
describe('with log and network capture enabled', function () {
|
|
92
|
+
let rollbar;
|
|
93
|
+
let addItemStub;
|
|
94
|
+
let response1;
|
|
95
|
+
let response2;
|
|
96
|
+
let mochaHandlers;
|
|
97
|
+
|
|
98
|
+
beforeEach(async function () {
|
|
99
|
+
// Remove Mocha's uncaught exception handlers to prevent
|
|
100
|
+
// them from interfering with Rollbar's handlers.
|
|
101
|
+
mochaHandlers = process.listeners('uncaughtException');
|
|
102
|
+
mochaHandlers.forEach((handler) => {
|
|
103
|
+
process.removeListener('uncaughtException', handler);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
rollbar = new Rollbar({
|
|
107
|
+
accessToken: 'abc123',
|
|
108
|
+
captureUncaught: true,
|
|
109
|
+
autoInstrument: true,
|
|
110
|
+
});
|
|
111
|
+
addItemStub = sinon.stub(rollbar.client.notifier.queue, 'addItem');
|
|
112
|
+
|
|
113
|
+
// These are necessary so nock intercepts these HTTP requests
|
|
114
|
+
stubGetWithResponse('http://example.com', 200, testHeaders3, testBody1);
|
|
115
|
+
stubPostWithResponse('https://example.com', 201, testHeaders4, testBody2);
|
|
116
|
+
|
|
117
|
+
// Invoke telemetry events
|
|
118
|
+
console.info(testMessage1, testMessagePart);
|
|
119
|
+
response1 = await request(http, 'http://example.com/api/users', {
|
|
120
|
+
method: 'GET',
|
|
121
|
+
headers: testHeaders1,
|
|
122
|
+
});
|
|
123
|
+
console.error(testMessage2);
|
|
124
|
+
response2 = await request(https, 'https://example.com/api/users', {
|
|
125
|
+
method: 'POST',
|
|
126
|
+
headers: testHeaders2,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
await uncaught(rollbar);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
afterEach(function () {
|
|
133
|
+
addItemStub.restore();
|
|
134
|
+
nock.cleanAll();
|
|
135
|
+
|
|
136
|
+
// Restore Mocha's uncaught exception handlers
|
|
137
|
+
mochaHandlers.forEach((handler) => {
|
|
138
|
+
process.on('uncaughtException', handler);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('exception payload should have telemetry', function () {
|
|
143
|
+
expect(addItemStub.called).to.be.true;
|
|
144
|
+
const telemetry = addItemStub.getCall(0).args[3].data.body.telemetry;
|
|
145
|
+
|
|
146
|
+
// Verify that the responses were received intact.
|
|
147
|
+
expect(response1.headers).to.deep.equal(testHeaders3);
|
|
148
|
+
expect(response2.headers).to.deep.equal(testHeaders4);
|
|
149
|
+
expect(response1.statusCode).to.equal(200);
|
|
150
|
+
expect(response2.statusCode).to.equal(201);
|
|
151
|
+
|
|
152
|
+
// Verify telemetry items and order
|
|
153
|
+
expect(telemetry[0].level).to.equal('info');
|
|
154
|
+
expect(telemetry[0].type).to.equal('log');
|
|
155
|
+
expect(telemetry[0].body.message).to.equal(
|
|
156
|
+
'test console message , extra part\n',
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
expect(telemetry[1].level).to.equal('info');
|
|
160
|
+
expect(telemetry[1].type).to.equal('network');
|
|
161
|
+
expect(telemetry[1].body.method).to.equal('GET');
|
|
162
|
+
expect(telemetry[1].body.url).to.equal('http://example.com/api/users');
|
|
163
|
+
expect(telemetry[1].body.status_code).to.equal(200);
|
|
164
|
+
expect(telemetry[1].body.subtype).to.equal('http');
|
|
165
|
+
|
|
166
|
+
expect(telemetry[2].level).to.equal('error');
|
|
167
|
+
expect(telemetry[2].type).to.equal('log');
|
|
168
|
+
expect(telemetry[2].body.message).to.equal(
|
|
169
|
+
'test console error message\n',
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
expect(telemetry[3].level).to.equal('info');
|
|
173
|
+
expect(telemetry[3].type).to.equal('network');
|
|
174
|
+
expect(telemetry[3].body.method).to.equal('POST');
|
|
175
|
+
expect(telemetry[3].body.url).to.equal('https://example.com/api/users');
|
|
176
|
+
expect(telemetry[3].body.status_code).to.equal(201);
|
|
177
|
+
expect(telemetry[3].body.subtype).to.equal('http');
|
|
178
|
+
|
|
179
|
+
// Verify headers are omitted
|
|
180
|
+
expect(telemetry[1].body.request_headers).to.be.undefined;
|
|
181
|
+
expect(telemetry[1].body.response.headers).to.be.undefined;
|
|
182
|
+
expect(telemetry[3].body.request_headers).to.be.undefined;
|
|
183
|
+
expect(telemetry[3].body.response.headers).to.be.undefined;
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
describe('with log and network capture enabled with headers enabled', function () {
|
|
188
|
+
let rollbar;
|
|
189
|
+
let addItemStub;
|
|
190
|
+
|
|
191
|
+
beforeEach(async function () {
|
|
192
|
+
rollbar = new Rollbar({
|
|
193
|
+
accessToken: 'abc123',
|
|
194
|
+
captureUncaught: true,
|
|
195
|
+
autoInstrument: {
|
|
196
|
+
network: true,
|
|
197
|
+
networkResponseHeaders: true,
|
|
198
|
+
networkRequestHeaders: true,
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
addItemStub = sinon.stub(rollbar.client.notifier.queue, 'addItem');
|
|
202
|
+
|
|
203
|
+
// These are necessary so nock intercepts these HTTP requests
|
|
204
|
+
stubGetWithResponse('https://example.com', 200, testHeaders3, testBody1);
|
|
205
|
+
stubPostWithResponse('http://example.com', 201, testHeaders4, testBody2);
|
|
206
|
+
|
|
207
|
+
// Invoke telemetry events
|
|
208
|
+
console.info(testMessage1, testMessagePart);
|
|
209
|
+
await request(https, 'https://example.com/api/users', {
|
|
210
|
+
method: 'GET',
|
|
211
|
+
headers: testHeaders1,
|
|
212
|
+
});
|
|
213
|
+
console.error(testMessage2);
|
|
214
|
+
await request(http, 'http://example.com/api/users', {
|
|
215
|
+
method: 'POST',
|
|
216
|
+
headers: testHeaders2,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
await message(rollbar);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
afterEach(function () {
|
|
223
|
+
addItemStub.restore();
|
|
224
|
+
nock.cleanAll();
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('message payload should have telemetry', function () {
|
|
228
|
+
expect(addItemStub.called).to.be.true;
|
|
229
|
+
const telemetry = addItemStub.getCall(0).args[3].data.body.telemetry;
|
|
230
|
+
|
|
231
|
+
// Verify headers captures, with scrubbing
|
|
232
|
+
expect(telemetry[1].body.request_headers).to.deep.equal({
|
|
233
|
+
'Content-Type': 'application/json',
|
|
234
|
+
'X-access-token': '********',
|
|
235
|
+
});
|
|
236
|
+
expect(telemetry[1].body.response.headers).to.deep.equal({
|
|
237
|
+
'content-type': 'application/json',
|
|
238
|
+
foo: '123',
|
|
239
|
+
});
|
|
240
|
+
expect(telemetry[3].body.request_headers).to.deep.equal({
|
|
241
|
+
authorization: '********',
|
|
242
|
+
foo: '456',
|
|
243
|
+
});
|
|
244
|
+
expect(telemetry[3].body.response.headers).to.deep.equal({
|
|
245
|
+
authorization: '********',
|
|
246
|
+
bar: '456',
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
describe('with telemetry disabled', function () {
|
|
252
|
+
let rollbar;
|
|
253
|
+
let addItemStub;
|
|
254
|
+
|
|
255
|
+
beforeEach(async function () {
|
|
256
|
+
rollbar = new Rollbar({
|
|
257
|
+
accessToken: 'abc123',
|
|
258
|
+
captureUncaught: true,
|
|
259
|
+
});
|
|
260
|
+
addItemStub = sinon.stub(rollbar.client.notifier.queue, 'addItem');
|
|
261
|
+
|
|
262
|
+
// These are necessary so nock intercepts these HTTP requests
|
|
263
|
+
stubGetWithResponse('https://example.com', 200, testHeaders3, testBody1);
|
|
264
|
+
stubPostWithResponse('https://example.com', 201, testHeaders4, testBody2);
|
|
265
|
+
|
|
266
|
+
// Invoke telemetry events
|
|
267
|
+
console.info(testMessage1, testMessagePart);
|
|
268
|
+
await request(https, 'https://example.com/api/users', {
|
|
269
|
+
method: 'GET',
|
|
270
|
+
headers: testHeaders1,
|
|
271
|
+
});
|
|
272
|
+
console.error(testMessage2);
|
|
273
|
+
await request(https, 'https://example.com/api/users', {
|
|
274
|
+
method: 'POST',
|
|
275
|
+
headers: testHeaders2,
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
await message(rollbar);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
afterEach(function () {
|
|
282
|
+
addItemStub.restore();
|
|
283
|
+
nock.cleanAll();
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('payload should not have telemetry', function () {
|
|
287
|
+
expect(addItemStub.called).to.be.true;
|
|
288
|
+
const telemetry = addItemStub.getCall(0).args[3].data.body.telemetry;
|
|
289
|
+
expect(telemetry).to.deep.equal([]);
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
describe('with callback request and error response', function () {
|
|
294
|
+
let rollbar;
|
|
295
|
+
let addItemStub;
|
|
296
|
+
let response1;
|
|
297
|
+
let response2;
|
|
298
|
+
|
|
299
|
+
beforeEach(async function () {
|
|
300
|
+
rollbar = new Rollbar({
|
|
301
|
+
accessToken: 'abc123',
|
|
302
|
+
captureUncaught: true,
|
|
303
|
+
autoInstrument: {
|
|
304
|
+
network: true,
|
|
305
|
+
networkResponseHeaders: true,
|
|
306
|
+
networkRequestHeaders: true,
|
|
307
|
+
},
|
|
308
|
+
});
|
|
309
|
+
addItemStub = sinon.stub(rollbar.client.notifier.queue, 'addItem');
|
|
310
|
+
|
|
311
|
+
const options = {
|
|
312
|
+
method: 'GET',
|
|
313
|
+
protocol: 'https:',
|
|
314
|
+
host: 'example.com',
|
|
315
|
+
path: '/api/users',
|
|
316
|
+
headers: testHeaders1,
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
// Invoke telemetry events
|
|
320
|
+
console.info(testMessage1, testMessagePart);
|
|
321
|
+
stubGetWithResponse('https://example.com', 200, testHeaders3, testBody1);
|
|
322
|
+
response1 = await requestWithCallback(https, options).catch((e) => e);
|
|
323
|
+
console.error(testMessage2);
|
|
324
|
+
stubGetWithError('https://example.com');
|
|
325
|
+
response2 = await requestWithCallback(https, options).catch((e) => e);
|
|
326
|
+
|
|
327
|
+
await message(rollbar);
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
afterEach(function () {
|
|
331
|
+
addItemStub.restore();
|
|
332
|
+
nock.cleanAll();
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it('message payload should have telemetry or error info', function () {
|
|
336
|
+
expect(addItemStub.called).to.be.true;
|
|
337
|
+
const telemetry = addItemStub.getCall(0).args[3].data.body.telemetry;
|
|
338
|
+
|
|
339
|
+
// Verify that the responses were received intact.
|
|
340
|
+
expect(response1.headers).to.deep.equal(testHeaders3);
|
|
341
|
+
expect(response1.statusCode).to.equal(200);
|
|
342
|
+
expect(response2).to.be.instanceof(Error);
|
|
343
|
+
|
|
344
|
+
// Verify telemetry
|
|
345
|
+
expect(telemetry[1].body.request_headers).to.deep.equal({
|
|
346
|
+
'Content-Type': 'application/json',
|
|
347
|
+
'X-access-token': '********',
|
|
348
|
+
});
|
|
349
|
+
expect(telemetry[1].body.response.headers).to.deep.equal({
|
|
350
|
+
'content-type': 'application/json',
|
|
351
|
+
foo: '123',
|
|
352
|
+
});
|
|
353
|
+
expect(telemetry[3].body.request_headers).to.deep.equal({
|
|
354
|
+
'Content-Type': 'application/json',
|
|
355
|
+
'X-access-token': '********',
|
|
356
|
+
});
|
|
357
|
+
expect(telemetry[3].body.response).to.be.undefined;
|
|
358
|
+
expect(telemetry[3].body.status_code).to.equal(0);
|
|
359
|
+
expect(telemetry[3].body.error).to.equal('Error: dns error');
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
describe('while using autoinstrument', function () {
|
|
364
|
+
it('mergeOptions should correctly handle URL and options', function () {
|
|
365
|
+
const optionsUsingStringUrl = mergeOptions(
|
|
366
|
+
'http://example.com/api/users',
|
|
367
|
+
{ method: 'GET', headers: testHeaders1 },
|
|
368
|
+
);
|
|
369
|
+
const optionsUsingClassUrl = mergeOptions(
|
|
370
|
+
new URL('http://example.com/api/users'),
|
|
371
|
+
{ method: 'GET', headers: testHeaders1 },
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
expect(optionsUsingStringUrl).to.deep.equal(optionsUsingClassUrl);
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
});
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/* globals describe */
|
|
2
|
+
/* globals it */
|
|
3
|
+
|
|
4
|
+
import { expect } from 'chai';
|
|
5
|
+
import Rollbar from '../src/server/rollbar.js';
|
|
6
|
+
import * as t from '../src/server/transforms.js';
|
|
7
|
+
import { merge } from '../src/utility.js';
|
|
8
|
+
|
|
9
|
+
describe('data transforms', function () {
|
|
10
|
+
describe('transforms.baseData', function () {
|
|
11
|
+
const emptyItem = {};
|
|
12
|
+
const testItem = {
|
|
13
|
+
level: 'critical',
|
|
14
|
+
environment: 'production',
|
|
15
|
+
framework: 'star-wars',
|
|
16
|
+
uuid: '12345',
|
|
17
|
+
custom: {
|
|
18
|
+
one: 'a1',
|
|
19
|
+
stuff: 'b2',
|
|
20
|
+
language: 'english',
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
describe('with default options', function () {
|
|
25
|
+
it('should have a timestamp, level and defaults with an empty item', function (done) {
|
|
26
|
+
t.baseData(emptyItem, Rollbar.defaultOptions, (err, item) => {
|
|
27
|
+
expect(err).to.not.exist;
|
|
28
|
+
|
|
29
|
+
const data = item.data;
|
|
30
|
+
expect(data).to.exist;
|
|
31
|
+
expect(data.timestamp).to.exist;
|
|
32
|
+
expect(data.level).to.equal('error');
|
|
33
|
+
expect(data.environment).to.be.a('string');
|
|
34
|
+
expect(data.environment).to.not.be.empty;
|
|
35
|
+
expect(data.environment).to.equal(Rollbar.defaultOptions.environment);
|
|
36
|
+
expect(data.framework).to.equal('node-js');
|
|
37
|
+
expect(data.language).to.equal('javascript');
|
|
38
|
+
expect(data.server).to.exist;
|
|
39
|
+
expect(data.server.host).to.exist;
|
|
40
|
+
expect(data.server.pid).to.exist;
|
|
41
|
+
|
|
42
|
+
done();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should have a critical level, overriden defaults and custom data with values in item', function (done) {
|
|
47
|
+
t.baseData(testItem, Rollbar.defaultOptions, (err, item) => {
|
|
48
|
+
expect(err).to.not.exist;
|
|
49
|
+
|
|
50
|
+
const data = item.data;
|
|
51
|
+
expect(data.level).to.equal('critical');
|
|
52
|
+
expect(data.environment).to.equal('production');
|
|
53
|
+
expect(data.framework).to.equal('star-wars');
|
|
54
|
+
expect(data.language).to.equal('javascript');
|
|
55
|
+
expect(data.uuid).to.equal('12345');
|
|
56
|
+
expect(data.one).to.equal('a1');
|
|
57
|
+
expect(data.stuff).to.equal('b2');
|
|
58
|
+
expect(data.language).to.not.equal('english');
|
|
59
|
+
|
|
60
|
+
done();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('with custom options', function () {
|
|
66
|
+
const customOptions = merge(Rollbar.defaultOptions, {
|
|
67
|
+
payload: {
|
|
68
|
+
environment: 'payload-prod',
|
|
69
|
+
},
|
|
70
|
+
framework: 'opt-node',
|
|
71
|
+
host: 'opt-host',
|
|
72
|
+
branch: 'opt-master',
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should have a timestamp, error level and data from options and defaults with an empty item', function (done) {
|
|
76
|
+
t.baseData(emptyItem, customOptions, (err, item) => {
|
|
77
|
+
expect(err).to.not.exist;
|
|
78
|
+
|
|
79
|
+
const data = item.data;
|
|
80
|
+
expect(data).to.exist;
|
|
81
|
+
expect(data.timestamp).to.exist;
|
|
82
|
+
expect(data.level).to.equal('error');
|
|
83
|
+
expect(data.environment).to.equal('payload-prod');
|
|
84
|
+
expect(data.framework).to.equal('opt-node');
|
|
85
|
+
expect(data.language).to.equal('javascript');
|
|
86
|
+
expect(data.server).to.exist;
|
|
87
|
+
expect(data.server.host).to.equal('opt-host');
|
|
88
|
+
expect(data.server.branch).to.equal('opt-master');
|
|
89
|
+
expect(data.server.pid).to.exist;
|
|
90
|
+
|
|
91
|
+
done();
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('should have a critical level, overriden item defaults and custom data with values in item', function (done) {
|
|
96
|
+
t.baseData(testItem, customOptions, (err, item) => {
|
|
97
|
+
expect(err).to.not.exist;
|
|
98
|
+
|
|
99
|
+
const data = item.data;
|
|
100
|
+
expect(data.level).to.equal('critical');
|
|
101
|
+
expect(data.environment).to.equal('production');
|
|
102
|
+
expect(data.framework).to.equal('star-wars');
|
|
103
|
+
expect(data.language).to.equal('javascript');
|
|
104
|
+
expect(data.uuid).to.equal('12345');
|
|
105
|
+
expect(data.one).to.equal('a1');
|
|
106
|
+
expect(data.stuff).to.equal('b2');
|
|
107
|
+
expect(data.language).to.not.equal('english');
|
|
108
|
+
|
|
109
|
+
done();
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('transforms.addBody', function () {
|
|
116
|
+
const options = { whatever: 'stuff' };
|
|
117
|
+
|
|
118
|
+
it('should set the trace_chain with no message with stackInfo', function (done) {
|
|
119
|
+
const item = { stackInfo: [{ message: 'hey' }] };
|
|
120
|
+
t.addBody(item, options, (err, item) => {
|
|
121
|
+
expect(err).to.not.exist;
|
|
122
|
+
expect(item.data.body.trace_chain).to.exist;
|
|
123
|
+
expect(item.data.body.message).to.not.exist;
|
|
124
|
+
done();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('should set a message with no trace_chain with no stackInfo', function (done) {
|
|
129
|
+
const item = { message: 'hello' };
|
|
130
|
+
t.addBody(item, options, (err, item) => {
|
|
131
|
+
expect(err).to.not.exist;
|
|
132
|
+
expect(item.data.body.trace_chain).to.not.exist;
|
|
133
|
+
expect(item.data.body.message).to.exist;
|
|
134
|
+
done();
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe('transforms.addMessageData', function () {
|
|
140
|
+
const options = { random: 'stuff' };
|
|
141
|
+
|
|
142
|
+
it('should add a body with diagnostic with no message', function (done) {
|
|
143
|
+
const item = { err: 'stuff', not: 'a message' };
|
|
144
|
+
t.addMessageData(item, options, (err, item) => {
|
|
145
|
+
expect(err).to.not.exist;
|
|
146
|
+
expect(item.data.body).to.exist;
|
|
147
|
+
expect(item.data.body.message.body).to.equal(
|
|
148
|
+
'Item sent with null or missing arguments.',
|
|
149
|
+
);
|
|
150
|
+
done();
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should add a body with the message with a message', function (done) {
|
|
155
|
+
const item = { message: 'this is awesome' };
|
|
156
|
+
t.addMessageData(item, options, (err, item) => {
|
|
157
|
+
expect(err).to.not.exist;
|
|
158
|
+
expect(item.data.body.message.body).to.equal('this is awesome');
|
|
159
|
+
done();
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
});
|