diff --git a/sentry-javascript/19815/README.md b/sentry-javascript/19815/README.md new file mode 100644 index 0000000..4271d52 --- /dev/null +++ b/sentry-javascript/19815/README.md @@ -0,0 +1,62 @@ +# Reproduction for sentry-javascript#19815 + +**Issue:** https://github.com/getsentry/sentry-javascript/issues/19815 + +## Description + +When tracing is disabled (no `tracesSampleRate` set), all errors from different +requests are assigned the **same** `traceId`. Without an active span per request, +the SDK never creates a fresh propagation context for each incoming request, so +every event ends up on the same static trace. + +## Steps to Reproduce + +1. Install dependencies: + ```bash + npm install + ``` + +2. (Optional) Set your Sentry DSN to also see events in Sentry UI: + ```bash + export SENTRY_DSN=https://@sentry.io/ + ``` + +3. Run the automated test (starts the server, fires 5 requests, then exits): + ```bash + bash test.sh + ``` + + Or run the server manually and send requests yourself: + ```bash + npm start + # in another terminal: + curl http://localhost:3000 + curl http://localhost:3000 + curl http://localhost:3000 + ``` + +## Expected Behavior + +Each request produces a **unique** `traceId`, so unrelated errors are not +grouped into the same trace. + +## Actual Behavior + +All requests share the same `traceId`. Example output: + +``` +[request #1] propagation traceId: e551c9b4398346c88486608a44c0a2a2 +[request #2] propagation traceId: e551c9b4398346c88486608a44c0a2a2 +[request #3] propagation traceId: e551c9b4398346c88486608a44c0a2a2 +[request #4] propagation traceId: e551c9b4398346c88486608a44c0a2a2 +[request #5] propagation traceId: e551c9b4398346c88486608a44c0a2a2 +``` + +This creates a false impression in Sentry that unrelated errors from different +requests belong to the same execution flow. + +## Environment + +- Node.js: v22.15.0 +- @sentry/node: 10.43.0 +- express: ^5.2.1 diff --git a/sentry-javascript/19815/app.js b/sentry-javascript/19815/app.js new file mode 100644 index 0000000..965a8d3 --- /dev/null +++ b/sentry-javascript/19815/app.js @@ -0,0 +1,36 @@ +import * as Sentry from '@sentry/node'; +import express from 'express'; + +const app = express(); + +let requestCount = 0; + +app.get('/', async (_req, res) => { + requestCount++; + const reqNum = requestCount; + + // Capture the current trace context before captureException + const scope = Sentry.getCurrentScope(); + const propagationContext = scope.getPropagationContext(); + console.log(`[request #${reqNum}] propagation traceId: ${propagationContext.traceId}`); + + Sentry.captureException(new Error(`Test Error from request #${reqNum}`)); + + res.end(`ok (request #${reqNum})\n`); +}); + +const server = app.listen(3000, () => { + console.log('App listening on port 3000'); + console.log(''); + console.log('Bug: All requests share the same traceId when tracing is disabled.'); + console.log('Each request should produce a different traceId.'); + console.log(''); + console.log('Run: curl http://localhost:3000 several times and observe the trace_id in the output.'); + console.log(''); +}); + +// Auto-shutdown after 30 seconds to simplify testing +setTimeout(() => { + server.close(); + process.exit(0); +}, 30_000); diff --git a/sentry-javascript/19815/instrument.js b/sentry-javascript/19815/instrument.js new file mode 100644 index 0000000..d08f80d --- /dev/null +++ b/sentry-javascript/19815/instrument.js @@ -0,0 +1,17 @@ +import * as Sentry from '@sentry/node'; + +Sentry.init({ + // Set your DSN here: export SENTRY_DSN=https://... + dsn: process.env.SENTRY_DSN, + // Tracing is intentionally disabled (no tracesSampleRate) + beforeSend(event) { + const traceId = event.contexts?.trace?.trace_id; + console.log(`[beforeSend] event type: error | trace_id: ${traceId}`); + return event; + }, + beforeSendTransaction(event) { + const traceId = event.contexts?.trace?.trace_id; + console.log(`[beforeSend] event type: transaction | trace_id: ${traceId}`); + return event; + }, +}); diff --git a/sentry-javascript/19815/package.json b/sentry-javascript/19815/package.json new file mode 100644 index 0000000..91f154c --- /dev/null +++ b/sentry-javascript/19815/package.json @@ -0,0 +1,13 @@ +{ + "name": "sentry-repro-19815", + "version": "1.0.0", + "description": "Reproduction for sentry-javascript#19815: All errors assigned to same trace when tracing is disabled", + "type": "module", + "scripts": { + "start": "node --import ./instrument.js app.js" + }, + "dependencies": { + "@sentry/node": "10.43.0", + "express": "^5.2.1" + } +} diff --git a/sentry-javascript/19815/test.sh b/sentry-javascript/19815/test.sh new file mode 100755 index 0000000..db555b4 --- /dev/null +++ b/sentry-javascript/19815/test.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Automated test: starts the server, fires 5 requests, and prints the trace IDs. +# All trace IDs should be the same (the bug), but each should be unique (the fix). + +set -e + +echo "Starting server..." +node --import ./instrument.js app.js & +SERVER_PID=$! + +# Wait for server to be ready +sleep 2 + +echo "" +echo "Sending 5 requests..." +for i in 1 2 3 4 5; do + curl -s http://localhost:3000 > /dev/null + sleep 0.2 +done + +echo "" +echo "Waiting for events to flush..." +sleep 1 + +kill $SERVER_PID 2>/dev/null || true +echo "Done."