-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathtransactions.test.ts
More file actions
131 lines (113 loc) · 5.17 KB
/
transactions.test.ts
File metadata and controls
131 lines (113 loc) · 5.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import { expect, test } from '@playwright/test';
import { waitForPlainRequest, waitForTransaction } from '@sentry-internal/test-utils';
test('Sends an API route transaction to OTLP', async ({ baseURL }) => {
waitForTransaction('node-otel-without-tracing', transactionEvent => {
throw new Error('THIS SHOULD NEVER HAPPEN!');
});
// Ensure we send data to the OTLP endpoint
const otelPromise = waitForPlainRequest('node-otel-without-tracing-otel', data => {
const json = JSON.parse(data) as any;
const scopeSpans = json.resourceSpans?.[0]?.scopeSpans;
const httpScope = scopeSpans?.find(scopeSpan => scopeSpan.scope.name === '@opentelemetry/instrumentation-http');
return (
httpScope &&
httpScope.spans.some(span =>
span.attributes.some(attr => attr.key === 'http.target' && attr.value?.stringValue === '/test-transaction'),
)
);
});
fetch(`${baseURL}/test-transaction`);
const otelData = await otelPromise;
expect(otelData).toBeDefined();
const json = JSON.parse(otelData);
expect(json.resourceSpans.length).toBe(1);
const scopeSpans = json.resourceSpans?.[0]?.scopeSpans;
expect(scopeSpans).toBeDefined();
// Http server span & undici client spans are emitted.
// Sentry.startSpan() spans are NOT emitted (non-recording when tracing is disabled).
// Our default node-fetch spans are also not emitted.
expect(scopeSpans.length).toEqual(2);
const httpScopes = scopeSpans?.filter(scopeSpan => scopeSpan.scope.name === '@opentelemetry/instrumentation-http');
const undiciScopes = scopeSpans?.filter(
scopeSpan => scopeSpan.scope.name === '@opentelemetry/instrumentation-undici',
);
const startSpanScopes = scopeSpans?.filter(scopeSpan => scopeSpan.scope.name === '@sentry/node');
expect(httpScopes.length).toBe(1);
// Sentry spans should not be exported when tracing is disabled
expect(startSpanScopes.length).toBe(0);
// Undici spans are emitted correctly
expect(undiciScopes.length).toBe(1);
expect(undiciScopes[0].spans.length).toBe(1);
expect(undiciScopes[0].spans).toEqual([
{
traceId: expect.any(String),
spanId: expect.any(String),
name: 'GET',
kind: 3,
startTimeUnixNano: expect.any(String),
endTimeUnixNano: expect.any(String),
attributes: expect.arrayContaining([
{ key: 'http.request.method', value: { stringValue: 'GET' } },
{ key: 'http.request.method_original', value: { stringValue: 'GET' } },
{ key: 'url.full', value: { stringValue: 'http://localhost:3030/test-success' } },
{ key: 'url.path', value: { stringValue: '/test-success' } },
{ key: 'url.query', value: { stringValue: '' } },
{ key: 'url.scheme', value: { stringValue: 'http' } },
{ key: 'server.address', value: { stringValue: 'localhost' } },
{ key: 'server.port', value: { intValue: 3030 } },
{ key: 'user_agent.original', value: { stringValue: 'node' } },
{ key: 'network.peer.address', value: { stringValue: expect.any(String) } },
{ key: 'network.peer.port', value: { intValue: 3030 } },
{ key: 'http.response.status_code', value: { intValue: 200 } },
{ key: 'http.response.header.content-length', value: { intValue: 16 } },
]),
droppedAttributesCount: 0,
events: [],
droppedEventsCount: 0,
status: { code: 0 },
links: [],
droppedLinksCount: 0,
flags: expect.any(Number),
},
]);
// There may be another span from another request, we can ignore that
const httpSpans = httpScopes[0].spans.filter(span =>
span.attributes.some(attr => attr.key === 'http.target' && attr.value?.stringValue === '/test-transaction'),
);
expect(httpSpans).toEqual([
{
traceId: expect.any(String),
spanId: expect.any(String),
name: 'GET',
kind: 2,
startTimeUnixNano: expect.any(String),
endTimeUnixNano: expect.any(String),
attributes: expect.arrayContaining([
{ key: 'http.url', value: { stringValue: 'http://localhost:3030/test-transaction' } },
{ key: 'http.host', value: { stringValue: 'localhost:3030' } },
{ key: 'net.host.name', value: { stringValue: 'localhost' } },
{ key: 'http.method', value: { stringValue: 'GET' } },
{ key: 'http.scheme', value: { stringValue: 'http' } },
{ key: 'http.target', value: { stringValue: '/test-transaction' } },
{ key: 'http.user_agent', value: { stringValue: 'node' } },
{ key: 'http.flavor', value: { stringValue: '1.1' } },
{ key: 'net.transport', value: { stringValue: 'ip_tcp' } },
{ key: 'net.host.ip', value: { stringValue: expect.any(String) } },
{ key: 'net.host.port', value: { intValue: 3030 } },
{ key: 'net.peer.ip', value: { stringValue: expect.any(String) } },
{ key: 'net.peer.port', value: { intValue: expect.any(Number) } },
{ key: 'http.status_code', value: { intValue: 200 } },
{ key: 'http.status_text', value: { stringValue: 'OK' } },
]),
droppedAttributesCount: 0,
events: [],
droppedEventsCount: 0,
status: {
code: 0,
},
links: [],
droppedLinksCount: 0,
flags: expect.any(Number),
},
]);
});