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

Koa scopes are not isolated between requests #13992

Closed
3 tasks done
TheHolyWaffle opened this issue Oct 16, 2024 · 4 comments
Closed
3 tasks done

Koa scopes are not isolated between requests #13992

TheHolyWaffle opened this issue Oct 16, 2024 · 4 comments
Labels
Package: node Issues related to the Sentry Node SDK

Comments

@TheHolyWaffle
Copy link

TheHolyWaffle commented Oct 16, 2024

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/node

SDK Version

8.34.0

Framework Version

koa 2.15.3, @koa/router 13.1.0

Link to Sentry event

No response

Reproduction Example/SDK Setup

instrument.ts

import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: "mydns",
  tracesSampleRate: 1.0,
  integrations: [Sentry.koaIntegration()],
  debug: true,
});

server.ts

import './instrument';
import Koa from 'koa';
import Router from '@koa/router';
import * as Sentry from '@sentry/node';

const app = new Koa();
const router = new Router();
Sentry.setupKoaErrorHandler(app);

function log(msg: string) {
  const globalScope = Sentry.getGlobalScope().getScopeData();
  const isolationScope = Sentry.getIsolationScope().getScopeData();
  const currentScope = Sentry.getCurrentScope().getScopeData();

  const data = {
    ...globalScope.tags,
    ...globalScope.extra,
    ...isolationScope.tags,
    ...isolationScope.extra,
    ...currentScope.tags,
    ...currentScope.extra,
  };

  console.info(msg, JSON.stringify(data));
}

router.get('/', (ctx) => {
  log('BEFORE');
  Sentry.setTag('query', ctx.request.query.test as string);
  log('AFTER');
});

app.use(router.routes());

export const server = app.listen(8088, () => log('Server started on 8088'));

Steps to Reproduce

  1. Run npx tsx server.ts
  2. Trigger the / endpoint with a GET request and a URL query parameter test set to foo
  3. Console outputs:
BEFORE {}
AFTER {"query":"foo"}
  1. Trigger the / endpoint again, but change query parameter value to foo2
  2. Console outputs:
BEFORE {"query":"foo"}
AFTER {"query":"foo2"}

Expected Result

The expected result is that the Sentry tag query is not persisted across consecutive incoming HTTP requests. Wrapping the / handler with Sentry.withScope does not fix this

In practice this means the second trigger should output:

BEFORE {}
AFTER {"query":"foo2"}

Actual Result

The second trigger outputs:

BEFORE {"query":"foo"}
AFTER {"query":"foo2"}
@github-actions github-actions bot added the Package: node Issues related to the Sentry Node SDK label Oct 16, 2024
@TheHolyWaffle
Copy link
Author

Full log

/Users/bert.degeyter/.nvm/versions/node/v20.18.0/bin/npm run start

> crm-app@2.0.0 start
> tsx src/server.ts

Debugger listening on ws://127.0.0.1:52179/0561b7fc-929a-4649-bc25-e5b57c978e97
For help, see: https://nodejs.org/en/docs/inspector
Debugger attached.
Debugger listening on ws://127.0.0.1:52190/b21beaa7-7672-4090-bd56-36839f60a9b2
For help, see: https://nodejs.org/en/docs/inspector
Debugger attached.
Sentry Logger [log]: Initializing Sentry: process: 8046, thread: main.
Sentry Logger [log]: Integration installed: InboundFilters
Sentry Logger [log]: Integration installed: FunctionToString
Sentry Logger [log]: Integration installed: LinkedErrors
Sentry Logger [log]: Integration installed: RequestData
Sentry Logger [log]: Integration installed: Console
Sentry Logger [log]: Integration installed: Http
Sentry Logger [log]: Integration installed: NodeFetch
Sentry Logger [log]: Integration installed: OnUncaughtException
Sentry Logger [log]: Integration installed: OnUnhandledRejection
Sentry Logger [log]: Integration installed: ContextLines
Sentry Logger [log]: Integration installed: LocalVariablesAsync
Sentry Logger [log]: Integration installed: Context
Sentry Logger [log]: Integration installed: Modules
Sentry Logger [log]: Integration installed: Express
Sentry Logger [log]: Integration installed: Fastify
Sentry Logger [log]: Integration installed: Graphql
Sentry Logger [log]: Integration installed: Mongo
Sentry Logger [log]: Integration installed: Mongoose
Sentry Logger [log]: Integration installed: Mysql
Sentry Logger [log]: Integration installed: Mysql2
Sentry Logger [log]: Integration installed: Redis
Sentry Logger [log]: Integration installed: Postgres
Sentry Logger [log]: Integration installed: Nest
Sentry Logger [log]: Integration installed: Hapi
Sentry Logger [log]: Integration installed: Koa
Sentry Logger [log]: Integration installed: Connect
Sentry Logger [log]: Integration installed: GenericPool
Sentry Logger [log]: Integration installed: Kafka
Sentry Logger [log]: Integration installed: Dataloader
Sentry Logger [log]: Integration installed: Amqplib
Sentry Logger [log]: Integration installed: LruMemoizer
Sentry Logger [log]: Running in CommonJS mode.
Sentry Logger [debug]: @opentelemetry/api: Registered a global for diag v1.9.0.
Sentry Logger [error]: Error: @opentelemetry/api: Registration of version v1.9.0 for trace does not match previously registered API v1.8.0
    at registerGlobal (/Users/bert.degeyter/dev/crm-app/node_modules/@opentelemetry/api/src/internal/global-utils.ts:56:17)
    at TraceAPI.setGlobalTracerProvider (/Users/bert.degeyter/dev/crm-app/node_modules/@opentelemetry/api/src/api/trace.ts:67:35)
    at BasicTracerProvider.register (/Users/bert.degeyter/dev/crm-app/node_modules/@opentelemetry/sdk-trace-base/src/BasicTracerProvider.ts:153:11)
    at setupOtel (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/initOtel.ts:147:12)
    at Object.initOpenTelemetry (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/initOtel.ts:31:20)
    at _init (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/index.ts:171:5)
    at Object.init (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/index.ts:104:10)
    at <anonymous> (/Users/bert.degeyter/dev/crm-app/src/instrument.ts:6:8)
    at Object.<anonymous> (/Users/bert.degeyter/dev/crm-app/src/instrument.ts:11:2)
    at Module._compile (node:internal/modules/cjs/loader:1469:14)
Sentry Logger [error]: Error: @opentelemetry/api: Registration of version v1.9.0 for context does not match previously registered API v1.8.0
    at registerGlobal (/Users/bert.degeyter/dev/crm-app/node_modules/@opentelemetry/api/src/internal/global-utils.ts:56:17)
    at ContextAPI.setGlobalContextManager (/Users/bert.degeyter/dev/crm-app/node_modules/@opentelemetry/api/src/api/context.ts:53:26)
    at BasicTracerProvider.register (/Users/bert.degeyter/dev/crm-app/node_modules/@opentelemetry/sdk-trace-base/src/BasicTracerProvider.ts:159:15)
    at setupOtel (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/initOtel.ts:147:12)
    at Object.initOpenTelemetry (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/initOtel.ts:31:20)
    at _init (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/index.ts:171:5)
    at Object.init (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/index.ts:104:10)
    at <anonymous> (/Users/bert.degeyter/dev/crm-app/src/instrument.ts:6:8)
    at Object.<anonymous> (/Users/bert.degeyter/dev/crm-app/src/instrument.ts:11:2)
    at Module._compile (node:internal/modules/cjs/loader:1469:14)
Sentry Logger [error]: Error: @opentelemetry/api: Registration of version v1.9.0 for propagation does not match previously registered API v1.8.0
    at registerGlobal (/Users/bert.degeyter/dev/crm-app/node_modules/@opentelemetry/api/src/internal/global-utils.ts:56:17)
    at PropagationAPI.setGlobalPropagator (/Users/bert.degeyter/dev/crm-app/node_modules/@opentelemetry/api/src/api/propagation.ts:67:26)
    at BasicTracerProvider.register (/Users/bert.degeyter/dev/crm-app/node_modules/@opentelemetry/sdk-trace-base/src/BasicTracerProvider.ts:163:19)
    at setupOtel (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/initOtel.ts:147:12)
    at Object.initOpenTelemetry (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/initOtel.ts:31:20)
    at _init (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/index.ts:171:5)
    at Object.init (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/index.ts:104:10)
    at <anonymous> (/Users/bert.degeyter/dev/crm-app/src/instrument.ts:6:8)
    at Object.<anonymous> (/Users/bert.degeyter/dev/crm-app/src/instrument.ts:11:2)
    at Module._compile (node:internal/modules/cjs/loader:1469:14)
Sentry Logger [debug]: @opentelemetry_sentry-patched/instrumentation-http Applying instrumentation patch for nodejs core module on require hook { module: 'http' }
Sentry Logger [debug]: @opentelemetry/instrumentation-koa Applying instrumentation patch for module on require hook {
  module: 'koa',
  version: '2.15.3',
  baseDir: '/Users/bert.degeyter/dev/crm-app/node_modules/koa'
}
Sentry Logger [debug]: patching Koa middleware layer
Sentry Logger [debug]: Patching @koa/router dispatch
Sentry Logger [debug]: patching Koa middleware layer
Server started on 8088 {}
Sentry Logger [debug]: @opentelemetry_sentry-patched/instrumentation-http http instrumentation incomingRequest
BEFORE {}
AFTER {"query":"foo"}
Sentry Logger [debug]: @opentelemetry_sentry-patched/instrumentation-http http instrumentation incomingRequest
BEFORE {"query":"foo"}
AFTER {"query":"foo2"}



@andreiborza
Copy link
Member

Hi @TheHolyWaffle thanks for writing in. Do you have a reproduction repo for this? I've tried it out locally using tsx and the code snippets you provided but I'm getting

BEFORE {}
AFTER {"query":"foo2"}

I'm also not getting

Sentry Logger [error]: Error: @opentelemetry/api: Registration of version v1.9.0 for trace does not match previously registered API v1.8.0
    at registerGlobal (/Users/bert.degeyter/dev/crm-app/node_modules/@opentelemetry/api/src/internal/global-utils.ts:56:17)
    at TraceAPI.setGlobalTracerProvider (/Users/bert.degeyter/dev/crm-app/node_modules/@opentelemetry/api/src/api/trace.ts:67:35)
    at BasicTracerProvider.register (/Users/bert.degeyter/dev/crm-app/node_modules/@opentelemetry/sdk-trace-base/src/BasicTracerProvider.ts:153:11)
    at setupOtel (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/initOtel.ts:147:12)
    at Object.initOpenTelemetry (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/initOtel.ts:31:20)
    at _init (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/index.ts:171:5)
    at Object.init (/Users/bert.degeyter/dev/crm-app/node_modules/@sentry/node/src/sdk/index.ts:104:10)
    at <anonymous> (/Users/bert.degeyter/dev/crm-app/src/instrument.ts:6:8)
    at Object.<anonymous> (/Users/bert.degeyter/dev/crm-app/src/instrument.ts:11:2)
    at Module._compile (node:internal/modules/cjs/loader:1469:14)

If you create a github repo or a stackblitz we can take a better look.

@TheHolyWaffle
Copy link
Author

TheHolyWaffle commented Oct 16, 2024

Aha, it was related due to multiple versions 1.8.0 and 1.9.0 of @opentelemetry/api being present in node_modules.

$ npm ls @opentelemetry/api --depth=2
├─┬ @sentry/node@8.34.0
│ ├── @opentelemetry/api@1.9.0
│ ├─┬ @opentelemetry/context-async-hooks@1.25.1
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/core@1.26.0
│ │ └── @opentelemetry/api@1.9.0 deduped
│ ├─┬ @opentelemetry/instrumentation-amqplib@0.42.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-connect@0.39.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-dataloader@0.12.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-express@0.42.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-fastify@0.39.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-fs@0.15.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-generic-pool@0.39.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-graphql@0.43.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-hapi@0.41.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-http@0.53.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-ioredis@0.43.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-kafkajs@0.3.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-koa@0.43.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-lru-memoizer@0.40.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-mongodb@0.47.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-mongoose@0.42.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-mysql@0.41.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-mysql2@0.41.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-nestjs-core@0.40.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-pg@0.44.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-redis-4@0.42.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation-undici@0.6.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @opentelemetry/instrumentation@0.53.0
│ │ └── @opentelemetry/api@1.9.0 deduped
│ ├─┬ @opentelemetry/resources@1.26.0
│ │ └── @opentelemetry/api@1.9.0 deduped
│ ├─┬ @opentelemetry/sdk-trace-base@1.26.0
│ │ └── @opentelemetry/api@1.8.0 deduped
│ ├─┬ @prisma/instrumentation@5.19.1
│ │ └── @opentelemetry/api@1.8.0 deduped
│ └─┬ @sentry/opentelemetry@8.34.0
│   └── @opentelemetry/api@1.9.0 deduped
└─┬ dd-trace@5.23.1
  ├── @opentelemetry/api@1.8.0
  └─┬ @opentelemetry/core@1.24.1
    └── @opentelemetry/api@1.8.0 deduped

Re-generating package-lock.json fixed it.

But I'm not sure how to prevent this in the future as we use renovatebot to auto upgrade dependencies.

Also, the only way to visualize this error is by turning on debug: true which you typically won't do for a production environment. Would be nice to fail-fast here in such scenario's

@andreiborza
Copy link
Member

@TheHolyWaffle great, glad it's been resolved. I agree it's hard to spot these. We'll discuss possibly failing differently here. Thanks again for filing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Package: node Issues related to the Sentry Node SDK
Projects
Archived in project
Development

No branches or pull requests

2 participants