Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(node): Implement Sentry-specific http instrumentation #13763

Merged
merged 14 commits into from
Oct 11, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
},
"devDependencies": {
"@sentry-internal/test-utils": "link:../../../test-utils",
"@playwright/test": "^1.44.1",
"wait-port": "1.0.4"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cleaned this up as this is not needed anymore

"@playwright/test": "^1.44.1"
},
"volta": {
"extends": "../../package.json"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
},
"devDependencies": {
"@sentry-internal/test-utils": "link:../../../test-utils",
"@playwright/test": "^1.41.1",
"wait-port": "1.0.4"
"@playwright/test": "^1.41.1"
},
"volta": {
"extends": "../../package.json"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ test('AWS Serverless SDK sends events in ESM mode', async ({ request }) => {
);

child_process.execSync('pnpm start', {
stdio: 'ignore',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was debugging a test here for some time, this made it much easier to debug this

stdio: 'inherit',
});

const transactionEvent = await transactionEventPromise;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@opentelemetry/sdk-trace-node": "1.26.0",
"@opentelemetry/exporter-trace-otlp-http": "0.53.0",
"@opentelemetry/instrumentation-undici": "0.6.0",
"@opentelemetry/instrumentation-http": "0.53.0",
"@opentelemetry/instrumentation": "0.53.0",
"@sentry/core": "latest || *",
"@sentry/node": "latest || *",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import express from 'express';
const app = express();
const port = 3030;

Sentry.setTag('root-level-tag', 'yes');

app.get('/test-success', function (req, res) {
res.send({ version: 'v1' });
});
Expand All @@ -23,8 +25,6 @@ app.get('/test-transaction', function (req, res) {

await fetch('http://localhost:3030/test-success');

await Sentry.flush();

res.send({});
});
});
Expand All @@ -38,7 +38,10 @@ app.get('/test-error', async function (req, res) {
});

app.get('/test-exception/:id', function (req, _res) {
throw new Error(`This is an exception with id ${req.params.id}`);
const id = req.params.id;
Sentry.setTag(`param-${id}`, id);

throw new Error(`This is an exception with id ${id}`);
});

Sentry.setupExpressErrorHandler(app);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
const { NodeTracerProvider, BatchSpanProcessor } = require('@opentelemetry/sdk-trace-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const Sentry = require('@sentry/node');
const { SentrySpanProcessor, SentryPropagator } = require('@sentry/opentelemetry');
const { SentryPropagator } = require('@sentry/opentelemetry');
const { UndiciInstrumentation } = require('@opentelemetry/instrumentation-undici');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');

Expand All @@ -15,6 +16,8 @@ Sentry.init({
tunnel: `http://localhost:3031/`, // proxy server
// Tracing is completely disabled

integrations: [Sentry.httpIntegration({ spans: false })],

// Custom OTEL setup
skipOpenTelemetrySetup: true,
});
Expand All @@ -37,5 +40,5 @@ provider.register({
});

registerInstrumentations({
instrumentations: [new UndiciInstrumentation()],
instrumentations: [new UndiciInstrumentation(), new HttpInstrumentation()],
});
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,24 @@ test('Sends correct error event', async ({ baseURL }) => {
span_id: expect.any(String),
});
});

test('Isolates requests correctly', async ({ baseURL }) => {
const errorEventPromise1 = waitForError('node-otel-without-tracing', event => {
return !event.type && event.exception?.values?.[0]?.value === 'This is an exception with id 555-a';
});
const errorEventPromise2 = waitForError('node-otel-without-tracing', event => {
return !event.type && event.exception?.values?.[0]?.value === 'This is an exception with id 555-b';
});

fetch(`${baseURL}/test-exception/555-a`);
fetch(`${baseURL}/test-exception/555-b`);

const errorEvent1 = await errorEventPromise1;
const errorEvent2 = await errorEventPromise2;

expect(errorEvent1.transaction).toEqual('GET /test-exception/555-a');
expect(errorEvent1.tags).toEqual({ 'root-level-tag': 'yes', 'param-555-a': '555-a' });

expect(errorEvent2.transaction).toEqual('GET /test-exception/555-b');
expect(errorEvent2.tags).toEqual({ 'root-level-tag': 'yes', 'param-555-b': '555-b' });
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ test('Sends an API route transaction to OTLP', async ({ baseURL }) => {

const scopeSpans = json.resourceSpans?.[0]?.scopeSpans;

const httpScope = scopeSpans?.find(
scopeSpan => scopeSpan.scope.name === '@opentelemetry_sentry-patched/instrumentation-http',
);
const httpScope = scopeSpans?.find(scopeSpan => scopeSpan.scope.name === '@opentelemetry/instrumentation-http');

return (
httpScope &&
Expand All @@ -40,9 +38,7 @@ test('Sends an API route transaction to OTLP', async ({ baseURL }) => {
// But our default node-fetch spans are not emitted
expect(scopeSpans.length).toEqual(2);

const httpScopes = scopeSpans?.filter(
scopeSpan => scopeSpan.scope.name === '@opentelemetry_sentry-patched/instrumentation-http',
);
const httpScopes = scopeSpans?.filter(scopeSpan => scopeSpan.scope.name === '@opentelemetry/instrumentation-http');
const undiciScopes = scopeSpans?.filter(
scopeSpan => scopeSpan.scope.name === '@opentelemetry/instrumentation-undici',
);
Expand Down Expand Up @@ -114,7 +110,6 @@ test('Sends an API route transaction to OTLP', async ({ baseURL }) => {
{ key: 'net.peer.port', value: { intValue: expect.any(Number) } },
{ key: 'http.status_code', value: { intValue: 200 } },
{ key: 'http.status_text', value: { stringValue: 'OK' } },
{ key: 'sentry.origin', value: { stringValue: 'auto.http.otel.http' } },
]),
droppedAttributesCount: 0,
events: [],
Expand Down
2 changes: 1 addition & 1 deletion packages/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
"@sentry/opentelemetry": "8.34.0",
"@sentry/types": "8.34.0",
"@sentry/utils": "8.34.0",
"import-in-the-middle": "^1.11.0"
"import-in-the-middle": "^1.11.2"
},
"devDependencies": {
"@types/node": "^14.18.0"
Expand Down
Loading
Loading