Skip to content

Commit 934be68

Browse files
committed
create toTracestate method
1 parent ab72f62 commit 934be68

File tree

3 files changed

+63
-9
lines changed

3 files changed

+63
-9
lines changed

packages/tracing/src/span.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,20 @@ export class Span implements SpanInterface {
248248
return `${this.traceId}-${this.spanId}${sampledString}`;
249249
}
250250

251+
/**
252+
* @inheritDoc
253+
*/
254+
public toTracestate(): string | undefined {
255+
const sentryTracestate = this.transaction?.metadata?.tracestate?.sentry || this._getNewTracestate();
256+
let thirdpartyTracestate = this.transaction?.metadata?.tracestate?.thirdparty;
257+
258+
// if there's third-party data, add a leading comma; otherwise, convert from `undefined` to the empty string, so the
259+
// end result doesn’t come out as `sentry=xxxxxundefined`
260+
thirdpartyTracestate = thirdpartyTracestate ? `,${thirdpartyTracestate}` : '';
261+
262+
return `${sentryTracestate}${thirdpartyTracestate}`;
263+
}
264+
251265
/**
252266
* @inheritDoc
253267
*/
@@ -290,13 +304,7 @@ export class Span implements SpanInterface {
290304
* @inheritDoc
291305
*/
292306
public getTraceHeaders(): TraceHeaders {
293-
// tracestates live on the transaction, so if this is a free-floating span, there won't be one
294-
let tracestate;
295-
if (this.transaction) {
296-
tracestate = this.transaction.metadata?.tracestate?.sentry;
297-
} else {
298-
tracestate = this._getNewTracestate();
299-
}
307+
const tracestate = this.toTracestate();
300308

301309
return {
302310
'sentry-trace': this.toTraceparent(),

packages/tracing/test/span.test.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { BrowserClient } from '@sentry/browser';
22
import { Hub, Scope } from '@sentry/hub';
3+
import * as hubPackage from '@sentry/hub';
34

45
import { Span, SpanStatus, Transaction } from '../src';
5-
import { SENTRY_TRACE_REGEX } from '../src/utils';
6+
import { computeTracestateValue, SENTRY_TRACE_REGEX } from '../src/utils';
67

78
describe('Span', () => {
89
let hub: Hub;
@@ -101,6 +102,48 @@ describe('Span', () => {
101102
});
102103
});
103104

105+
describe('toTracestate', () => {
106+
const publicKey = 'dogsarebadatkeepingsecrets';
107+
const release = 'off.leash.trail';
108+
const environment = 'dogpark';
109+
const traceId = '12312012123120121231201212312012';
110+
111+
const computedTracestate = `sentry=${computeTracestateValue({ traceId, environment, release, publicKey })}`;
112+
const thirdpartyData = 'maisey=silly,charlie=goofy';
113+
114+
const hub = new Hub(
115+
new BrowserClient({
116+
dsn: 'https://[email protected]/12312012',
117+
tracesSampleRate: 1,
118+
release,
119+
environment,
120+
}),
121+
);
122+
123+
test('no third-party data', () => {
124+
const transaction = new Transaction({ name: 'FETCH /ball', traceId }, hub);
125+
const span = transaction.startChild({ op: 'dig.hole' });
126+
127+
expect(span.toTracestate()).toEqual(computedTracestate);
128+
});
129+
130+
test('third-party data', () => {
131+
const transaction = new Transaction({ name: 'FETCH /ball' }, hub);
132+
transaction.setMetadata({ tracestate: { sentry: computedTracestate, thirdparty: thirdpartyData } });
133+
const span = transaction.startChild({ op: 'dig.hole' });
134+
135+
expect(span.toTracestate()).toEqual(`${computedTracestate},${thirdpartyData}`);
136+
});
137+
138+
test('orphan span', () => {
139+
jest.spyOn(hubPackage, 'getCurrentHub').mockReturnValueOnce(hub);
140+
const span = new Span({ op: 'dig.hole' });
141+
span.traceId = traceId;
142+
143+
expect(span.toTracestate()).toEqual(computedTracestate);
144+
});
145+
});
146+
104147
describe('getTraceHeaders', () => {
105148
it('returns correct headers', () => {
106149
const hub = new Hub(

packages/types/src/span.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,12 @@ export interface Span extends SpanContext {
149149
*/
150150
isSuccess(): boolean;
151151

152-
/** Return a traceparent compatible header string */
152+
/** Return a traceparent-compatible header string */
153153
toTraceparent(): string;
154154

155+
/** Return a tracestate-compatible header string. Returns undefined if there is no client or no DSN. */
156+
toTracestate(): string | undefined;
157+
155158
/** Returns the current span properties as a `SpanContext` */
156159
toContext(): SpanContext;
157160

0 commit comments

Comments
 (0)