Skip to content

Commit 2e993b3

Browse files
committed
Add status to transactions
1 parent 0a83eae commit 2e993b3

File tree

4 files changed

+149
-13
lines changed

4 files changed

+149
-13
lines changed

packages/hub/src/span.ts

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Span as SpanInterface, SpanContext } from '@sentry/types';
22
import { timestampWithMs, uuid4 } from '@sentry/utils';
3+
34
import { getCurrentHub, Hub } from './hub';
45

56
export const TRACEPARENT_REGEXP = /^[ \t]*([0-9a-f]{32})?-?([0-9a-f]{16})?-?([01])?[ \t]*$/;
@@ -61,12 +62,12 @@ export class Span implements SpanInterface, SpanContext {
6162
/**
6263
* @inheritDoc
6364
*/
64-
public tags?: { [key: string]: string };
65+
public tags: { [key: string]: string } = {};
6566

6667
/**
6768
* @inheritDoc
6869
*/
69-
public data?: { [key: string]: any };
70+
public data: { [key: string]: any } = {};
7071

7172
/**
7273
* List of spans that were finalized
@@ -154,6 +155,55 @@ export class Span implements SpanInterface, SpanContext {
154155
return undefined;
155156
}
156157

158+
/**
159+
* Sets the tag attribute on the current span
160+
* @param key Tag key
161+
* @param value Tag value
162+
*/
163+
public setTag(key: string, value: string): this {
164+
this.tags = { ...this.tags, [key]: value };
165+
return this;
166+
}
167+
168+
/**
169+
* Sets the data attribute on the current span
170+
* @param key Data key
171+
* @param value Data value
172+
*/
173+
public setData(key: string, value: any): this {
174+
this.data = { ...this.data, [key]: value };
175+
return this;
176+
}
177+
178+
/**
179+
* Sets the data attribute on the current span
180+
* @param key Data key
181+
* @param value Data value
182+
*/
183+
public setFailure(): this {
184+
this.setTag('status', 'failure');
185+
return this;
186+
}
187+
188+
/**
189+
* Sets the data attribute on the current span
190+
* @param key Data key
191+
* @param value Data value
192+
*/
193+
public setSuccess(): this {
194+
this.setTag('status', 'success');
195+
return this;
196+
}
197+
198+
/**
199+
* Sets the data attribute on the current span
200+
* @param key Data key
201+
* @param value Data value
202+
*/
203+
public isSuccess(): boolean {
204+
return this.tags.status !== 'failure';
205+
}
206+
157207
/**
158208
* Sets the finish timestamp on the current span
159209
*/
@@ -200,7 +250,7 @@ export class Span implements SpanInterface, SpanContext {
200250
* @inheritDoc
201251
*/
202252
public getTraceContext(): object {
203-
return {
253+
const context = {
204254
data: this.data,
205255
description: this.description,
206256
op: this.op,
@@ -209,6 +259,13 @@ export class Span implements SpanInterface, SpanContext {
209259
tags: this.tags,
210260
trace_id: this._traceId,
211261
};
262+
263+
if (this.tags.status) {
264+
// TODO: Fixme, just use better typings
265+
(context as any).status = this.tags.status;
266+
}
267+
268+
return context;
212269
}
213270

214271
/**

packages/hub/test/span.test.ts

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,69 @@ describe('Span', () => {
1818
expect((span2 as any).sampled).toBe((span as any).sampled);
1919
});
2020

21-
test.only('gets currentHub', () => {
21+
test('gets currentHub', () => {
22+
const span = new Span({});
23+
const span2 = span.newSpan();
24+
expect((span as any)._hub).toBeInstanceOf(Hub);
25+
expect((span2 as any)._hub).toBeInstanceOf(Hub);
26+
});
27+
});
28+
29+
describe('setters', () => {
30+
test('setTag', () => {
31+
const span = new Span({});
32+
expect(span.tags.foo).toBeUndefined();
33+
span.setTag('foo', 'bar');
34+
expect(span.tags.foo).toBe('bar');
35+
span.setTag('foo', 'baz');
36+
expect(span.tags.foo).toBe('baz');
37+
});
38+
39+
test('setData', () => {
40+
const span = new Span({});
41+
expect(span.data.foo).toBeUndefined();
42+
span.setData('foo', null);
43+
expect(span.data.foo).toBe(null);
44+
span.setData('foo', 2);
45+
expect(span.data.foo).toBe(2);
46+
span.setData('foo', true);
47+
expect(span.data.foo).toBe(true);
48+
});
49+
});
50+
51+
describe('status', () => {
52+
test('setSuccess', () => {
53+
const span = new Span({});
54+
span.setSuccess();
55+
expect(span.tags.status).toBe('success');
56+
});
57+
58+
test('setFailure', () => {
59+
const span = new Span({});
60+
span.setFailure();
61+
expect(span.tags.status).toBe('failure');
62+
});
63+
64+
test('isSuccess', () => {
65+
const span = new Span({});
66+
expect(span.isSuccess()).toBe(true);
67+
span.setFailure();
68+
expect(span.isSuccess()).toBe(false);
69+
span.setSuccess();
70+
expect(span.isSuccess()).toBe(true);
71+
});
72+
});
73+
74+
describe('newSpan', () => {
75+
test('simple', () => {
76+
const span = new Span({ sampled: true });
77+
const span2 = span.newSpan();
78+
expect((span2 as any)._parentSpanId).toBe((span as any)._spanId);
79+
expect((span2 as any)._traceId).toBe((span as any)._traceId);
80+
expect((span2 as any).sampled).toBe((span as any).sampled);
81+
});
82+
83+
test('gets currentHub', () => {
2284
const span = new Span({});
2385
const span2 = span.newSpan();
2486
expect((span as any)._hub).toBeInstanceOf(Hub);
@@ -123,4 +185,26 @@ describe('Span', () => {
123185
expect(spy.mock.calls[0][0].spans).toHaveLength(1);
124186
});
125187
});
188+
189+
describe('getTraceContext', () => {
190+
test('should have status attribute undefined if no status tag is available', () => {
191+
const span = new Span({});
192+
const context = span.getTraceContext();
193+
expect((context as any).status).toBeUndefined();
194+
});
195+
196+
test('should have success status extracted from tags', () => {
197+
const span = new Span({});
198+
span.setSuccess();
199+
const context = span.getTraceContext();
200+
expect((context as any).status).toBe('success');
201+
});
202+
203+
test('should have failure status extracted from tags', () => {
204+
const span = new Span({});
205+
span.setFailure();
206+
const context = span.getTraceContext();
207+
expect((context as any).status).toBe('failure');
208+
});
209+
});
126210
});

packages/types/src/hub.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,4 @@ export interface Hub {
183183
* @param bindOnScope Determines if the started span will be set on the Scope
184184
*/
185185
startSpan(spanContext?: SpanContext, bindOnScope?: boolean): Span;
186-
187-
/**
188-
* This finishes the passed `Span`. If the `Span` has the property `transaction` set and it's bound on the
189-
* current Scope, an `transaction` Event will be sent to Sentry containing all finished Spans inbetween.
190-
* Returns either an `event.id` or `undefined` in case event wasn't sent.
191-
*
192-
* @param span `Span` instance that was created by {@link startSpan}
193-
*/
194-
finishSpan(span?: Span): string | undefined;
195186
}

packages/types/src/span.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ export interface SpanContext {
1818
* Operation of the Span.
1919
*/
2020
op?: string;
21+
/**
22+
* Completion status of the Span.
23+
*/
24+
status?: boolean;
2125
/**
2226
* Parent Span ID
2327
*/

0 commit comments

Comments
 (0)