Skip to content

Commit ab31931

Browse files
authored
post spans from tracing exporter (#1335)
1 parent 9ce7947 commit ab31931

File tree

9 files changed

+92
-15
lines changed

9 files changed

+92
-15
lines changed

src/browser/core.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class Rollbar {
3636
const transport = new Transport(truncation);
3737
const api = new API(this.options, transport, urllib, truncation);
3838
if (Tracing) {
39-
this.tracing = new Tracing(_gWindow(), this.options);
39+
this.tracing = new Tracing(_gWindow(), api, this.options);
4040
this.tracing.initSession();
4141
}
4242
if (Telemeter) {

src/tracing/exporter.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import hrtime from './hrtime.js';
55
* and transforming them into the OTLP-compatible format.
66
*/
77
export class SpanExporter {
8+
constructor(api, options = {}) {
9+
this.api = api;
10+
this.options = options;
11+
}
12+
813
/**
914
* Export spans to the span export queue
1015
*
@@ -66,6 +71,17 @@ export class SpanExporter {
6671
};
6772
}
6873

74+
/**
75+
* Sends the given payload to the Rollbar API.
76+
*
77+
* @param {String} payload - Serialized OTLP format payload
78+
* @param {Object} headers - Optional request headers
79+
* @returns {Promise} Promise that resolves when the request completes
80+
*/
81+
post(payload, headers = {}) {
82+
return this.api.postSpans(payload, headers);
83+
}
84+
6985
/**
7086
* Transforms a ReadableSpan into the OTLP Span format
7187
*

src/tracing/tracing.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import id from './id.js';
88
const SPAN_KEY = createContextKey('Rollbar Context Key SPAN');
99

1010
export default class Tracing {
11-
constructor(gWindow, options) {
11+
constructor(gWindow, api, options) {
12+
this.api = api;
1213
this.options = options;
1314
this.window = gWindow;
1415

@@ -59,7 +60,7 @@ export default class Tracing {
5960

6061
createTracer() {
6162
this.contextManager = new ContextManager();
62-
this.exporter = new SpanExporter();
63+
this.exporter = new SpanExporter(this.api, this.options);
6364
this.spanProcessor = new SpanProcessor(this.exporter, this.options.tracing);
6465
this.tracer = new Tracer(this, this.spanProcessor);
6566
}

test/browser.telemetry.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ describe('instrumentDom', function () {
7676
await loadHtml('test/fixtures/html/dom-events.html');
7777
scrubFields = ['foo', 'bar'];
7878
rollbar = new Rollbar({})
79-
tracing = new Tracing(window, {})
79+
tracing = new Tracing(window, null, {})
8080
tracing.initSession();
8181
telemeter = new Telemeter({}, tracing);
8282
instrumenter = new Instrumenter(

test/replay/integration/e2e.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ describe('Session Replay E2E', function () {
6666
};
6767
const logger = { error: sinon.spy(), log: sinon.spy() };
6868

69-
tracing = new Tracing(window, options);
69+
tracing = new Tracing(window, null, options);
7070
tracing.initSession();
7171
api = new Api(
7272
{ accessToken: 'test-token-12345' },

test/replay/integration/replayManager.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ describe('ReplayManager API Integration', function () {
4747
truncate: sinon.stub().returns({ error: null, value: '{}' }),
4848
};
4949

50-
tracing = new Tracing(window, options);
50+
tracing = new Tracing(window, null, options);
5151
tracing.initSession();
5252

5353
const mockPayload = [{ id: 'span1', name: 'recording-span' }];

test/replay/integration/sessionRecording.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ describe('Session Replay Integration', function () {
6464
let recorder;
6565

6666
beforeEach(function () {
67-
tracing = new Tracing(window, options);
67+
tracing = new Tracing(window, null, options);
6868
tracing.initSession();
6969
});
7070

@@ -207,7 +207,7 @@ describe('Session Replay Transport Integration', function () {
207207
truncate: sinon.stub().returns({ error: null, value: '{}' }),
208208
};
209209

210-
tracing = new Tracing(window, options);
210+
tracing = new Tracing(window, null, options);
211211
tracing.initSession();
212212

213213
api = new Api(

test/telemetry.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ describe('capture events', function () {
4949
beforeEach(function () {
5050
const tracing = new Tracing(
5151
window,
52+
null,
5253
{
5354
resource: {
5455
'service.name': 'Test',

test/tracing/tracing.test.js

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { expect } from 'chai';
22
import sinon from 'sinon';
33

4+
import Api from '../../src/api.js';
45
import {
56
ContextManager,
67
createContextKey,
@@ -28,7 +29,7 @@ const tracingOptions = function (options = {}) {
2829
describe('Tracing()', function () {
2930
it('should initialize', function (done) {
3031
const options = tracingOptions();
31-
const t = new Tracing(window, options);
32+
const t = new Tracing(window, null, options);
3233
t.initSession();
3334

3435
expect(t).to.have.property('initSession').and.to.be.a('function');
@@ -53,7 +54,7 @@ describe('Tracing()', function () {
5354

5455
it('should configure', function () {
5556
const options = tracingOptions();
56-
const t = new Tracing(window, options);
57+
const t = new Tracing(window, null, options);
5758
t.initSession();
5859

5960
expect(t.options.resource).to.deep.equal(options.resource);
@@ -74,7 +75,7 @@ describe('Tracing()', function () {
7475

7576
it('should create and export spans', function (done) {
7677
const options = tracingOptions();
77-
const t = new Tracing(window, options);
78+
const t = new Tracing(window, null, options);
7879
t.initSession();
7980

8081
expect(t.sessionId).to.match(/^[a-f0-9]{32}$/);
@@ -120,7 +121,7 @@ describe('Tracing()', function () {
120121

121122
it('should create spans with span option overrides', function () {
122123
const options = tracingOptions();
123-
const t = new Tracing(window, options);
124+
const t = new Tracing(window, null, options);
124125
t.initSession();
125126

126127
expect(t.sessionId).to.match(/^[a-f0-9]{32}$/);
@@ -143,7 +144,7 @@ describe('Tracing()', function () {
143144

144145
it('should get and set session attributes', function () {
145146
const options = tracingOptions();
146-
const t = new Tracing(window, options);
147+
const t = new Tracing(window, null, options);
147148
t.initSession();
148149

149150
t.session.setAttributes({codeVersion: 'abc123'});
@@ -162,7 +163,7 @@ describe('Tracing()', function () {
162163
it('should not init session when sessionStorage is not detected', function () {
163164
const stub = sinon.stub(window, 'sessionStorage').value(undefined);
164165
const options = tracingOptions();
165-
const t = new Tracing(window, options);
166+
const t = new Tracing(window, null, options);
166167

167168
// calling initSession should be a no-op
168169
t.initSession();
@@ -173,12 +174,70 @@ describe('Tracing()', function () {
173174

174175
it('should generate ids', function (done) {
175176
const options = tracingOptions();
176-
const t = new Tracing(window, options);
177+
const t = new Tracing(window, null, options);
177178

178179
const replayId = t.idGen(8);
179180

180181
expect(replayId).to.match(/^[a-f0-9]{16}$/);
181182

182183
done();
183184
});
185+
186+
describe('post', function () {
187+
let api;
188+
let transport;
189+
let tracing;
190+
191+
beforeEach(function () {
192+
transport = {
193+
post: sinon
194+
.stub()
195+
.callsFake(({ accessToken, options, payload, callback }) => {
196+
setTimeout(() => {
197+
callback(
198+
null,
199+
{ err: 0, result: { id: '12345' } },
200+
);
201+
}, 1);
202+
}),
203+
postJsonPayload: sinon.stub(),
204+
};
205+
const urlMock = { parse: sinon.stub().returns({}) };
206+
const truncationMock = {
207+
truncate: sinon.stub().returns({ error: null, value: '{}' }),
208+
};
209+
210+
api = new Api(
211+
{ accessToken: 'test-token-12345' },
212+
transport,
213+
urlMock,
214+
truncationMock,
215+
);
216+
tracing = new Tracing(window, api, {});
217+
tracing.initSession();
218+
});
219+
220+
afterEach(function () {
221+
sinon.restore();
222+
});
223+
224+
it('should post a trace payload', function (done) {
225+
const span = tracing.startSpan('test.span');
226+
span.end();
227+
tracing.exporter.post(
228+
tracing.exporter.toPayload(),
229+
{ 'X-Rollbar-Session-Id': tracing.sessionId }
230+
);
231+
232+
setTimeout(() => {
233+
expect(transport.post.callCount).to.equal(1);
234+
const call = transport.post.getCall(0);
235+
const { payload, headers } = call.args[0];
236+
expect(payload).to.have.property('resourceSpans');
237+
expect(headers).to.have.property('X-Rollbar-Session-Id', tracing.sessionId);
238+
239+
done();
240+
}, 10);
241+
});
242+
});
184243
});

0 commit comments

Comments
 (0)