Skip to content

Commit 27b145d

Browse files
committed
fixups and failing node integration tests :)
1 parent e4a2807 commit 27b145d

File tree

11 files changed

+410
-5
lines changed

11 files changed

+410
-5
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import * as Sentry from '@sentry/node';
2+
import { loggingTransport } from '@sentry-internal/node-integration-tests';
3+
4+
Sentry.init({
5+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
6+
release: '1.0',
7+
tracesSampleRate: 1.0,
8+
transport: loggingTransport,
9+
traceLifecycle: 'stream',
10+
debug: true,
11+
});
12+
13+
Sentry.getCurrentScope().setAttribute('scope_attr', { value: 100, unit: 'millisecond' });
14+
15+
Sentry.startSpan({ name: 'parent' }, parentSpan => {
16+
parentSpan.setAttribute('parent_span_attr', true);
17+
Sentry.startSpan({ name: 'child' }, childSpan => {
18+
childSpan.addLink({ context: parentSpan.spanContext(), attributes: { child_link_attr: 'hi' } });
19+
Sentry.startSpan({ name: 'grandchild' }, grandchildSpan => {
20+
Sentry.updateSpanName(grandchildSpan, 'grandchild_new_name');
21+
});
22+
});
23+
});
24+
25+
Sentry.flush();
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
import { expect, test } from 'vitest';
2+
import { createRunner } from '../../../utils/runner';
3+
4+
test('sends spans with correct properties', async () => {
5+
await createRunner(__dirname, 'scenario.ts')
6+
.expect({
7+
span: spanContainer => {
8+
const spans = spanContainer.items;
9+
expect(spans).toHaveLength(3);
10+
11+
const segmentSpanId = spans.find(span => span.is_segment)?.span_id;
12+
expect(segmentSpanId).toMatch(/^[\da-f]{16}$/);
13+
14+
const childSpanId = spans.find(span => span.name === 'child')?.span_id;
15+
expect(childSpanId).toMatch(/^[\da-f]{16}$/);
16+
17+
const traceId = spans.find(span => span.is_segment)?.trace_id;
18+
expect(traceId).toMatch(/^[\da-f]{32}$/);
19+
20+
expect(spans).toEqual([
21+
{
22+
end_timestamp: expect.any(Number),
23+
is_segment: false,
24+
name: 'grandchild_new_name',
25+
parent_span_id: childSpanId,
26+
span_id: expect.stringMatching(/^[\da-f]{16}$/),
27+
start_timestamp: expect.any(Number),
28+
status: 'ok',
29+
trace_id: traceId,
30+
attributes: {
31+
scope_attr: {
32+
type: 'integer',
33+
unit: 'millisecond',
34+
value: 100,
35+
},
36+
'sentry.custom_span_name': {
37+
type: 'string',
38+
value: 'grandchild_new_name',
39+
},
40+
'sentry.origin': {
41+
type: 'string',
42+
value: 'manual',
43+
},
44+
'sentry.release': {
45+
type: 'string',
46+
value: '1.0',
47+
},
48+
'sentry.sdk.name': {
49+
type: 'string',
50+
value: 'sentry.javascript.node',
51+
},
52+
'sentry.sdk.version': {
53+
type: 'string',
54+
value: expect.any(String),
55+
},
56+
'sentry.segment.id': {
57+
type: 'string',
58+
value: segmentSpanId,
59+
},
60+
'sentry.segment.name': {
61+
type: 'string',
62+
value: 'parent',
63+
},
64+
'sentry.source': {
65+
type: 'string',
66+
value: 'custom',
67+
},
68+
'sentry.span.source': {
69+
type: 'string',
70+
value: 'custom',
71+
},
72+
},
73+
},
74+
{
75+
end_timestamp: expect.any(Number),
76+
is_segment: false,
77+
name: 'child',
78+
parent_span_id: segmentSpanId,
79+
span_id: childSpanId,
80+
start_timestamp: expect.any(Number),
81+
status: 'ok',
82+
trace_id: traceId,
83+
links: [
84+
{
85+
attributes: {
86+
child_link_attr: {
87+
type: 'string',
88+
value: 'hi',
89+
},
90+
},
91+
sampled: true,
92+
span_id: segmentSpanId,
93+
traceState: {
94+
_internalState: {},
95+
},
96+
trace_id: traceId,
97+
},
98+
],
99+
attributes: {
100+
scope_attr: {
101+
type: 'integer',
102+
unit: 'millisecond',
103+
value: 100,
104+
},
105+
'sentry.origin': {
106+
type: 'string',
107+
value: 'manual',
108+
},
109+
'sentry.release': {
110+
type: 'string',
111+
value: '1.0',
112+
},
113+
'sentry.sdk.name': {
114+
type: 'string',
115+
value: 'sentry.javascript.node',
116+
},
117+
'sentry.sdk.version': {
118+
type: 'string',
119+
value: expect.any(String),
120+
},
121+
'sentry.segment.id': {
122+
type: 'string',
123+
value: segmentSpanId,
124+
},
125+
'sentry.segment.name': {
126+
type: 'string',
127+
value: 'parent',
128+
},
129+
'sentry.source': {
130+
type: 'string',
131+
value: 'custom',
132+
},
133+
'sentry.span.source': {
134+
type: 'string',
135+
value: 'custom',
136+
},
137+
},
138+
},
139+
{
140+
end_timestamp: expect.any(Number),
141+
is_segment: true,
142+
name: 'parent',
143+
span_id: segmentSpanId,
144+
start_timestamp: expect.any(Number),
145+
status: 'ok',
146+
trace_id: traceId,
147+
attributes: {
148+
parent_span_attr: {
149+
type: 'boolean',
150+
value: true,
151+
},
152+
scope_attr: {
153+
type: 'integer',
154+
unit: 'millisecond',
155+
value: 100,
156+
},
157+
'sentry.origin': {
158+
type: 'string',
159+
value: 'manual',
160+
},
161+
'sentry.release': {
162+
type: 'string',
163+
value: '1.0',
164+
},
165+
'sentry.sample_rate': {
166+
type: 'integer',
167+
value: 1,
168+
},
169+
'sentry.sdk.name': {
170+
type: 'string',
171+
value: 'sentry.javascript.node',
172+
},
173+
'sentry.sdk.version': {
174+
type: 'string',
175+
value: expect.any(String),
176+
},
177+
'sentry.segment.id': {
178+
type: 'string',
179+
value: segmentSpanId,
180+
},
181+
'sentry.segment.name': {
182+
type: 'string',
183+
value: 'parent',
184+
},
185+
'sentry.source': {
186+
type: 'string',
187+
value: 'custom',
188+
},
189+
'sentry.span.source': {
190+
type: 'string',
191+
value: 'custom',
192+
},
193+
},
194+
},
195+
]);
196+
},
197+
})
198+
.start()
199+
.completed();
200+
});
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import * as Sentry from '@sentry/node';
2+
import { loggingTransport } from '@sentry-internal/node-integration-tests';
3+
4+
Sentry.init({
5+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
6+
release: '1.0',
7+
tracesSampleRate: 1.0,
8+
transport: loggingTransport,
9+
traceLifecycle: 'stream',
10+
// This should match only the 'child-to-ignore' span
11+
ignoreSpans: ['child-to-ignore'],
12+
debug: true,
13+
clientReportFlushInterval: 1000,
14+
});
15+
16+
// The segment span should be sent
17+
Sentry.startSpan({ name: 'parent' }, parent => {
18+
console.log('xx parent span started', parent.spanContext().spanId);
19+
// This child span should be ignored
20+
Sentry.startSpan({ name: 'child-to-ignore' }, childToIgnore => {
21+
console.log('xx child-to-ignore span started', childToIgnore.spanContext().spanId);
22+
// but this one should be sent
23+
Sentry.startSpan({ name: 'child-of-ignored-child' }, childOfIgnoredChild => {
24+
console.log('xx child-of-ignored-child span started', childOfIgnoredChild.spanContext().spanId);
25+
});
26+
});
27+
// This child span should be sent
28+
Sentry.startSpan({ name: 'child-to-keep' }, childToKeep => {
29+
console.log('xx child-to-keep span started', childToKeep.spanContext().spanId);
30+
});
31+
});
32+
33+
Sentry.flush(2000);
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import * as Sentry from '@sentry/node';
2+
import { loggingTransport } from '@sentry-internal/node-integration-tests';
3+
4+
Sentry.init({
5+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
6+
release: '1.0',
7+
tracesSampleRate: 1.0,
8+
transport: loggingTransport,
9+
traceLifecycle: 'stream',
10+
// This should match the segment span name 'segment-to-ignore'
11+
ignoreSpans: ['segment-to-ignore'],
12+
clientReportFlushInterval: 1000,
13+
debug: true,
14+
});
15+
16+
// This segment span should be ignored, along with all its children
17+
Sentry.startSpan({ name: 'segment-to-ignore' }, () => {
18+
Sentry.startSpan({ name: 'child-of-ignored-segment' }, () => {
19+
Sentry.startSpan({ name: 'grandchild-of-ignored-segment' }, () => {
20+
// noop
21+
});
22+
});
23+
});
24+
25+
// This segment span should NOT be ignored and should be sent
26+
Sentry.startSpan({ name: 'segment-to-keep' }, () => {
27+
Sentry.startSpan({ name: 'child-of-kept-segment' }, () => {
28+
// noop
29+
});
30+
});
31+
32+
Sentry.flush();
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { expect, test } from 'vitest';
2+
import { createRunner } from '../../../utils/runner';
3+
4+
test('ignoring a segment span drops the entire segment', async () => {
5+
// When the segment span matches ignoreSpans, all spans within that segment should be dropped
6+
// We verify this by having two segments - one ignored and one not - and checking only the non-ignored one is sent
7+
await createRunner(__dirname, 'scenario-ignore-segment.ts')
8+
.expect({
9+
span: spanContainer => {
10+
const spans = spanContainer.items;
11+
12+
console.log('xx spans', JSON.stringify(spans, null, 2));
13+
14+
// We should only have spans from 'segment-to-keep' (2 spans: segment + child)
15+
// The 'segment-to-ignore' and all its children (3 spans) should NOT be sent
16+
expect(spans).toHaveLength(2);
17+
18+
const spanNames = spans.map(span => span.name);
19+
20+
// These should be present (from the non-ignored segment)
21+
expect(spanNames).toContain('segment-to-keep');
22+
expect(spanNames).toContain('child-of-kept-segment');
23+
24+
// These should NOT be present (from the ignored segment)
25+
expect(spanNames).not.toContain('segment-to-ignore');
26+
expect(spanNames).not.toContain('child-of-ignored-segment');
27+
expect(spanNames).not.toContain('grandchild-of-ignored-segment');
28+
29+
// Verify the segment span
30+
const segmentSpan = spans.find(span => span.is_segment);
31+
expect(segmentSpan).toBeDefined();
32+
expect(segmentSpan?.name).toBe('segment-to-keep');
33+
},
34+
})
35+
.expect({
36+
client_report: {
37+
discarded_events: [{ category: 'span', reason: 'event_processor', quantity: 3 }],
38+
},
39+
})
40+
.start()
41+
.completed();
42+
});
43+
44+
test('ignoring a child span only drops that child span', async () => {
45+
await createRunner(__dirname, 'scenario-ignore-child.ts')
46+
.expect({
47+
span: spanContainer => {
48+
const spans = spanContainer.items;
49+
50+
expect(spans).toHaveLength(3);
51+
52+
const spanNames = spans.map(span => span.name);
53+
expect(spanNames).toContain('parent');
54+
expect(spanNames).toContain('child-to-keep');
55+
expect(spanNames).toContain('child-of-ignored-child');
56+
expect(spanNames).not.toContain('child-to-ignore');
57+
58+
const segmentSpan = spans.find(span => span.is_segment);
59+
expect(segmentSpan).toBeDefined();
60+
expect(segmentSpan?.name).toBe('parent');
61+
62+
// Verify the child spans to be kept are the children of the dropped span's parent
63+
const childSpan = spans.find(span => span.name === 'child-to-keep');
64+
expect(childSpan).toBeDefined();
65+
expect(childSpan?.is_segment).toBe(false);
66+
expect(childSpan?.parent_span_id).toBe(segmentSpan?.span_id);
67+
68+
const childOfIgnoredChildSpan = spans.find(span => span.name === 'child-of-ignored-child');
69+
expect(childOfIgnoredChildSpan).toBeDefined();
70+
expect(childOfIgnoredChildSpan?.is_segment).toBe(false);
71+
expect(childOfIgnoredChildSpan?.parent_span_id).toBe(segmentSpan?.span_id);
72+
},
73+
})
74+
.expect({
75+
client_report: {
76+
discarded_events: [{ category: 'span', reason: 'event_processor', quantity: 1 }],
77+
},
78+
})
79+
.start()
80+
.completed();
81+
});

dev-packages/node-integration-tests/utils/assertions.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import type {
66
SerializedLogContainer,
77
SerializedMetricContainer,
88
SerializedSession,
9+
SerializedSpanContainer,
910
SessionAggregates,
11+
SpanV2JSON,
1012
TransactionEvent,
1113
} from '@sentry/core';
1214
import { SDK_VERSION } from '@sentry/core';
@@ -86,6 +88,12 @@ export function assertSentryMetricContainer(
8688
});
8789
}
8890

91+
export function assertSentrySpans(actual: SerializedSpanContainer, expected: Partial<SerializedSpanContainer>): void {
92+
expect(actual).toMatchObject({
93+
...expected,
94+
});
95+
}
96+
8997
export function assertEnvelopeHeader(actual: Envelope[0], expected: Partial<Envelope[0]>): void {
9098
expect(actual).toEqual({
9199
event_id: expect.any(String),

0 commit comments

Comments
 (0)