Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f75c3ed

Browse files
feat(node): Pass requestHook and responseHook option to OTel (#17996)
This adds two new options into the `nativeNodeFetchIntegration` - the only thing it does is passing the two new options directly into the OTel instrumentation. Since this is OTel related, this is only accessible within the `node` SDK. The documentation will be then updated for the fetch integration ([it seems](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/nodefetch/) that also the `spans` are missing) (closes #17953)
1 parent 39f85b3 commit f75c3ed

File tree

3 files changed

+87
-1
lines changed
  • dev-packages/node-integration-tests/suites/tracing/http-client-spans/fetch-forward-request-hook
  • packages/node/src/integrations

3 files changed

+87
-1
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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+
integrations: [
10+
Sentry.nativeNodeFetchIntegration({
11+
requestHook: (span, req) => {
12+
span.setAttribute('sentry.request.hook', req.path);
13+
},
14+
responseHook: (span, { response, request }) => {
15+
span.setAttribute('sentry.response.hook.path', request.path);
16+
span.setAttribute('sentry.response.hook.status_code', response.statusCode);
17+
},
18+
}),
19+
],
20+
});
21+
22+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
23+
Sentry.startSpan({ name: 'test_transaction' }, async () => {
24+
await fetch(`${process.env.SERVER_URL}/api/v0`);
25+
await fetch(`${process.env.SERVER_URL}/api/v1`);
26+
});
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { expect, test } from 'vitest';
2+
import { createRunner } from '../../../../utils/runner';
3+
import { createTestServer } from '../../../../utils/server';
4+
5+
test('adds requestHook and responseHook attributes to spans of outgoing fetch requests', async () => {
6+
expect.assertions(3);
7+
8+
const [SERVER_URL, closeTestServer] = await createTestServer()
9+
.get('/api/v0', () => {
10+
// Just ensure we're called
11+
expect(true).toBe(true);
12+
})
13+
.get(
14+
'/api/v1',
15+
() => {
16+
// Just ensure we're called
17+
expect(true).toBe(true);
18+
},
19+
404,
20+
)
21+
.start();
22+
23+
await createRunner(__dirname, 'scenario.ts')
24+
.withEnv({ SERVER_URL })
25+
.expect({
26+
transaction: {
27+
transaction: 'test_transaction',
28+
spans: [
29+
expect.objectContaining({
30+
description: expect.stringMatching(/GET.*\/api\/v0/),
31+
op: 'http.client',
32+
origin: 'auto.http.otel.node_fetch',
33+
status: 'ok',
34+
data: expect.objectContaining({
35+
'sentry.request.hook': '/api/v0',
36+
'sentry.response.hook.path': '/api/v0',
37+
'sentry.response.hook.status_code': 200,
38+
}),
39+
}),
40+
expect.objectContaining({
41+
description: expect.stringMatching(/GET.*\/api\/v1/),
42+
op: 'http.client',
43+
origin: 'auto.http.otel.node_fetch',
44+
status: 'not_found',
45+
data: expect.objectContaining({
46+
'sentry.request.hook': '/api/v1',
47+
'sentry.response.hook.path': '/api/v1',
48+
'sentry.response.hook.status_code': 404,
49+
'http.response.status_code': 404,
50+
}),
51+
}),
52+
],
53+
},
54+
})
55+
.start()
56+
.completed();
57+
closeTestServer();
58+
});

‎packages/node/src/integrations/node-fetch.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type { NodeClientOptions } from '../types';
88

99
const INTEGRATION_NAME = 'NodeFetch';
1010

11-
interface NodeFetchOptions {
11+
interface NodeFetchOptions extendsPick<UndiciInstrumentationConfig,'requestHook'|'responseHook'>{
1212
/**
1313
* Whether breadcrumbs should be recorded for requests.
1414
* Defaults to true
@@ -106,6 +106,8 @@ function getConfigWithDefaults(options: Partial<NodeFetchOptions> = {}): UndiciI
106106
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.node_fetch',
107107
};
108108
},
109+
requestHook: options.requestHook,
110+
responseHook: options.responseHook,
109111
} satisfies UndiciInstrumentationConfig;
110112

111113
return instrumentationConfig;

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /