From ca6954ea63981c598f7cce8052a8ec2f8751c48b Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Mon, 16 Mar 2026 10:23:48 -0400 Subject: [PATCH 01/21] feat(elysia): Add Elysia SDK Adds a new @sentry/elysia package providing Sentry instrumentation for the Elysia framework running on Bun. Includes request/response tracing, error capturing, span filtering for lifecycle hooks, trace propagation via response headers, and comprehensive unit + e2e tests. Co-Authored-By: Claude Opus 4.6 (1M context) --- .craft.yml | 5 + .github/ISSUE_TEMPLATE/bug.yml | 1 + .github/workflows/build.yml | 2 +- .size-limit.js | 26 +- README.md | 1 + .../test-applications/bun-elysia/.gitignore | 1 + .../test-applications/bun-elysia/.npmrc | 2 + .../test-applications/bun-elysia/package.json | 25 + .../bun-elysia/playwright.config.mjs | 7 + .../test-applications/bun-elysia/src/app.ts | 142 ++++ .../bun-elysia/start-event-proxy.mjs | 6 + .../bun-elysia/tests/errors.test.ts | 109 +++ .../bun-elysia/tests/isolation.test.ts | 30 + .../bun-elysia/tests/propagation.test.ts | 113 +++ .../bun-elysia/tests/transactions.test.ts | 211 ++++++ .../bun-elysia/tsconfig.json | 11 + .../scripts/consistentExports.ts | 6 + .../e2e-tests/verdaccio-config/config.yaml | 6 + package.json | 7 +- packages/elysia/.eslintrc.js | 9 + packages/elysia/LICENSE | 21 + packages/elysia/README.md | 34 + packages/elysia/package.json | 86 +++ packages/elysia/rollup.npm.config.mjs | 3 + packages/elysia/src/clientHooks.ts | 63 ++ packages/elysia/src/index.ts | 195 ++++++ packages/elysia/src/sdk.ts | 60 ++ packages/elysia/src/types.ts | 6 + packages/elysia/src/withElysia.ts | 107 +++ packages/elysia/test/sdk.test.ts | 123 ++++ packages/elysia/test/withElysia.test.ts | 184 +++++ packages/elysia/tsconfig.json | 10 + packages/elysia/tsconfig.test.json | 12 + packages/elysia/tsconfig.types.json | 10 + yarn.lock | 651 ++++++++++++++++-- 35 files changed, 2224 insertions(+), 61 deletions(-) create mode 100644 dev-packages/e2e-tests/test-applications/bun-elysia/.gitignore create mode 100644 dev-packages/e2e-tests/test-applications/bun-elysia/.npmrc create mode 100644 dev-packages/e2e-tests/test-applications/bun-elysia/package.json create mode 100644 dev-packages/e2e-tests/test-applications/bun-elysia/playwright.config.mjs create mode 100644 dev-packages/e2e-tests/test-applications/bun-elysia/src/app.ts create mode 100644 dev-packages/e2e-tests/test-applications/bun-elysia/start-event-proxy.mjs create mode 100644 dev-packages/e2e-tests/test-applications/bun-elysia/tests/errors.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/bun-elysia/tests/isolation.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/bun-elysia/tests/propagation.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/bun-elysia/tests/transactions.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/bun-elysia/tsconfig.json create mode 100644 packages/elysia/.eslintrc.js create mode 100644 packages/elysia/LICENSE create mode 100644 packages/elysia/README.md create mode 100644 packages/elysia/package.json create mode 100644 packages/elysia/rollup.npm.config.mjs create mode 100644 packages/elysia/src/clientHooks.ts create mode 100644 packages/elysia/src/index.ts create mode 100644 packages/elysia/src/sdk.ts create mode 100644 packages/elysia/src/types.ts create mode 100644 packages/elysia/src/withElysia.ts create mode 100644 packages/elysia/test/sdk.test.ts create mode 100644 packages/elysia/test/withElysia.test.ts create mode 100644 packages/elysia/tsconfig.json create mode 100644 packages/elysia/tsconfig.test.json create mode 100644 packages/elysia/tsconfig.types.json diff --git a/.craft.yml b/.craft.yml index dd6f1a7f3453..b4499fbe2cd4 100644 --- a/.craft.yml +++ b/.craft.yml @@ -95,6 +95,9 @@ targets: - name: npm id: '@sentry/bun' includeNames: /^sentry-bun-\d.*\.tgz$/ + - name: npm + id: '@sentry/elysia' + includeNames: /^sentry-elysia-\d.*\.tgz$/ - name: npm id: '@sentry/hono' includeNames: /^sentry-hono-\d.*\.tgz$/ @@ -198,6 +201,8 @@ targets: onlyIfPresent: /^sentry-cloudflare-\d.*\.tgz$/ 'npm:@sentry/deno': onlyIfPresent: /^sentry-deno-\d.*\.tgz$/ + 'npm:@sentry/elysia': + onlyIfPresent: /^sentry-elysia-\d.*\.tgz$/ 'npm:@sentry/ember': onlyIfPresent: /^sentry-ember-\d.*\.tgz$/ 'npm:@sentry/gatsby': diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 305e975b48fd..47edbfeed264 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -46,6 +46,7 @@ body: - '@sentry/cloudflare - hono' - '@sentry/deno' - '@sentry/effect' + - '@sentry/elysia' - '@sentry/ember' - '@sentry/gatsby' - '@sentry/google-cloud-serverless' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 69523f544f2f..ed3f2d8678b8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -961,7 +961,7 @@ jobs: with: node-version-file: 'dev-packages/e2e-tests/test-applications/${{ matrix.test-application }}/package.json' - name: Set up Bun - if: contains(fromJSON('["node-exports-test-app","nextjs-16-bun"]'), matrix.test-application) + if: contains(fromJSON('["node-exports-test-app","nextjs-16-bun", "bun-elysia"]'), matrix.test-application) uses: oven-sh/setup-bun@v2 - name: Set up AWS SAM if: matrix.test-application == 'aws-serverless' diff --git a/.size-limit.js b/.size-limit.js index 750e7ce8f7fd..8935636df43f 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -184,7 +184,7 @@ module.exports = [ name: 'CDN Bundle (incl. Tracing)', path: createCDNPath('bundle.tracing.min.js'), gzip: true, - limit: '44 KB', + limit: '45 KB', }, { name: 'CDN Bundle (incl. Logs, Metrics)', @@ -196,37 +196,37 @@ module.exports = [ name: 'CDN Bundle (incl. Tracing, Logs, Metrics)', path: createCDNPath('bundle.tracing.logs.metrics.min.js'), gzip: true, - limit: '45 KB', + limit: '46 KB', }, { name: 'CDN Bundle (incl. Replay, Logs, Metrics)', path: createCDNPath('bundle.replay.logs.metrics.min.js'), gzip: true, - limit: '69 KB', + limit: '70 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay)', path: createCDNPath('bundle.tracing.replay.min.js'), gzip: true, - limit: '81 KB', + limit: '82 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Logs, Metrics)', path: createCDNPath('bundle.tracing.replay.logs.metrics.min.js'), gzip: true, - limit: '82 KB', + limit: '83 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Feedback)', path: createCDNPath('bundle.tracing.replay.feedback.min.js'), gzip: true, - limit: '86 KB', + limit: '88 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics)', path: createCDNPath('bundle.tracing.replay.feedback.logs.metrics.min.js'), gzip: true, - limit: '87 KB', + limit: '88 KB', }, // browser CDN bundles (non-gzipped) { @@ -241,7 +241,7 @@ module.exports = [ path: createCDNPath('bundle.tracing.min.js'), gzip: false, brotli: false, - limit: '129 KB', + limit: '133 KB', }, { name: 'CDN Bundle (incl. Logs, Metrics) - uncompressed', @@ -255,28 +255,28 @@ module.exports = [ path: createCDNPath('bundle.tracing.logs.metrics.min.js'), gzip: false, brotli: false, - limit: '132 KB', + limit: '136 KB', }, { name: 'CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed', path: createCDNPath('bundle.replay.logs.metrics.min.js'), gzip: false, brotli: false, - limit: '210 KB', + limit: '212 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay) - uncompressed', path: createCDNPath('bundle.tracing.replay.min.js'), gzip: false, brotli: false, - limit: '246 KB', + limit: '250 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed', path: createCDNPath('bundle.tracing.replay.logs.metrics.min.js'), gzip: false, brotli: false, - limit: '250 KB', + limit: '253 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed', @@ -290,7 +290,7 @@ module.exports = [ path: createCDNPath('bundle.tracing.replay.feedback.logs.metrics.min.js'), gzip: false, brotli: false, - limit: '264 KB', + limit: '266 KB', }, // Next.js SDK (ESM) { diff --git a/README.md b/README.md index 5ac7fefc3b81..841a6380b5e2 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ package. Please refer to the README and instructions of those SDKs for more deta for native crashes - [`@sentry/effect`](https://github.com/getsentry/sentry-javascript/tree/master/packages/effect): SDK for Effect (Alpha) - [`@sentry/bun`](https://github.com/getsentry/sentry-javascript/tree/master/packages/bun): SDK for Bun +- [`@sentry/elysia`](https://github.com/getsentry/sentry-javascript/tree/master/packages/elysia): SDK for Elysia - [`@sentry/deno`](https://github.com/getsentry/sentry-javascript/tree/master/packages/deno): SDK for Deno - [`@sentry/cloudflare`](https://github.com/getsentry/sentry-javascript/tree/master/packages/cloudflare): SDK for Cloudflare diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/.gitignore b/dev-packages/e2e-tests/test-applications/bun-elysia/.gitignore new file mode 100644 index 000000000000..1521c8b7652b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/bun-elysia/.gitignore @@ -0,0 +1 @@ +dist diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/.npmrc b/dev-packages/e2e-tests/test-applications/bun-elysia/.npmrc new file mode 100644 index 000000000000..070f80f05092 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/bun-elysia/.npmrc @@ -0,0 +1,2 @@ +@sentry:registry=http://127.0.0.1:4873 +@sentry-internal:registry=http://127.0.0.1:4873 diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/package.json b/dev-packages/e2e-tests/test-applications/bun-elysia/package.json new file mode 100644 index 000000000000..77fd6e13c0cb --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/bun-elysia/package.json @@ -0,0 +1,25 @@ +{ + "name": "bun-elysia-app", + "version": "1.0.0", + "private": true, + "scripts": { + "start": "bun src/app.ts", + "test": "playwright test", + "clean": "npx rimraf node_modules pnpm-lock.yaml", + "test:build": "pnpm install", + "test:assert": "pnpm test" + }, + "dependencies": { + "@elysiajs/opentelemetry": "^1.4.0", + "@sentry/elysia": "latest || *", + "elysia": "^1.4.0" + }, + "devDependencies": { + "@playwright/test": "~1.56.0", + "@sentry-internal/test-utils": "link:../../../test-utils", + "bun-types": "^1.2.9" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/bun-elysia/playwright.config.mjs new file mode 100644 index 000000000000..e684456a1896 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/bun-elysia/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `bun src/app.ts`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/src/app.ts b/dev-packages/e2e-tests/test-applications/bun-elysia/src/app.ts new file mode 100644 index 000000000000..db6a5fff8bd1 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/bun-elysia/src/app.ts @@ -0,0 +1,142 @@ +import * as Sentry from '@sentry/elysia'; +import { Elysia } from 'elysia'; + +Sentry.init({ + environment: 'qa', // dynamic sampling bias to keep transactions + dsn: process.env.E2E_TEST_DSN, + tunnel: `http://localhost:3031/`, // proxy server + tracesSampleRate: 1, + tracePropagationTargets: ['http://localhost:3030', '/external-allowed'], +}); + +const app = Sentry.withElysia(new Elysia()); + +// Simple success route +app.get('/test-success', () => ({ version: 'v1' })); + +// Parameterized route +app.get('/test-param/:param', ({ params }) => ({ paramWas: params.param })); + +// Multiple params +app.get('/test-multi-param/:param1/:param2', ({ params }) => ({ + param1: params.param1, + param2: params.param2, +})); + +// Route that throws an error (will be caught by onError) +app.get('/test-exception/:id', ({ params }) => { + throw new Error(`This is an exception with id ${params.id}`); +}); + +// Route with a custom span +app.get('/test-transaction', () => { + Sentry.startSpan({ name: 'test-span' }, () => { + Sentry.startSpan({ name: 'child-span' }, () => {}); + }); + return { status: 'ok' }; +}); + +// Route with specific middleware via .guard or .use +app.group('/with-middleware', app => + app + .onBeforeHandle(() => { + // This is a route-specific middleware + }) + .get('/test', () => ({ middleware: true })), +); + +// Error with specific status code +app.post('/test-post-error', () => { + throw new Error('Post error'); +}); + +// Route that returns a non-500 error +app.get('/test-4xx', ({ set }) => { + set.status = 400; + return { error: 'Bad Request' }; +}); + +// Error that reaches the error handler with status still set to 200 (unusual, should still be captured) +app.get('/test-error-with-200-status', ({ set }) => { + set.status = 200; + throw new Error('Error with 200 status'); +}); + +// POST route that echoes body +app.post('/test-post', ({ body }) => ({ status: 'ok', body })); + +// Route that returns inbound headers (for propagation tests) +app.get('/test-inbound-headers/:id', ({ params, request }) => { + const headers = Object.fromEntries(request.headers.entries()); + return { headers, id: params.id }; +}); + +// Outgoing fetch propagation +app.get('/test-outgoing-fetch/:id', async ({ params }) => { + const id = params.id; + const response = await fetch(`http://localhost:3030/test-inbound-headers/${id}`); + const data = await response.json(); + return data; +}); + +// Outgoing fetch to external (allowed by tracePropagationTargets) +app.get('/test-outgoing-fetch-external-allowed', async () => { + const response = await fetch(`http://localhost:3040/external-allowed`); + const data = await response.json(); + return data; +}); + +// Outgoing fetch to external (disallowed by tracePropagationTargets) +app.get('/test-outgoing-fetch-external-disallowed', async () => { + const response = await fetch(`http://localhost:3040/external-disallowed`); + const data = await response.json(); + return data; +}); + +// Route that throws a string (not an Error object) +app.get('/test-string-error', () => { + // eslint-disable-next-line no-throw-literal + throw 'String error message'; +}); + +// Route for concurrent isolation tests — returns scope data in response +app.get('/test-isolation/:userId', async ({ params }) => { + Sentry.setUser({ id: params.userId }); + Sentry.setTag('user_id', params.userId); + + // Simulate async work to increase overlap between concurrent requests + await new Promise(resolve => setTimeout(resolve, 200)); + + return { + userId: params.userId, + isolationScopeUserId: Sentry.getIsolationScope().getUser()?.id, + isolationScopeTag: Sentry.getIsolationScope().getScopeData().tags?.user_id, + }; +}); + +// Flush route for waiting on events +app.get('/flush', async () => { + await Sentry.flush(); + return { ok: true }; +}); + +app.listen(3030, () => { + console.log('Elysia app listening on port 3030'); +}); + +// Second app for external propagation tests +const app2 = new Elysia(); + +app2.get('/external-allowed', ({ request }) => { + const headers = Object.fromEntries(request.headers.entries()); + return { headers, route: '/external-allowed' }; +}); + +app2.get('/external-disallowed', ({ request }) => { + const headers = Object.fromEntries(request.headers.entries()); + return { headers, route: '/external-disallowed' }; +}); + +app2.listen(3040, () => { + console.log('External app listening on port 3040'); +}); diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/bun-elysia/start-event-proxy.mjs new file mode 100644 index 000000000000..400ce8a5e380 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/bun-elysia/start-event-proxy.mjs @@ -0,0 +1,6 @@ +import { startEventProxyServer } from '@sentry-internal/test-utils'; + +startEventProxyServer({ + port: 3031, + proxyServerName: 'bun-elysia', +}); diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/bun-elysia/tests/errors.test.ts new file mode 100644 index 000000000000..1dc7a4e5c7c8 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/bun-elysia/tests/errors.test.ts @@ -0,0 +1,109 @@ +import { expect, test } from '@playwright/test'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; + +test('Captures an error thrown in a route handler', async ({ baseURL, request }) => { + const errorEventPromise = waitForError('bun-elysia', event => { + return !event.type && event.exception?.values?.[0]?.value === 'This is an exception with id 123'; + }); + + await request.get(`${baseURL}/test-exception/123`); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.exception?.values).toHaveLength(1); + const exception = errorEvent.exception?.values?.[0]; + expect(exception?.value).toBe('This is an exception with id 123'); + expect(exception?.mechanism).toEqual({ + type: 'elysia', + handled: false, + }); + + expect(errorEvent.transaction).toEqual('GET /test-exception/:id'); + + expect(errorEvent.contexts?.trace).toEqual( + expect.objectContaining({ + trace_id: expect.stringMatching(/[a-f0-9]{32}/), + span_id: expect.stringMatching(/[a-f0-9]{16}/), + }), + ); +}); + +test('Error event includes request metadata', async ({ baseURL, request }) => { + const errorEventPromise = waitForError('bun-elysia', event => { + return !event.type && event.exception?.values?.[0]?.value === 'This is an exception with id 456'; + }); + + await request.get(`${baseURL}/test-exception/456`); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.request).toEqual( + expect.objectContaining({ + method: 'GET', + url: expect.stringContaining('/test-exception/456'), + headers: expect.any(Object), + }), + ); +}); + +test('Does not capture errors for 4xx responses', async ({ baseURL, request }) => { + const transactionPromise = waitForTransaction('bun-elysia', transactionEvent => { + return transactionEvent?.transaction === 'GET /test-4xx'; + }); + + const response = await request.get(`${baseURL}/test-4xx`); + // Wait for the transaction to ensure the request was processed + await transactionPromise; + + expect(response.status()).toBe(400); +}); + +test('Captures errors even when status is <= 299 in error handler', async ({ baseURL, request }) => { + const errorEventPromise = waitForError('bun-elysia', event => { + return !event.type && event.exception?.values?.[0]?.value === 'Error with 200 status'; + }); + + await request.get(`${baseURL}/test-error-with-200-status`); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.exception?.values?.[0]?.value).toBe('Error with 200 status'); + expect(errorEvent.exception?.values?.[0]?.mechanism).toEqual({ + type: 'elysia', + handled: false, + }); +}); + +test('Captures POST route errors', async ({ baseURL, request }) => { + const errorEventPromise = waitForError('bun-elysia', event => { + return !event.type && event.exception?.values?.[0]?.value === 'Post error'; + }); + + await request.post(`${baseURL}/test-post-error`); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.exception?.values?.[0]?.value).toBe('Post error'); + expect(errorEvent.exception?.values?.[0]?.mechanism).toEqual({ + type: 'elysia', + handled: false, + }); +}); + +test('Captures thrown string errors', async ({ baseURL, request }) => { + const errorEventPromise = waitForError('bun-elysia', event => { + return !event.type && event.exception?.values?.[0]?.value === 'String error message'; + }); + + await request.get(`${baseURL}/test-string-error`); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.exception?.values?.[0]?.value).toBe('String error message'); + expect(errorEvent.exception?.values?.[0]?.mechanism).toEqual( + expect.objectContaining({ + type: 'elysia', + handled: false, + }), + ); +}); diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/tests/isolation.test.ts b/dev-packages/e2e-tests/test-applications/bun-elysia/tests/isolation.test.ts new file mode 100644 index 000000000000..3bdc1cc2e99d --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/bun-elysia/tests/isolation.test.ts @@ -0,0 +1,30 @@ +import { expect, test } from '@playwright/test'; + +// The Elysia integration currently does not fork isolation scopes per request, +// so `setUser`/`setTag` on the isolation scope leaks between concurrent requests. +// This test documents the expected behavior once per-request isolation is implemented. +test.fixme('Concurrent requests have isolated scope data', async ({ baseURL }) => { + // Fire 3 concurrent requests with different user IDs + const [response1, response2, response3] = await Promise.all([ + fetch(`${baseURL}/test-isolation/user-1`), + fetch(`${baseURL}/test-isolation/user-2`), + fetch(`${baseURL}/test-isolation/user-3`), + ]); + + const data1 = await response1.json(); + const data2 = await response2.json(); + const data3 = await response3.json(); + + // Each response should have its own user ID — no leaking between requests + expect(data1.userId).toBe('user-1'); + expect(data1.isolationScopeUserId).toBe('user-1'); + expect(data1.isolationScopeTag).toBe('user-1'); + + expect(data2.userId).toBe('user-2'); + expect(data2.isolationScopeUserId).toBe('user-2'); + expect(data2.isolationScopeTag).toBe('user-2'); + + expect(data3.userId).toBe('user-3'); + expect(data3.isolationScopeUserId).toBe('user-3'); + expect(data3.isolationScopeTag).toBe('user-3'); +}); diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/tests/propagation.test.ts b/dev-packages/e2e-tests/test-applications/bun-elysia/tests/propagation.test.ts new file mode 100644 index 000000000000..b7af9b893a6d --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/bun-elysia/tests/propagation.test.ts @@ -0,0 +1,113 @@ +import { randomUUID } from 'node:crypto'; +import { expect, test } from '@playwright/test'; +import { waitForTransaction } from '@sentry-internal/test-utils'; + +test('Includes sentry-trace and baggage in response headers', async ({ baseURL }) => { + const response = await fetch(`${baseURL}/test-success`); + + const sentryTrace = response.headers.get('sentry-trace'); + const baggage = response.headers.get('baggage'); + + expect(sentryTrace).toMatch(/[a-f0-9]{32}-[a-f0-9]{16}-[01]/); + expect(baggage).toContain('sentry-environment=qa'); + expect(baggage).toContain('sentry-trace_id='); +}); + +// Bun's native fetch does not emit undici diagnostics channels, +// so the nativeNodeFetchIntegration cannot inject sentry-trace/baggage headers. +// These tests document the desired behavior and will pass once Bun adds support +// for undici diagnostics channels or an alternative propagation mechanism is added. + +test.fixme('Propagates trace for outgoing fetch requests', async ({ baseURL }) => { + const id = randomUUID(); + + const inboundTransactionPromise = waitForTransaction('bun-elysia', transactionEvent => { + return ( + transactionEvent.contexts?.trace?.op === 'http.server' && + transactionEvent.transaction === 'GET /test-inbound-headers/:id' + ); + }); + + const outboundTransactionPromise = waitForTransaction('bun-elysia', transactionEvent => { + return ( + transactionEvent.contexts?.trace?.op === 'http.server' && + transactionEvent.transaction === 'GET /test-outgoing-fetch/:id' + ); + }); + + const response = await fetch(`${baseURL}/test-outgoing-fetch/${id}`); + const data = await response.json(); + + const inboundTransaction = await inboundTransactionPromise; + const outboundTransaction = await outboundTransactionPromise; + + const traceId = outboundTransaction?.contexts?.trace?.trace_id; + expect(traceId).toEqual(expect.any(String)); + + // Verify sentry-trace header was propagated to the inbound request + const inboundHeaderSentryTrace = data.headers?.['sentry-trace']; + const inboundHeaderBaggage = data.headers?.['baggage']; + + expect(inboundHeaderSentryTrace).toMatch(new RegExp(`^${traceId}-[a-f0-9]{16}-1$`)); + expect(inboundHeaderBaggage).toBeDefined(); + + const baggage = (inboundHeaderBaggage || '').split(','); + expect(baggage).toEqual( + expect.arrayContaining([ + 'sentry-environment=qa', + `sentry-trace_id=${traceId}`, + expect.stringMatching(/sentry-public_key=/), + ]), + ); + + // Both transactions should share the same trace ID + expect(inboundTransaction.contexts?.trace?.trace_id).toBe(traceId); +}); + +test.fixme('Propagates trace for outgoing fetch to external allowed URL', async ({ baseURL }) => { + const inboundTransactionPromise = waitForTransaction('bun-elysia', transactionEvent => { + return ( + transactionEvent.contexts?.trace?.op === 'http.server' && + transactionEvent.transaction === 'GET /test-outgoing-fetch-external-allowed' + ); + }); + + const response = await fetch(`${baseURL}/test-outgoing-fetch-external-allowed`); + const data = await response.json(); + + const inboundTransaction = await inboundTransactionPromise; + const traceId = inboundTransaction?.contexts?.trace?.trace_id; + + expect(traceId).toEqual(expect.any(String)); + + expect(data.route).toBe('/external-allowed'); + expect(data.headers?.['sentry-trace']).toMatch(/[a-f0-9]{32}-[a-f0-9]{16}-1/); + expect(data.headers?.baggage).toBeDefined(); + + const baggage = (data.headers.baggage || '').split(','); + expect(baggage).toEqual( + expect.arrayContaining([ + 'sentry-environment=qa', + `sentry-trace_id=${traceId}`, + expect.stringMatching(/sentry-public_key=/), + ]), + ); +}); + +test('Does not propagate outgoing fetch requests not covered by tracePropagationTargets', async ({ baseURL }) => { + const inboundTransactionPromise = waitForTransaction('bun-elysia', transactionEvent => { + return ( + transactionEvent.contexts?.trace?.op === 'http.server' && + transactionEvent.transaction === 'GET /test-outgoing-fetch-external-disallowed' + ); + }); + + const response = await fetch(`${baseURL}/test-outgoing-fetch-external-disallowed`); + const data = await response.json(); + + await inboundTransactionPromise; + + expect(data.route).toBe('/external-disallowed'); + expect(data.headers?.['sentry-trace']).toBeUndefined(); + expect(data.headers?.baggage).toBeUndefined(); +}); diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/bun-elysia/tests/transactions.test.ts new file mode 100644 index 000000000000..fd3166b2fea1 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/bun-elysia/tests/transactions.test.ts @@ -0,0 +1,211 @@ +import { expect, test } from '@playwright/test'; +import { waitForTransaction } from '@sentry-internal/test-utils'; + +test('Sends a transaction for a successful route', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /test-success' + ); + }); + + await request.get(`${baseURL}/test-success`); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent).toEqual( + expect.objectContaining({ + transaction: 'GET /test-success', + type: 'transaction', + transaction_info: { + source: 'route', + }, + }), + ); + + expect(transactionEvent.contexts?.trace).toEqual( + expect.objectContaining({ + op: 'http.server', + status: 'ok', + trace_id: expect.stringMatching(/[a-f0-9]{32}/), + span_id: expect.stringMatching(/[a-f0-9]{16}/), + }), + ); +}); + +test('Sends a transaction with parameterized route name', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && + transactionEvent?.transaction === 'GET /test-param/:param' + ); + }); + + await request.get(`${baseURL}/test-param/123`); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent.transaction).toBe('GET /test-param/:param'); + expect(transactionEvent.transaction_info?.source).toBe('route'); +}); + +test('Sends a transaction with multiple parameterized segments', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && + transactionEvent?.transaction === 'GET /test-multi-param/:param1/:param2' + ); + }); + + await request.get(`${baseURL}/test-multi-param/foo/bar`); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent.transaction).toBe('GET /test-multi-param/:param1/:param2'); + expect(transactionEvent.transaction_info?.source).toBe('route'); +}); + +test('Sends a transaction for an errored route', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && + transactionEvent?.transaction === 'GET /test-exception/:id' + ); + }); + + await request.get(`${baseURL}/test-exception/777`); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent.transaction).toBe('GET /test-exception/:id'); + expect(transactionEvent.contexts?.trace?.status).toBe('internal_error'); +}); + +test('Includes manually started spans with parent-child relationship', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && + transactionEvent?.transaction === 'GET /test-transaction' + ); + }); + + await request.get(`${baseURL}/test-transaction`); + + const transactionEvent = await transactionEventPromise; + const spans = transactionEvent.spans || []; + + const testSpan = spans.find(span => span.description === 'test-span'); + const childSpan = spans.find(span => span.description === 'child-span'); + + expect(testSpan).toEqual( + expect.objectContaining({ + description: 'test-span', + origin: 'manual', + }), + ); + + expect(childSpan).toEqual( + expect.objectContaining({ + description: 'child-span', + origin: 'manual', + parent_span_id: testSpan?.span_id, + }), + ); +}); + +test('Creates lifecycle spans for Elysia hooks', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /test-success' + ); + }); + + await request.get(`${baseURL}/test-success`); + + const transactionEvent = await transactionEventPromise; + const spans = transactionEvent.spans || []; + + // Elysia should produce lifecycle spans enriched with sentry attributes + const elysiaSpans = spans.filter(span => span.origin === 'auto.http.otel.elysia'); + expect(elysiaSpans.length).toBeGreaterThan(0); + + // The Handle span should be present as a request handler + expect(spans).toContainEqual( + expect.objectContaining({ + description: 'Handle', + op: 'request_handler.elysia', + origin: 'auto.http.otel.elysia', + }), + ); +}); + +test('Filters out empty anonymous Elysia spans but keeps all other spans', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /test-success' + ); + }); + + await request.get(`${baseURL}/test-success`); + + const transactionEvent = await transactionEventPromise; + const spans = transactionEvent.spans || []; + + // Elysia produces empty anonymous spans for arrow function handlers that show up as . + // These should be filtered out by our beforeSendEvent hook. + const unknownSpans = spans.filter(span => span.description === ''); + expect(unknownSpans).toHaveLength(0); + + // But named Elysia lifecycle spans should still be present + expect(spans.filter(span => span.origin === 'auto.http.otel.elysia').length).toBeGreaterThan(0); +}); + +test('Creates lifecycle spans for route-specific middleware', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && + transactionEvent?.transaction === 'GET /with-middleware/test' + ); + }); + + await request.get(`${baseURL}/with-middleware/test`); + + const transactionEvent = await transactionEventPromise; + const spans = transactionEvent.spans || []; + + // BeforeHandle span should be present from the route-specific middleware + expect(spans).toContainEqual( + expect.objectContaining({ + description: 'BeforeHandle', + op: 'middleware.elysia', + origin: 'auto.http.otel.elysia', + }), + ); +}); + +test('Captures request metadata for POST requests', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'POST /test-post' + ); + }); + + const response = await request.post(`${baseURL}/test-post`, { + data: { foo: 'bar', other: 1 }, + headers: { 'Content-Type': 'application/json' }, + }); + const resBody = await response.json(); + + expect(resBody).toEqual({ status: 'ok', body: { foo: 'bar', other: 1 } }); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent.request).toEqual( + expect.objectContaining({ + method: 'POST', + url: expect.stringContaining('/test-post'), + headers: expect.objectContaining({ + 'content-type': 'application/json', + }), + }), + ); +}); diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/tsconfig.json b/dev-packages/e2e-tests/test-applications/bun-elysia/tsconfig.json new file mode 100644 index 000000000000..869427e44d4d --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/bun-elysia/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "types": ["bun-types"], + "esModuleInterop": true, + "lib": ["es2020"], + "strict": true, + "outDir": "dist", + "skipLibCheck": true + }, + "include": ["src/**/*.ts"] +} diff --git a/dev-packages/e2e-tests/test-applications/node-exports-test-app/scripts/consistentExports.ts b/dev-packages/e2e-tests/test-applications/node-exports-test-app/scripts/consistentExports.ts index 17c6f714c499..1ddb8e57c0b3 100644 --- a/dev-packages/e2e-tests/test-applications/node-exports-test-app/scripts/consistentExports.ts +++ b/dev-packages/e2e-tests/test-applications/node-exports-test-app/scripts/consistentExports.ts @@ -41,6 +41,8 @@ const DEPENDENTS: Dependent[] = [ ignoreExports: [ // Not needed for Astro 'setupFastifyErrorHandler', + 'elysiaIntegration', + 'withElysia', ], }, { @@ -75,6 +77,8 @@ const DEPENDENTS: Dependent[] = [ ignoreExports: [ // Not needed for Serverless 'setupFastifyErrorHandler', + 'elysiaIntegration', + 'withElysia', ], }, { @@ -84,6 +88,8 @@ const DEPENDENTS: Dependent[] = [ ignoreExports: [ // Not needed for Serverless 'setupFastifyErrorHandler', + 'elysiaIntegration', + 'withElysia', ], }, { diff --git a/dev-packages/e2e-tests/verdaccio-config/config.yaml b/dev-packages/e2e-tests/verdaccio-config/config.yaml index beb758aca018..9d726fdf772f 100644 --- a/dev-packages/e2e-tests/verdaccio-config/config.yaml +++ b/dev-packages/e2e-tests/verdaccio-config/config.yaml @@ -80,6 +80,12 @@ packages: unpublish: $all # proxy: npmjs # Don't proxy for E2E tests! + '@sentry/elysia': + access: $all + publish: $all + unpublish: $all + # proxy: npmjs # Don't proxy for E2E tests! + '@sentry/ember': access: $all publish: $all diff --git a/package.json b/package.json index 42edbcaf8879..547b6a065fdb 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "packages/deno", "packages/effect", "packages/ember", + "packages/elysia", "packages/eslint-config-sdk", "packages/eslint-plugin-sdk", "packages/feedback", @@ -157,7 +158,11 @@ "wide-align/string-width": "4.2.3", "cliui/wrap-ansi": "7.0.0", "sucrase": "getsentry/sucrase#es2020-polyfills", - "**/express/path-to-regexp": "0.1.12" + "**/express/path-to-regexp": "0.1.12", + "**/@opentelemetry/core": "2.6.0", + "**/@opentelemetry/resources": "2.6.0", + "**/@opentelemetry/sdk-trace-base": "2.6.0", + "**/@opentelemetry/instrumentation": "0.213.0" }, "version": "0.0.0", "name": "sentry-javascript" diff --git a/packages/elysia/.eslintrc.js b/packages/elysia/.eslintrc.js new file mode 100644 index 000000000000..6da218bd8641 --- /dev/null +++ b/packages/elysia/.eslintrc.js @@ -0,0 +1,9 @@ +module.exports = { + env: { + node: true, + }, + extends: ['../../.eslintrc.js'], + rules: { + '@sentry-internal/sdk/no-class-field-initializers': 'off', + }, +}; diff --git a/packages/elysia/LICENSE b/packages/elysia/LICENSE new file mode 100644 index 000000000000..b3c4b18a6317 --- /dev/null +++ b/packages/elysia/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Functional Software, Inc. dba Sentry + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/elysia/README.md b/packages/elysia/README.md new file mode 100644 index 000000000000..29143f36cb63 --- /dev/null +++ b/packages/elysia/README.md @@ -0,0 +1,34 @@ +

+ + Sentry + +

+ +# Official Sentry SDK for Elysia + +[![npm version](https://img.shields.io/npm/v/@sentry/elysia.svg)](https://www.npmjs.com/package/@sentry/elysia) +[![npm dm](https://img.shields.io/npm/dm/@sentry/elysia.svg)](https://www.npmjs.com/package/@sentry/elysia) +[![npm dt](https://img.shields.io/npm/dt/@sentry/elysia.svg)](https://www.npmjs.com/package/@sentry/elysia) + +> **Alpha**: This SDK is in alpha stage and may have breaking changes in future releases. + +## Links + +- [Official SDK Docs](https://docs.sentry.io/platforms/javascript/guides/elysia/) +- [TypeDoc](http://getsentry.github.io/sentry-javascript/) + +## Usage + +```javascript +import * as Sentry from '@sentry/elysia'; +import { Elysia } from 'elysia'; + +Sentry.init({ + dsn: '__DSN__', + tracesSampleRate: 1.0, +}); + +const app = Sentry.withElysia(new Elysia()) + .get('/', () => 'Hello World') + .listen(3000); +``` diff --git a/packages/elysia/package.json b/packages/elysia/package.json new file mode 100644 index 000000000000..196208747dcc --- /dev/null +++ b/packages/elysia/package.json @@ -0,0 +1,86 @@ +{ + "name": "@sentry/elysia", + "version": "10.43.0", + "description": "Official Sentry SDK for Elysia", + "repository": "git://github.com/getsentry/sentry-javascript.git", + "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/elysia", + "author": "Sentry", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "files": [ + "/build" + ], + "main": "build/cjs/index.js", + "module": "build/esm/index.js", + "types": "build/types/index.d.ts", + "exports": { + "./package.json": "./package.json", + ".": { + "import": { + "types": "./build/types/index.d.ts", + "default": "./build/esm/index.js" + }, + "require": { + "types": "./build/types/index.d.ts", + "default": "./build/cjs/index.js" + } + } + }, + "typesVersions": { + "<5.0": { + "build/types/index.d.ts": [ + "build/types-ts3.8/index.d.ts" + ] + } + }, + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@sentry/bun": "10.43.0", + "@sentry/core": "10.43.0" + }, + "peerDependencies": { + "elysia": "^1.4.0", + "@elysiajs/opentelemetry": "^1.4.0" + }, + "devDependencies": { + "@elysiajs/opentelemetry": "^1.4.0", + "bun-types": "^1.2.9", + "elysia": "^1.4.0" + }, + "peerDependenciesMeta": { + "elysia": { + "optional": false + }, + "@elysiajs/opentelemetry": { + "optional": false + } + }, + "scripts": { + "build": "run-p build:transpile build:types", + "build:dev": "yarn build", + "build:transpile": "rollup -c rollup.npm.config.mjs", + "build:types": "run-s build:types:core build:types:downlevel", + "build:types:core": "tsc -p tsconfig.types.json", + "build:types:downlevel": "yarn downlevel-dts build/types build/types-ts3.8 --to ts3.8", + "build:watch": "run-p build:transpile:watch", + "build:dev:watch": "yarn build:watch", + "build:transpile:watch": "rollup -c rollup.npm.config.mjs --watch", + "build:tarball": "npm pack", + "circularDepCheck": "madge --circular src/index.ts", + "clean": "rimraf build coverage sentry-elysia-*.tgz", + "fix": "eslint . --format stylish --fix", + "lint": "eslint . --format stylish", + "lint:es-compatibility": "es-check es2022 ./build/cjs/*.js && es-check es2022 ./build/esm/*.js --module", + "test": "vitest run", + "test:watch": "vitest --watch", + "yalc:publish": "yalc publish --push --sig" + }, + "volta": { + "extends": "../../package.json" + }, + "sideEffects": false +} diff --git a/packages/elysia/rollup.npm.config.mjs b/packages/elysia/rollup.npm.config.mjs new file mode 100644 index 000000000000..6aa756423128 --- /dev/null +++ b/packages/elysia/rollup.npm.config.mjs @@ -0,0 +1,3 @@ +import { makeBaseNPMConfig, makeNPMConfigVariants } from '@sentry-internal/rollup-utils'; + +export default makeNPMConfigVariants(makeBaseNPMConfig({})); diff --git a/packages/elysia/src/clientHooks.ts b/packages/elysia/src/clientHooks.ts new file mode 100644 index 000000000000..6d1cb0cd646b --- /dev/null +++ b/packages/elysia/src/clientHooks.ts @@ -0,0 +1,63 @@ +import type { Client, Event, Span } from '@sentry/core'; +import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, spanToJSON } from '@sentry/core'; + +const ELYSIA_ORIGIN = 'auto.http.otel.elysia'; + +const ELYSIA_LIFECYCLE_OP_MAP: Record = { + Request: 'middleware.elysia', + Parse: 'middleware.elysia', + Transform: 'middleware.elysia', + BeforeHandle: 'middleware.elysia', + Handle: 'request_handler.elysia', + AfterHandle: 'middleware.elysia', + MapResponse: 'middleware.elysia', + AfterResponse: 'middleware.elysia', + Error: 'middleware.elysia', +}; + +/** + * Enrich Elysia lifecycle spans with semantic op and origin, + * and filter out empty anonymous child spans that Elysia produces. + */ +export function setupClientHooks(client: Client): void { + // Enrich Elysia lifecycle spans with semantic op and origin. + // We mutate the attributes directly because the span has already ended + // and `setAttribute()` is a no-op on ended OTel spans. + client.on('spanEnd', (span: Span) => { + const spanData = spanToJSON(span); + const op = ELYSIA_LIFECYCLE_OP_MAP[spanData.description || '']; + if (op && spanData.data) { + const attrs = spanData.data; + attrs[SEMANTIC_ATTRIBUTE_SENTRY_OP] = op; + attrs[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = ELYSIA_ORIGIN; + } + }); + + // Filter out empty child spans that Elysia produces for each function handler. + // Users usually use arrow functions so they show up as . + // We identify Elysia spans by checking if their parent is an Elysia lifecycle span + // (one we enriched with our origin), so we don't accidentally drop spans from other integrations. + client.on('beforeSendEvent', (event: Event) => { + if (event.type === 'transaction' && event.spans) { + const elysiaSpanIds = new Set(); + for (const span of event.spans) { + if (span.origin === ELYSIA_ORIGIN) { + elysiaSpanIds.add(span.span_id); + } + } + + if (elysiaSpanIds.size > 0) { + event.spans = event.spans.filter(span => { + if ( + (!span.description || span.description === '') && + span.parent_span_id && + elysiaSpanIds.has(span.parent_span_id) + ) { + return false; + } + return true; + }); + } + } + }); +} diff --git a/packages/elysia/src/index.ts b/packages/elysia/src/index.ts new file mode 100644 index 000000000000..8a5c5e622de1 --- /dev/null +++ b/packages/elysia/src/index.ts @@ -0,0 +1,195 @@ +// Re-export everything from @sentry/bun +export { + addEventProcessor, + addBreadcrumb, + addIntegration, + captureException, + captureEvent, + captureMessage, + captureCheckIn, + captureFeedback, + startSession, + captureSession, + endSession, + withMonitor, + createTransport, + getClient, + isInitialized, + isEnabled, + generateInstrumentOnce, + getCurrentScope, + getGlobalScope, + getIsolationScope, + getTraceData, + getTraceMetaTags, + setCurrentClient, + Scope, + SDK_VERSION, + setContext, + setConversationId, + setExtra, + setExtras, + setTag, + setTags, + setUser, + getSpanStatusFromHttpCode, + setHttpStatus, + withScope, + withIsolationScope, + makeNodeTransport, + NodeClient, + defaultStackParser, + lastEventId, + flush, + close, + getSentryRelease, + createGetModuleFromFilename, + createLangChainCallbackHandler, + httpHeadersToSpanAttributes, + winterCGHeadersToDict, + // eslint-disable-next-line deprecation/deprecation + anrIntegration, + // eslint-disable-next-line deprecation/deprecation + disableAnrDetectionForCallback, + consoleIntegration, + httpIntegration, + httpServerIntegration, + httpServerSpansIntegration, + nativeNodeFetchIntegration, + onUncaughtExceptionIntegration, + onUnhandledRejectionIntegration, + openAIIntegration, + langChainIntegration, + langGraphIntegration, + modulesIntegration, + contextLinesIntegration, + nodeContextIntegration, + localVariablesIntegration, + requestDataIntegration, + fsIntegration, + functionToStringIntegration, + // eslint-disable-next-line deprecation/deprecation + inboundFiltersIntegration, + eventFiltersIntegration, + linkedErrorsIntegration, + setMeasurement, + getActiveSpan, + startSpan, + startInactiveSpan, + startSpanManual, + startNewTrace, + suppressTracing, + withActiveSpan, + getRootSpan, + getSpanDescendants, + continueTrace, + getAutoPerformanceIntegrations, + cron, + parameterize, + SEMANTIC_ATTRIBUTE_SENTRY_OP, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, + SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, + dataloaderIntegration, + expressIntegration, + expressErrorHandler, + setupExpressErrorHandler, + fastifyIntegration, + setupFastifyErrorHandler, + firebaseIntegration, + koaIntegration, + setupKoaErrorHandler, + connectIntegration, + setupConnectErrorHandler, + genericPoolIntegration, + graphqlIntegration, + knexIntegration, + kafkaIntegration, + lruMemoizerIntegration, + mongoIntegration, + mongooseIntegration, + mysqlIntegration, + mysql2Integration, + redisIntegration, + tediousIntegration, + postgresIntegration, + postgresJsIntegration, + prismaIntegration, + processSessionIntegration, + hapiIntegration, + setupHapiErrorHandler, + honoIntegration, + setupHonoErrorHandler, + spotlightIntegration, + initOpenTelemetry, + spanToJSON, + spanToTraceHeader, + spanToBaggageHeader, + trpcMiddleware, + updateSpanName, + supabaseIntegration, + instrumentSupabaseClient, + instrumentOpenAiClient, + instrumentAnthropicAiClient, + instrumentGoogleGenAIClient, + instrumentLangGraph, + instrumentStateGraphCompile, + zodErrorsIntegration, + profiler, + amqplibIntegration, + anthropicAIIntegration, + googleGenAIIntegration, + vercelAIIntegration, + logger, + consoleLoggingIntegration, + createConsolaReporter, + createSentryWinstonTransport, + wrapMcpServerWithSentry, + featureFlagsIntegration, + launchDarklyIntegration, + growthbookIntegration, + buildLaunchDarklyFlagUsedHandler, + openFeatureIntegration, + OpenFeatureIntegrationHook, + statsigIntegration, + unleashIntegration, + metrics, + bunServerIntegration, + makeFetchTransport, +} from '@sentry/bun'; + +export type { + Breadcrumb, + BreadcrumbHint, + PolymorphicRequest, + RequestEventData, + SdkInfo, + Event, + EventHint, + ErrorEvent, + Exception, + Session, + SeverityLevel, + Span, + StackFrame, + Stacktrace, + Thread, + User, + FeatureFlagsIntegration, + Metric, + ExclusiveEventHintOrCaptureContext, + CaptureContext, +} from '@sentry/core'; + +export { + captureConsoleIntegration, + dedupeIntegration, + extraErrorDataIntegration, + rewriteFramesIntegration, +} from '@sentry/core'; + +export type { ElysiaOptions } from './types'; + +// Elysia-specific exports +export { withElysia } from './withElysia'; +export { getDefaultIntegrations, init } from './sdk'; diff --git a/packages/elysia/src/sdk.ts b/packages/elysia/src/sdk.ts new file mode 100644 index 000000000000..567af8834c93 --- /dev/null +++ b/packages/elysia/src/sdk.ts @@ -0,0 +1,60 @@ +import * as os from 'node:os'; +import { + bunServerIntegration, + getDefaultIntegrations as getBunDefaultIntegrations, + makeFetchTransport, +} from '@sentry/bun'; +import type { Integration, Options } from '@sentry/core'; +import { applySdkMetadata } from '@sentry/core'; +import { init as initNode, type NodeClient } from '@sentry/bun'; +import type { ElysiaOptions } from './types'; + +/** Get the default integrations for the Elysia SDK. */ +export function getDefaultIntegrations(_options: Options): Integration[] { + // Filter out bunServerIntegration + // Elysia already produces an HTTP server span, so we don't need Bun's competing root span. + return getBunDefaultIntegrations(_options).filter(i => i.name !== bunServerIntegration().name); +} + +/** + * Get the runtime name and version. + */ +function getRuntime(): { name: string; version: string } { + if (typeof Bun !== 'undefined') { + return { name: 'bun', version: Bun.version }; + } + + return { name: 'node', version: process.version }; +} + +/** + * Initializes the Sentry Elysia SDK. + * + * @example + * ```javascript + * import * as Sentry from '@sentry/elysia'; + * + * Sentry.init({ + * dsn: '__DSN__', + * tracesSampleRate: 1.0, + * }); + * ``` + */ +export function init(userOptions: ElysiaOptions = {}): NodeClient | undefined { + applySdkMetadata(userOptions, 'elysia'); + + const options = { + ...userOptions, + platform: 'javascript', + runtime: getRuntime(), + serverName: userOptions.serverName || global.process.env.SENTRY_NAME || os.hostname(), + }; + + options.transport = options.transport || makeFetchTransport; + + if (options.defaultIntegrations === undefined) { + options.defaultIntegrations = getDefaultIntegrations(options); + } + + return initNode(options); +} diff --git a/packages/elysia/src/types.ts b/packages/elysia/src/types.ts new file mode 100644 index 000000000000..78b4afd14e87 --- /dev/null +++ b/packages/elysia/src/types.ts @@ -0,0 +1,6 @@ +import type { BunOptions } from '@sentry/bun'; + +/** + * Configuration options for the Sentry Elysia SDK. + */ +export type ElysiaOptions = BunOptions; diff --git a/packages/elysia/src/withElysia.ts b/packages/elysia/src/withElysia.ts new file mode 100644 index 000000000000..7e3b63c368c5 --- /dev/null +++ b/packages/elysia/src/withElysia.ts @@ -0,0 +1,107 @@ +import { opentelemetry } from '@elysiajs/opentelemetry'; +import { + captureException, + getClient, + getIsolationScope, + getTraceData, + winterCGRequestToRequestData, +} from '@sentry/core'; +import type { Elysia, ErrorContext } from 'elysia'; +import { setupClientHooks } from './clientHooks'; + +interface ElysiaHandlerOptions { + shouldHandleError: (context: ErrorContext) => boolean; +} + +let isClientHooksSetup = false; +const instrumentedApps = new WeakSet(); + +function defaultShouldHandleError(context: ErrorContext): boolean { + const status = context.set.status; + if (status === undefined) { + return true; + } + const statusCode = typeof status === 'string' ? parseInt(status, 10) : status; + if (Number.isNaN(statusCode)) { + return true; + } + // Capture server errors (5xx) and unusual status codes (<= 299 in an error handler). + // 3xx and 4xx are not captured by default (client errors / redirects). + return statusCode >= 500 || statusCode <= 299; +} + +/** + * Integrate Sentry with an Elysia app for error handling, request context, + * and tracing. Returns the app instance for chaining. + * + * Should be called at the **start** of the chain before defining routes. + * + * @param app The Elysia instance + * @param options Configuration options + * @returns The same Elysia instance for chaining + * + * @example + * ```javascript + * import * as Sentry from '@sentry/elysia'; + * import { Elysia } from 'elysia'; + * + * Sentry.withElysia(new Elysia()) + * .get('/', () => 'Hello World') + * .listen(3000); + * ``` + */ +export function withElysia(app: T, options?: Partial): T { + if (instrumentedApps.has(app)) { + return app; + } + instrumentedApps.add(app); + + // Register the opentelemetry plugin + // https://elysiajs.com/plugins/opentelemetry + app.use(opentelemetry()); + + if (!isClientHooksSetup) { + const client = getClient(); + if (client) { + isClientHooksSetup = true; + setupClientHooks(client); + } + } + + // Set SDK processing metadata for all requests + app.onRequest(context => { + getIsolationScope().setSDKProcessingMetadata({ + normalizedRequest: winterCGRequestToRequestData(context.request), + }); + }); + + // Propagate trace data to all response headers + app.onAfterHandle({ as: 'global' }, context => { + const traceData = getTraceData(); + if (traceData['sentry-trace']) { + context.set.headers['sentry-trace'] = traceData['sentry-trace']; + } + if (traceData.baggage) { + context.set.headers['baggage'] = traceData.baggage; + } + }); + + // Register the error handler for all routes + app.onError({ as: 'global' }, context => { + if (context.route) { + getIsolationScope().setTransactionName(`${context.request.method} ${context.route}`); + } + + const shouldHandleError = options?.shouldHandleError || defaultShouldHandleError; + if (shouldHandleError(context)) { + captureException(context.error, { + mechanism: { + type: 'elysia', + handled: false, + }, + }); + } + }); + + return app; +} diff --git a/packages/elysia/test/sdk.test.ts b/packages/elysia/test/sdk.test.ts new file mode 100644 index 000000000000..c85cae154a38 --- /dev/null +++ b/packages/elysia/test/sdk.test.ts @@ -0,0 +1,123 @@ +import type { Integration } from '@sentry/core'; +import { afterEach, describe, expect, it, vi } from 'vitest'; + +const mockApplySdkMetadata = vi.fn(); +const mockInitNode = vi.fn(); +const mockGetBunDefaultIntegrations = vi.fn(() => [] as Integration[]); +const mockMakeFetchTransport = vi.fn(); + +vi.mock('@sentry/core', async importActual => { + // eslint-disable-next-line @typescript-eslint/consistent-type-imports + const actual = await importActual(); + return { + ...actual, + applySdkMetadata: mockApplySdkMetadata, + }; +}); + +vi.mock('@sentry/bun', () => ({ + init: mockInitNode, + getDefaultIntegrations: mockGetBunDefaultIntegrations, + makeFetchTransport: mockMakeFetchTransport, + bunServerIntegration: () => ({ name: 'BunServer', setupOnce: vi.fn() }), +})); + +// Must import after mocks are set up +// @ts-expect-error - dynamic import +const { init, getDefaultIntegrations } = await import('../src/sdk'); + +describe('init', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + it('sets SDK metadata to elysia', () => { + init({ dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' }); + + expect(mockApplySdkMetadata).toHaveBeenCalledWith( + expect.objectContaining({ dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' }), + 'elysia', + ); + }); + + it('calls initNode with the options', () => { + init({ dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' }); + + expect(mockInitNode).toHaveBeenCalledWith( + expect.objectContaining({ + dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0', + platform: 'javascript', + }), + ); + }); + + it('uses makeFetchTransport by default', () => { + init({ dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' }); + + expect(mockInitNode).toHaveBeenCalledWith( + expect.objectContaining({ + transport: mockMakeFetchTransport, + }), + ); + }); + + it('allows overriding transport', () => { + const customTransport = vi.fn(); + init({ dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0', transport: customTransport }); + + expect(mockInitNode).toHaveBeenCalledWith( + expect.objectContaining({ + transport: customTransport, + }), + ); + }); + + it('sets default integrations from bun and filters out BunServer', () => { + const mockIntegration = { name: 'MockIntegration', setupOnce: vi.fn() }; + const bunServerMock = { name: 'BunServer', setupOnce: vi.fn() }; + mockGetBunDefaultIntegrations.mockReturnValueOnce([mockIntegration, bunServerMock]); + + init({ dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' }); + + expect(mockInitNode).toHaveBeenCalledWith( + expect.objectContaining({ + defaultIntegrations: [mockIntegration], + }), + ); + }); + + it('does not override user-provided defaultIntegrations', () => { + const userIntegrations = [{ name: 'UserIntegration', setupOnce: vi.fn() }]; + + init({ dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0', defaultIntegrations: userIntegrations }); + + expect(mockInitNode).toHaveBeenCalledWith( + expect.objectContaining({ + defaultIntegrations: userIntegrations, + }), + ); + expect(mockGetBunDefaultIntegrations).not.toHaveBeenCalled(); + }); + + it('detects runtime correctly', () => { + init({ dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' }); + + const calledOptions = mockInitNode.mock.calls[0]![0]; + // In vitest (Node), Bun is not defined, so runtime should be node + expect(calledOptions.runtime.name).toBe('node'); + expect(calledOptions.runtime.version).toBe(process.version); + }); +}); + +describe('getDefaultIntegrations', () => { + it('returns bun default integrations without BunServer', () => { + const mockIntegration = { name: 'MockIntegration', setupOnce: vi.fn() }; + const bunServerMock = { name: 'BunServer', setupOnce: vi.fn() }; + mockGetBunDefaultIntegrations.mockReturnValueOnce([mockIntegration, bunServerMock]); + + const integrations = getDefaultIntegrations({}); + + expect(integrations).toEqual([mockIntegration]); + expect(mockGetBunDefaultIntegrations).toHaveBeenCalledWith({}); + }); +}); diff --git a/packages/elysia/test/withElysia.test.ts b/packages/elysia/test/withElysia.test.ts new file mode 100644 index 000000000000..0bed50248af1 --- /dev/null +++ b/packages/elysia/test/withElysia.test.ts @@ -0,0 +1,184 @@ +import type { ErrorContext } from 'elysia'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; + +// Capture the handlers registered by withElysia +let onAfterHandleHandler: (context: unknown) => void; +let onErrorHandler: (context: unknown) => void; + +function createMockApp() { + const app: Record = {}; + app.use = vi.fn().mockReturnValue(app); + app.onRequest = vi.fn(() => app); + app.onAfterHandle = vi.fn((_opts: unknown, handler: (context: unknown) => void) => { + onAfterHandleHandler = handler; + return app; + }); + app.onError = vi.fn((_opts: unknown, handler: (context: unknown) => void) => { + onErrorHandler = handler; + return app; + }); + return app; +} + +let mockApp: ReturnType; + +const mockCaptureException = vi.fn(); +const mockGetIsolationScope = vi.fn(() => ({ + setSDKProcessingMetadata: vi.fn(), + setTransactionName: vi.fn(), +})); +const mockGetClient = vi.fn(() => ({ + on: vi.fn(), +})); +const mockGetTraceData = vi.fn(() => ({ + 'sentry-trace': 'abc123-def456-1', + baggage: 'sentry-environment=test,sentry-trace_id=abc123', +})); + +vi.mock('@elysiajs/opentelemetry', () => ({ + opentelemetry: vi.fn(() => 'otel-plugin'), +})); + +vi.mock('@sentry/core', async importActual => { + // eslint-disable-next-line @typescript-eslint/consistent-type-imports + const actual = await importActual(); + return { + ...actual, + captureException: (...args: unknown[]) => mockCaptureException(...args), + getIsolationScope: () => mockGetIsolationScope(), + getClient: () => mockGetClient(), + getTraceData: () => mockGetTraceData(), + }; +}); + +// @ts-expect-error - dynamic import after mocks +const { withElysia } = await import('../src/withElysia'); + +describe('withElysia', () => { + beforeEach(() => { + mockApp = createMockApp(); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it('registers opentelemetry plugin', () => { + // @ts-expect-error - mock app + withElysia(mockApp); + expect(mockApp.use).toHaveBeenCalledWith('otel-plugin'); + }); + + it('registers onRequest, onAfterHandle, and onError hooks', () => { + // @ts-expect-error - mock app + withElysia(mockApp); + expect(mockApp.onRequest).toHaveBeenCalled(); + expect(mockApp.onAfterHandle).toHaveBeenCalledWith({ as: 'global' }, expect.any(Function)); + expect(mockApp.onError).toHaveBeenCalledWith({ as: 'global' }, expect.any(Function)); + }); + + it('returns the app instance for chaining', () => { + // @ts-expect-error - mock app + const result = withElysia(mockApp); + expect(result).toBe(mockApp); + }); + + describe('response trace headers', () => { + it('injects sentry-trace and baggage into response headers', () => { + // @ts-expect-error - mock app + withElysia(mockApp); + const headers: Record = {}; + onAfterHandleHandler({ set: { headers } }); + + expect(headers['sentry-trace']).toBe('abc123-def456-1'); + expect(headers['baggage']).toBe('sentry-environment=test,sentry-trace_id=abc123'); + }); + + it('does not set headers when trace data is empty', () => { + mockGetTraceData.mockReturnValueOnce({}); + // @ts-expect-error - mock app + withElysia(mockApp); + const headers: Record = {}; + onAfterHandleHandler({ set: { headers } }); + + expect(headers['sentry-trace']).toBeUndefined(); + expect(headers['baggage']).toBeUndefined(); + }); + }); + + describe('defaultShouldHandleError', () => { + function triggerError(status: number | string | undefined): void { + // @ts-expect-error - mock app + withElysia(mockApp); + onErrorHandler({ + route: '/test', + request: { method: 'GET' }, + error: new Error('test'), + set: { status }, + } as unknown as ErrorContext); + } + + it('captures errors with status >= 500', () => { + triggerError(500); + expect(mockCaptureException).toHaveBeenCalled(); + }); + + it('captures errors with status 503', () => { + triggerError(503); + expect(mockCaptureException).toHaveBeenCalled(); + }); + + it('captures errors with undefined status', () => { + triggerError(undefined); + expect(mockCaptureException).toHaveBeenCalled(); + }); + + it('captures errors with status <= 299 (unusual in error handler)', () => { + triggerError(200); + expect(mockCaptureException).toHaveBeenCalled(); + }); + + it('does not capture 4xx errors', () => { + triggerError(400); + expect(mockCaptureException).not.toHaveBeenCalled(); + }); + + it('does not capture 404 errors', () => { + triggerError(404); + expect(mockCaptureException).not.toHaveBeenCalled(); + }); + + it('does not capture 3xx responses', () => { + triggerError(302); + expect(mockCaptureException).not.toHaveBeenCalled(); + }); + + it('handles string status codes', () => { + triggerError('500'); + expect(mockCaptureException).toHaveBeenCalled(); + }); + + it('does not capture string 4xx status codes', () => { + triggerError('400'); + expect(mockCaptureException).not.toHaveBeenCalled(); + }); + }); + + describe('custom shouldHandleError', () => { + it('uses custom shouldHandleError when provided', () => { + const customShouldHandle = vi.fn(() => false); + // @ts-expect-error - mock app + withElysia(mockApp, { shouldHandleError: customShouldHandle }); + + onErrorHandler({ + route: '/test', + request: { method: 'GET' }, + error: new Error('test'), + set: { status: 500 }, + } as unknown as ErrorContext); + + expect(customShouldHandle).toHaveBeenCalled(); + expect(mockCaptureException).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/elysia/tsconfig.json b/packages/elysia/tsconfig.json new file mode 100644 index 000000000000..dcbef254b942 --- /dev/null +++ b/packages/elysia/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + + "include": ["src/**/*"], + + "compilerOptions": { + // package-specific options + "types": ["bun-types"] + } +} diff --git a/packages/elysia/tsconfig.test.json b/packages/elysia/tsconfig.test.json new file mode 100644 index 000000000000..4cbbffaccbbc --- /dev/null +++ b/packages/elysia/tsconfig.test.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + + "include": ["test/**/*"], + + "compilerOptions": { + // should include all types from `./tsconfig.json` plus types for all test frameworks used + "types": ["bun-types"] + + // other package-specific, test-specific options + } +} diff --git a/packages/elysia/tsconfig.types.json b/packages/elysia/tsconfig.types.json new file mode 100644 index 000000000000..65455f66bd75 --- /dev/null +++ b/packages/elysia/tsconfig.types.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "build/types" + } +} diff --git a/yarn.lock b/yarn.lock index 1237ed9f3caa..3e5a076b6e98 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3279,6 +3279,15 @@ resolved "https://registry.yarnpkg.com/@effect/vitest/-/vitest-0.23.13.tgz#17edf9d8e3443f080ff8fe93bd37b023612a07a4" integrity sha512-F3x2phMXuVzqWexdcYp8v0z1qQHkKxp2UaHNbqZaEjPEp8FBz/iMwbi6iS/oIWzLfGF8XqdP8BGJptvGIJONNw== +"@elysiajs/opentelemetry@^1.4.0": + version "1.4.10" + resolved "https://registry.yarnpkg.com/@elysiajs/opentelemetry/-/opentelemetry-1.4.10.tgz#1c107d9071fbc284737f7b47cdf15554ef075521" + integrity sha512-2GH187Rr3n3Rq+R7fogn/jcmdwWk9OMtbYhnaJg5ydiLOJvtrztDp0p+zbyGFG2gspx8U9vpaCvSJ69Aq1zZkA== + dependencies: + "@opentelemetry/api" "^1.9.0" + "@opentelemetry/instrumentation" "^0.200.0" + "@opentelemetry/sdk-node" "^0.200.0" + "@ember-data/rfc395-data@^0.0.4": version "0.0.4" resolved "https://registry.yarnpkg.com/@ember-data/rfc395-data/-/rfc395-data-0.0.4.tgz#ecb86efdf5d7733a76ff14ea651a1b0ed1f8a843" @@ -4424,6 +4433,16 @@ resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.0.0.tgz#f22824caff3ae506b18207bad4126dbc6ccdb6b8" integrity sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ== +"@fastify/otel@0.16.0": + version "0.16.0" + resolved "https://registry.yarnpkg.com/@fastify/otel/-/otel-0.16.0.tgz#e003c9b81039490af9141a7f1397de6b05baa768" + integrity sha512-2304BdM5Q/kUvQC9qJO1KZq3Zn1WWsw+WWkVmFEaj1UE2hEIiuFqrPeglQOwEtw/ftngisqfQ3v70TWMmwhhHA== + dependencies: + "@opentelemetry/core" "^2.0.0" + "@opentelemetry/instrumentation" "^0.208.0" + "@opentelemetry/semantic-conventions" "^1.28.0" + minimatch "^10.0.3" + "@fastify/otel@0.17.1": version "0.17.1" resolved "https://registry.yarnpkg.com/@fastify/otel/-/otel-0.17.1.tgz#a7f13edc40dbc2e0c2a59d54e388f11e4d2235ce" @@ -4643,6 +4662,24 @@ dependencies: dom-mutator "^0.6.0" +"@grpc/grpc-js@^1.7.1": + version "1.14.3" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.14.3.tgz#4c9b817a900ae4020ddc28515ae4b52c78cfb8da" + integrity sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA== + dependencies: + "@grpc/proto-loader" "^0.8.0" + "@js-sdsl/ordered-map" "^4.4.2" + +"@grpc/proto-loader@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.8.0.tgz#b6c324dd909c458a0e4aa9bfd3d69cf78a4b9bd8" + integrity sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ== + dependencies: + lodash.camelcase "^4.3.0" + long "^5.0.0" + protobufjs "^7.5.3" + yargs "^17.7.2" + "@handlebars/parser@~2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@handlebars/parser/-/parser-2.0.0.tgz#5e8b7298f31ff8f7b260e6b7363c7e9ceed7d9c5" @@ -5212,6 +5249,11 @@ resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-5.7.0.tgz#526d437b07cbb41e28df34d487cbfccbe730185b" integrity sha512-WBu4ULVVxySLLzK1Ppq+OdfP+adRS4ntmDQT915rzDJ++i95gc2jZkM5B6LWEAwN3lGXpfie3yPABozdD3K3Vg== +"@js-sdsl/ordered-map@^4.4.2": + version "4.4.2" + resolved "https://registry.yarnpkg.com/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz#9299f82874bab9e4c7f9c48d865becbfe8d6907c" + integrity sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw== + "@kwsites/file-exists@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@kwsites/file-exists/-/file-exists-1.1.1.tgz#ad1efcac13e1987d8dbaf235ef3be5b0d96faa99" @@ -6185,17 +6227,10 @@ dependencies: "@octokit/openapi-types" "^12.11.0" -"@opentelemetry/api-logs@0.207.0": - version "0.207.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.207.0.tgz#ae991c51eedda55af037a3e6fc1ebdb12b289f49" - integrity sha512-lAb0jQRVyleQQGiuuvCOTDVspc14nx6XJjP4FspJ1sNARo3Regq4ZZbrc3rN4b1TYSuUCvgH+UXUPug4SLOqEQ== - dependencies: - "@opentelemetry/api" "^1.3.0" - -"@opentelemetry/api-logs@0.212.0": - version "0.212.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.212.0.tgz#ec66a0951b84b1f082e13fd8a027b9f9d65a3f7a" - integrity sha512-TEEVrLbNROUkYY51sBJGk7lO/OLjuepch8+hmpM6ffMJQ2z/KVCjdHuCFX6fJj8OkJP2zckPjrJzQtXU3IAsFg== +"@opentelemetry/api-logs@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.200.0.tgz#f9015fd844920c13968715b3cdccf5a4d4ff907e" + integrity sha512-IKJBQxh91qJ+3ssRly5hYEJ8NDHu9oY/B1PXVSCWf7zytmYO9RNLB0Ox9XQ/fJ8m6gY6Q6NtBWlmXfaXt5Uc4Q== dependencies: "@opentelemetry/api" "^1.3.0" @@ -6211,18 +6246,159 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== -"@opentelemetry/context-async-hooks@^2.6.0": +"@opentelemetry/context-async-hooks@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-2.0.0.tgz#c98a727238ca199cda943780acf6124af8d8cd80" + integrity sha512-IEkJGzK1A9v3/EHjXh3s2IiFc6L4jfK+lNgKVgUjeUJQRRhnVFMIO3TAvKwonm9O1HebCuoOt98v8bZW7oVQHA== + +"@opentelemetry/context-async-hooks@^2.5.1", "@opentelemetry/context-async-hooks@^2.6.0": version "2.6.0" resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-2.6.0.tgz#6c824e900630b378233c1a78ca7f0dc5a3b460b2" integrity sha512-L8UyDwqpTcbkIK5cgwDRDYDoEhQoj8wp8BwsO19w3LB1Z41yEQm2VJyNfAi9DrLP/YTqXqWpKHyZfR9/tFYo1Q== -"@opentelemetry/core@2.6.0", "@opentelemetry/core@^2.0.0", "@opentelemetry/core@^2.6.0": +"@opentelemetry/core@2.0.0", "@opentelemetry/core@2.5.0", "@opentelemetry/core@2.6.0", "@opentelemetry/core@^2.0.0", "@opentelemetry/core@^2.5.1", "@opentelemetry/core@^2.6.0": version "2.6.0" resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-2.6.0.tgz#719c829ed98bd7af808a2d2c83374df1fd1f3c66" integrity sha512-HLM1v2cbZ4TgYN6KEOj+Bbj8rAKriOdkF9Ed3tG25FoprSiQl7kYc+RRT6fUZGOvx0oMi5U67GoFdT+XUn8zEg== dependencies: "@opentelemetry/semantic-conventions" "^1.29.0" +"@opentelemetry/exporter-logs-otlp-grpc@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.200.0.tgz#693e0f7041c533061d0689ab43d64d039078ee7a" + integrity sha512-+3MDfa5YQPGM3WXxW9kqGD85Q7s9wlEMVNhXXG7tYFLnIeaseUt9YtCeFhEDFzfEktacdFpOtXmJuNW8cHbU5A== + dependencies: + "@grpc/grpc-js" "^1.7.1" + "@opentelemetry/core" "2.0.0" + "@opentelemetry/otlp-exporter-base" "0.200.0" + "@opentelemetry/otlp-grpc-exporter-base" "0.200.0" + "@opentelemetry/otlp-transformer" "0.200.0" + "@opentelemetry/sdk-logs" "0.200.0" + +"@opentelemetry/exporter-logs-otlp-http@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.200.0.tgz#3a99c9554f871b5c6cddb8716316c125d4edca6c" + integrity sha512-KfWw49htbGGp9s8N4KI8EQ9XuqKJ0VG+yVYVYFiCYSjEV32qpQ5qZ9UZBzOZ6xRb+E16SXOSCT3RkqBVSABZ+g== + dependencies: + "@opentelemetry/api-logs" "0.200.0" + "@opentelemetry/core" "2.0.0" + "@opentelemetry/otlp-exporter-base" "0.200.0" + "@opentelemetry/otlp-transformer" "0.200.0" + "@opentelemetry/sdk-logs" "0.200.0" + +"@opentelemetry/exporter-logs-otlp-proto@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.200.0.tgz#53573ea43bce4129bcb18bda172a95c6535bb1a2" + integrity sha512-GmahpUU/55hxfH4TP77ChOfftADsCq/nuri73I/AVLe2s4NIglvTsaACkFVZAVmnXXyPS00Fk3x27WS3yO07zA== + dependencies: + "@opentelemetry/api-logs" "0.200.0" + "@opentelemetry/core" "2.0.0" + "@opentelemetry/otlp-exporter-base" "0.200.0" + "@opentelemetry/otlp-transformer" "0.200.0" + "@opentelemetry/resources" "2.0.0" + "@opentelemetry/sdk-logs" "0.200.0" + "@opentelemetry/sdk-trace-base" "2.0.0" + +"@opentelemetry/exporter-metrics-otlp-grpc@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.200.0.tgz#f9a4d209083a6a12489c4ae4c20e6923a1780c88" + integrity sha512-uHawPRvKIrhqH09GloTuYeq2BjyieYHIpiklOvxm9zhrCL2eRsnI/6g9v2BZTVtGp8tEgIa7rCQ6Ltxw6NBgew== + dependencies: + "@grpc/grpc-js" "^1.7.1" + "@opentelemetry/core" "2.0.0" + "@opentelemetry/exporter-metrics-otlp-http" "0.200.0" + "@opentelemetry/otlp-exporter-base" "0.200.0" + "@opentelemetry/otlp-grpc-exporter-base" "0.200.0" + "@opentelemetry/otlp-transformer" "0.200.0" + "@opentelemetry/resources" "2.0.0" + "@opentelemetry/sdk-metrics" "2.0.0" + +"@opentelemetry/exporter-metrics-otlp-http@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.200.0.tgz#daa28a2b868bacf02efb153fa8780d078807919e" + integrity sha512-5BiR6i8yHc9+qW7F6LqkuUnIzVNA7lt0qRxIKcKT+gq3eGUPHZ3DY29sfxI3tkvnwMgtnHDMNze5DdxW39HsAw== + dependencies: + "@opentelemetry/core" "2.0.0" + "@opentelemetry/otlp-exporter-base" "0.200.0" + "@opentelemetry/otlp-transformer" "0.200.0" + "@opentelemetry/resources" "2.0.0" + "@opentelemetry/sdk-metrics" "2.0.0" + +"@opentelemetry/exporter-metrics-otlp-proto@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.200.0.tgz#5a494e2df8703be2f1f5f01629dfd48a6d39e5a6" + integrity sha512-E+uPj0yyvz81U9pvLZp3oHtFrEzNSqKGVkIViTQY1rH3TOobeJPSpLnTVXACnCwkPR5XeTvPnK3pZ2Kni8AFMg== + dependencies: + "@opentelemetry/core" "2.0.0" + "@opentelemetry/exporter-metrics-otlp-http" "0.200.0" + "@opentelemetry/otlp-exporter-base" "0.200.0" + "@opentelemetry/otlp-transformer" "0.200.0" + "@opentelemetry/resources" "2.0.0" + "@opentelemetry/sdk-metrics" "2.0.0" + +"@opentelemetry/exporter-prometheus@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.200.0.tgz#8f3dd3a8903447563a5be30ddf9e7bfb1e7ad127" + integrity sha512-ZYdlU9r0USuuYppiDyU2VFRA0kFl855ylnb3N/2aOlXrbA4PMCznen7gmPbetGQu7pz8Jbaf4fwvrDnVdQQXSw== + dependencies: + "@opentelemetry/core" "2.0.0" + "@opentelemetry/resources" "2.0.0" + "@opentelemetry/sdk-metrics" "2.0.0" + +"@opentelemetry/exporter-trace-otlp-grpc@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.200.0.tgz#e259367f324c01342bf3f0175c52d9f4e61a345f" + integrity sha512-hmeZrUkFl1YMsgukSuHCFPYeF9df0hHoKeHUthRKFCxiURs+GwF1VuabuHmBMZnjTbsuvNjOB+JSs37Csem/5Q== + dependencies: + "@grpc/grpc-js" "^1.7.1" + "@opentelemetry/core" "2.0.0" + "@opentelemetry/otlp-exporter-base" "0.200.0" + "@opentelemetry/otlp-grpc-exporter-base" "0.200.0" + "@opentelemetry/otlp-transformer" "0.200.0" + "@opentelemetry/resources" "2.0.0" + "@opentelemetry/sdk-trace-base" "2.0.0" + +"@opentelemetry/exporter-trace-otlp-http@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.200.0.tgz#ddf2bbdff5157a89f64aad6dad44c394872d589d" + integrity sha512-Goi//m/7ZHeUedxTGVmEzH19NgqJY+Bzr6zXo1Rni1+hwqaksEyJ44gdlEMREu6dzX1DlAaH/qSykSVzdrdafA== + dependencies: + "@opentelemetry/core" "2.0.0" + "@opentelemetry/otlp-exporter-base" "0.200.0" + "@opentelemetry/otlp-transformer" "0.200.0" + "@opentelemetry/resources" "2.0.0" + "@opentelemetry/sdk-trace-base" "2.0.0" + +"@opentelemetry/exporter-trace-otlp-proto@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.200.0.tgz#f3f149e6bad8c899c8f1e5c58e5d855ce07f7319" + integrity sha512-V9TDSD3PjK1OREw2iT9TUTzNYEVWJk4Nhodzhp9eiz4onDMYmPy3LaGbPv81yIR6dUb/hNp/SIhpiCHwFUq2Vg== + dependencies: + "@opentelemetry/core" "2.0.0" + "@opentelemetry/otlp-exporter-base" "0.200.0" + "@opentelemetry/otlp-transformer" "0.200.0" + "@opentelemetry/resources" "2.0.0" + "@opentelemetry/sdk-trace-base" "2.0.0" + +"@opentelemetry/exporter-zipkin@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.0.0.tgz#6aca658d64f5e8bc079b07ee0a3076c4ca328ec9" + integrity sha512-icxaKZ+jZL/NHXX8Aru4HGsrdhK0MLcuRXkX5G5IRmCgoRLw+Br6I/nMVozX2xjGGwV7hw2g+4Slj8K7s4HbVg== + dependencies: + "@opentelemetry/core" "2.0.0" + "@opentelemetry/resources" "2.0.0" + "@opentelemetry/sdk-trace-base" "2.0.0" + "@opentelemetry/semantic-conventions" "^1.29.0" + +"@opentelemetry/instrumentation-amqplib@0.58.0": + version "0.58.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.58.0.tgz#e3dc86ebfa7d72fe861a63b1c24a062faeb64a8c" + integrity sha512-fjpQtH18J6GxzUZ+cwNhWUpb71u+DzT7rFkg5pLssDGaEber91Y2WNGdpVpwGivfEluMlNMZumzjEqfg8DeKXQ== + dependencies: + "@opentelemetry/core" "^2.0.0" + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/semantic-conventions" "^1.33.0" + "@opentelemetry/instrumentation-amqplib@0.60.0": version "0.60.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.60.0.tgz#a2b2abe3cf433bea166c18a703c8ddf6accf83da" @@ -6241,6 +6417,16 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.34.0" +"@opentelemetry/instrumentation-connect@0.54.0": + version "0.54.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.54.0.tgz#87312850844b6c57976d00bd3256d55650543772" + integrity sha512-43RmbhUhqt3uuPnc16cX6NsxEASEtn8z/cYV8Zpt6EP4p2h9s4FNuJ4Q9BbEQ2C0YlCCB/2crO1ruVz/hWt8fA== + dependencies: + "@opentelemetry/core" "^2.0.0" + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@types/connect" "3.4.38" + "@opentelemetry/instrumentation-connect@0.56.0": version "0.56.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.56.0.tgz#8d846d2f7cf1f6b2723e5b0ff5595e8d31cb7446" @@ -6251,6 +6437,13 @@ "@opentelemetry/semantic-conventions" "^1.27.0" "@types/connect" "3.4.38" +"@opentelemetry/instrumentation-dataloader@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.28.0.tgz#b857bb038e4a2a3b7278f3da89a1e210bb15339e" + integrity sha512-ExXGBp0sUj8yhm6Znhf9jmuOaGDsYfDES3gswZnKr4MCqoBWQdEFn6EoDdt5u+RdbxQER+t43FoUihEfTSqsjA== + dependencies: + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/instrumentation-dataloader@0.30.0": version "0.30.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.30.0.tgz#7fbea57b27165324092639abf090ca3697eb7a80" @@ -6258,6 +6451,15 @@ dependencies: "@opentelemetry/instrumentation" "^0.213.0" +"@opentelemetry/instrumentation-express@0.59.0": + version "0.59.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.59.0.tgz#c2ac7dcb4f9904926518408cdf4efb046e724382" + integrity sha512-pMKV/qnHiW/Q6pmbKkxt0eIhuNEtvJ7sUAyee192HErlr+a1Jx+FZ3WjfmzhQL1geewyGEiPGkmjjAgNY8TgDA== + dependencies: + "@opentelemetry/core" "^2.0.0" + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-express@0.61.0": version "0.61.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.61.0.tgz#49b4d144ab6e9d6e035941a51f5e573e84e3647f" @@ -6267,6 +6469,14 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.27.0" +"@opentelemetry/instrumentation-fs@0.30.0": + version "0.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.30.0.tgz#5e28edde0591dc4ffa471a86a68f91e737fe31fb" + integrity sha512-n3Cf8YhG7reaj5dncGlRIU7iT40bxPOjsBEA5Bc1a1g6e9Qvb+JFJ7SEiMlPbUw4PBmxE3h40ltE8LZ3zVt6OA== + dependencies: + "@opentelemetry/core" "^2.0.0" + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/instrumentation-fs@0.32.0": version "0.32.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.32.0.tgz#2010d86da8ab3d543f8e44c8fff81b94f904d91d" @@ -6275,6 +6485,13 @@ "@opentelemetry/core" "^2.0.0" "@opentelemetry/instrumentation" "^0.213.0" +"@opentelemetry/instrumentation-generic-pool@0.54.0": + version "0.54.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.54.0.tgz#9f3ad0cedbfe5011efe4ebdc76c85a73a0b967a6" + integrity sha512-8dXMBzzmEdXfH/wjuRvcJnUFeWzZHUnExkmFJ2uPfa31wmpyBCMxO59yr8f/OXXgSogNgi/uPo9KW9H7LMIZ+g== + dependencies: + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/instrumentation-generic-pool@0.56.0": version "0.56.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.56.0.tgz#01560f52d5bac6fb6312a1f0bc74bf0939119894" @@ -6282,6 +6499,13 @@ dependencies: "@opentelemetry/instrumentation" "^0.213.0" +"@opentelemetry/instrumentation-graphql@0.58.0": + version "0.58.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.58.0.tgz#3ca294ba410e04c920dc82ab4caa23ec1c2e1a2e" + integrity sha512-+yWVVY7fxOs3j2RixCbvue8vUuJ1inHxN2q1sduqDB0Wnkr4vOzVKRYl/Zy7B31/dcPS72D9lo/kltdOTBM3bQ== + dependencies: + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/instrumentation-graphql@0.61.0": version "0.61.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.61.0.tgz#d1f896095a891c9576967645e7fcba935da82a94" @@ -6289,6 +6513,15 @@ dependencies: "@opentelemetry/instrumentation" "^0.213.0" +"@opentelemetry/instrumentation-hapi@0.57.0": + version "0.57.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.57.0.tgz#27b3a44a51444af3100a321f2e40623e89e5bb75" + integrity sha512-Os4THbvls8cTQTVA8ApLfZZztuuqGEeqog0XUnyRW7QVF0d/vOVBEcBCk1pazPFmllXGEdNbbat8e2fYIWdFbw== + dependencies: + "@opentelemetry/core" "^2.0.0" + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-hapi@0.59.0": version "0.59.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.59.0.tgz#412ea19e97ead684c5737e1f1aaa19ff940512d3" @@ -6298,6 +6531,16 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.27.0" +"@opentelemetry/instrumentation-http@0.211.0": + version "0.211.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.211.0.tgz#2f12f83f0c21d37917fd9710fb5b755f28858cf6" + integrity sha512-n0IaQ6oVll9PP84SjbOCwDjaJasWRHi6BLsbMLiT6tNj7QbVOkuA5sk/EfZczwI0j5uTKl1awQPivO/ldVtsqA== + dependencies: + "@opentelemetry/core" "2.5.0" + "@opentelemetry/instrumentation" "0.211.0" + "@opentelemetry/semantic-conventions" "^1.29.0" + forwarded-parse "2.1.2" + "@opentelemetry/instrumentation-http@0.213.0": version "0.213.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.213.0.tgz#b379d6bcbae43a7d6d54070f3794527021f176c9" @@ -6308,6 +6551,15 @@ "@opentelemetry/semantic-conventions" "^1.29.0" forwarded-parse "2.1.2" +"@opentelemetry/instrumentation-ioredis@0.59.0": + version "0.59.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.59.0.tgz#530d06aa67b73ea732414557adebe1dde7de430f" + integrity sha512-875UxzBHWkW+P4Y45SoFM2AR8f8TzBMD8eO7QXGCyFSCUMP5s9vtt/BS8b/r2kqLyaRPK6mLbdnZznK3XzQWvw== + dependencies: + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/redis-common" "^0.38.2" + "@opentelemetry/semantic-conventions" "^1.33.0" + "@opentelemetry/instrumentation-ioredis@0.61.0": version "0.61.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.61.0.tgz#e862540cbf188d0ca368d3a75020d165cb8beefb" @@ -6317,6 +6569,14 @@ "@opentelemetry/redis-common" "^0.38.2" "@opentelemetry/semantic-conventions" "^1.33.0" +"@opentelemetry/instrumentation-kafkajs@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.20.0.tgz#521db06d10d39f42e842ce336e5c1e48b3da2956" + integrity sha512-yJXOuWZROzj7WmYCUiyT27tIfqBrVtl1/TwVbQyWPz7rL0r1Lu7kWjD0PiVeTCIL6CrIZ7M2s8eBxsTAOxbNvw== + dependencies: + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/semantic-conventions" "^1.30.0" + "@opentelemetry/instrumentation-kafkajs@0.22.0": version "0.22.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.22.0.tgz#a3cf7aca003f96211e514a348b7568799efdfba1" @@ -6325,6 +6585,14 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.30.0" +"@opentelemetry/instrumentation-knex@0.55.0": + version "0.55.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.55.0.tgz#fefc17d854a107d99ab0dbc8933d5897efce1abd" + integrity sha512-FtTL5DUx5Ka/8VK6P1VwnlUXPa3nrb7REvm5ddLUIeXXq4tb9pKd+/ThB1xM/IjefkRSN3z8a5t7epYw1JLBJQ== + dependencies: + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/semantic-conventions" "^1.33.1" + "@opentelemetry/instrumentation-knex@0.57.0": version "0.57.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.57.0.tgz#d46622a3f82f3df2ba29c64498d6ef828a40457e" @@ -6333,6 +6601,15 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.33.1" +"@opentelemetry/instrumentation-koa@0.59.0": + version "0.59.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.59.0.tgz#7df8850fa193a8f590e3fbcab00016e25db27041" + integrity sha512-K9o2skADV20Skdu5tG2bogPKiSpXh4KxfLjz6FuqIVvDJNibwSdu5UvyyBzRVp1rQMV6UmoIk6d3PyPtJbaGSg== + dependencies: + "@opentelemetry/core" "^2.0.0" + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/semantic-conventions" "^1.36.0" + "@opentelemetry/instrumentation-koa@0.61.0": version "0.61.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.61.0.tgz#c12f57b023834afb1c142c11746d560bcc288b5b" @@ -6342,6 +6619,13 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.36.0" +"@opentelemetry/instrumentation-lru-memoizer@0.55.0": + version "0.55.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.55.0.tgz#776d5f10178adfbda7286b4f31adde8bb518d55a" + integrity sha512-FDBfT7yDGcspN0Cxbu/k8A0Pp1Jhv/m7BMTzXGpcb8ENl3tDj/51U65R5lWzUH15GaZA15HQ5A5wtafklxYj7g== + dependencies: + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/instrumentation-lru-memoizer@0.57.0": version "0.57.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.57.0.tgz#4da92ecd1bc5d5e9c7de28ea14ed57c9f29cfefd" @@ -6349,6 +6633,14 @@ dependencies: "@opentelemetry/instrumentation" "^0.213.0" +"@opentelemetry/instrumentation-mongodb@0.64.0": + version "0.64.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.64.0.tgz#0027c13fdd7506eb1f618998245edd244cc23cc7" + integrity sha512-pFlCJjweTqVp7B220mCvCld1c1eYKZfQt1p3bxSbcReypKLJTwat+wbL2YZoX9jPi5X2O8tTKFEOahO5ehQGsA== + dependencies: + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/semantic-conventions" "^1.33.0" + "@opentelemetry/instrumentation-mongodb@0.66.0": version "0.66.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.66.0.tgz#990bf4571382d3b02a9584927411c92c375d2fd4" @@ -6357,6 +6649,15 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.33.0" +"@opentelemetry/instrumentation-mongoose@0.57.0": + version "0.57.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.57.0.tgz#2ce3f3bbf66a255958c3a112a92079898d69f624" + integrity sha512-MthiekrU/BAJc5JZoZeJmo0OTX6ycJMiP6sMOSRTkvz5BrPMYDqaJos0OgsLPL/HpcgHP7eo5pduETuLguOqcg== + dependencies: + "@opentelemetry/core" "^2.0.0" + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/semantic-conventions" "^1.33.0" + "@opentelemetry/instrumentation-mongoose@0.59.0": version "0.59.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.59.0.tgz#8446ece86df59f09c630e7df6d794c8cd08f58d8" @@ -6366,6 +6667,15 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.33.0" +"@opentelemetry/instrumentation-mysql2@0.57.0": + version "0.57.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.57.0.tgz#928eda47c6f4ab193d3363fcab01d81a70adc46b" + integrity sha512-nHSrYAwF7+aV1E1V9yOOP9TchOodb6fjn4gFvdrdQXiRE7cMuffyLLbCZlZd4wsspBzVwOXX8mpURdRserAhNA== + dependencies: + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/semantic-conventions" "^1.33.0" + "@opentelemetry/sql-common" "^0.41.2" + "@opentelemetry/instrumentation-mysql2@0.59.0": version "0.59.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.59.0.tgz#938cd4a294b7e4a6e8c3855b8cfe267c8d2e5493" @@ -6375,6 +6685,15 @@ "@opentelemetry/semantic-conventions" "^1.33.0" "@opentelemetry/sql-common" "^0.41.2" +"@opentelemetry/instrumentation-mysql@0.57.0": + version "0.57.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.57.0.tgz#74d42a1c6d20aee93996f8b6f6b7b69469748754" + integrity sha512-HFS/+FcZ6Q7piM7Il7CzQ4VHhJvGMJWjx7EgCkP5AnTntSN5rb5Xi3TkYJHBKeR27A0QqPlGaCITi93fUDs++Q== + dependencies: + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/semantic-conventions" "^1.33.0" + "@types/mysql" "2.15.27" + "@opentelemetry/instrumentation-mysql@0.59.0": version "0.59.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.59.0.tgz#bf43cafbac5928236ea53704a52c718349c22e38" @@ -6392,6 +6711,18 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.30.0" +"@opentelemetry/instrumentation-pg@0.63.0": + version "0.63.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.63.0.tgz#852ca5519d756c613bb9f3153a5e70c2b805e5cf" + integrity sha512-dKm/ODNN3GgIQVlbD6ZPxwRc3kleLf95hrRWXM+l8wYo+vSeXtEpQPT53afEf6VFWDVzJK55VGn8KMLtSve/cg== + dependencies: + "@opentelemetry/core" "^2.0.0" + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/semantic-conventions" "^1.34.0" + "@opentelemetry/sql-common" "^0.41.2" + "@types/pg" "8.15.6" + "@types/pg-pool" "2.0.7" + "@opentelemetry/instrumentation-pg@0.65.0": version "0.65.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.65.0.tgz#f1f76f8c57c5c6fec68c77ce6ee104fee5de13e1" @@ -6404,6 +6735,15 @@ "@types/pg" "8.15.6" "@types/pg-pool" "2.0.7" +"@opentelemetry/instrumentation-redis@0.59.0": + version "0.59.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.59.0.tgz#44c1bd7852cdadbe77c1bdfa94185528012558cf" + integrity sha512-JKv1KDDYA2chJ1PC3pLP+Q9ISMQk6h5ey+99mB57/ARk0vQPGZTTEb4h4/JlcEpy7AYT8HIGv7X6l+br03Neeg== + dependencies: + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/redis-common" "^0.38.2" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-redis@0.61.0": version "0.61.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.61.0.tgz#b43b9c3b5d0b124f2e60b055e4529a3a4b55dbc4" @@ -6413,6 +6753,15 @@ "@opentelemetry/redis-common" "^0.38.2" "@opentelemetry/semantic-conventions" "^1.27.0" +"@opentelemetry/instrumentation-tedious@0.30.0": + version "0.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.30.0.tgz#4a8906b5322c4add4132e6e086c23e17bc23626b" + integrity sha512-bZy9Q8jFdycKQ2pAsyuHYUHNmCxCOGdG6eg1Mn75RvQDccq832sU5OWOBnc12EFUELI6icJkhR7+EQKMBam2GA== + dependencies: + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/semantic-conventions" "^1.33.0" + "@types/tedious" "^4.0.14" + "@opentelemetry/instrumentation-tedious@0.32.0": version "0.32.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.32.0.tgz#8204a14adb71adcbf7d72705244d606bb69e428a" @@ -6422,6 +6771,15 @@ "@opentelemetry/semantic-conventions" "^1.33.0" "@types/tedious" "^4.0.14" +"@opentelemetry/instrumentation-undici@0.21.0": + version "0.21.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.21.0.tgz#dcb43a364c39e78217946aeb7aa09156e55f4c6c" + integrity sha512-gok0LPUOTz2FQ1YJMZzaHcOzDFyT64XJ8M9rNkugk923/p6lDGms/cRW1cqgqp6N6qcd6K6YdVHwPEhnx9BWbw== + dependencies: + "@opentelemetry/core" "^2.0.0" + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/semantic-conventions" "^1.24.0" + "@opentelemetry/instrumentation-undici@0.23.0": version "0.23.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.23.0.tgz#e328bf6e53847ba7baa2a345d02221cc62917cec" @@ -6431,7 +6789,7 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.24.0" -"@opentelemetry/instrumentation@0.213.0", "@opentelemetry/instrumentation@^0.213.0": +"@opentelemetry/instrumentation@0.200.0", "@opentelemetry/instrumentation@0.211.0", "@opentelemetry/instrumentation@0.213.0", "@opentelemetry/instrumentation@^0.200.0", "@opentelemetry/instrumentation@^0.207.0", "@opentelemetry/instrumentation@^0.208.0", "@opentelemetry/instrumentation@^0.211.0", "@opentelemetry/instrumentation@^0.212.0", "@opentelemetry/instrumentation@^0.213.0": version "0.213.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.213.0.tgz#55362569efd0cba00aab9921a78dd20dfddf70b6" integrity sha512-3i9NdkET/KvQomeh7UaR/F4r9P25Rx6ooALlWXPIjypcEOUxksCmVu0zA70NBJWlrMW1rPr/LRidFAflLI+s/w== @@ -6440,30 +6798,57 @@ import-in-the-middle "^3.0.0" require-in-the-middle "^8.0.0" -"@opentelemetry/instrumentation@^0.207.0": - version "0.207.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.207.0.tgz#1a5a921c04f171ff28096fa320af713f3c87ec14" - integrity sha512-y6eeli9+TLKnznrR8AZlQMSJT7wILpXH+6EYq5Vf/4Ao+huI7EedxQHwRgVUOMLFbe7VFDvHJrX9/f4lcwnJsA== +"@opentelemetry/otlp-exporter-base@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.200.0.tgz#906bcf2e59815c8ded732d328f6bc060fb7b0459" + integrity sha512-IxJgA3FD7q4V6gGq4bnmQM5nTIyMDkoGFGrBrrDjB6onEiq1pafma55V+bHvGYLWvcqbBbRfezr1GED88lacEQ== + dependencies: + "@opentelemetry/core" "2.0.0" + "@opentelemetry/otlp-transformer" "0.200.0" + +"@opentelemetry/otlp-grpc-exporter-base@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.200.0.tgz#cfc6cfd4def7d47f84e43d438d75cb463c67bf0d" + integrity sha512-CK2S+bFgOZ66Bsu5hlDeOX6cvW5FVtVjFFbWuaJP0ELxJKBB6HlbLZQ2phqz/uLj1cWap5xJr/PsR3iGoB7Vqw== + dependencies: + "@grpc/grpc-js" "^1.7.1" + "@opentelemetry/core" "2.0.0" + "@opentelemetry/otlp-exporter-base" "0.200.0" + "@opentelemetry/otlp-transformer" "0.200.0" + +"@opentelemetry/otlp-transformer@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-transformer/-/otlp-transformer-0.200.0.tgz#19afb2274554cb74e2d2b7e32a54a7f7d83c8642" + integrity sha512-+9YDZbYybOnv7sWzebWOeK6gKyt2XE7iarSyBFkwwnP559pEevKOUD8NyDHhRjCSp13ybh9iVXlMfcj/DwF/yw== + dependencies: + "@opentelemetry/api-logs" "0.200.0" + "@opentelemetry/core" "2.0.0" + "@opentelemetry/resources" "2.0.0" + "@opentelemetry/sdk-logs" "0.200.0" + "@opentelemetry/sdk-metrics" "2.0.0" + "@opentelemetry/sdk-trace-base" "2.0.0" + protobufjs "^7.3.0" + +"@opentelemetry/propagator-b3@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-b3/-/propagator-b3-2.0.0.tgz#1b6244ef2d08a70672521a9aff56e485bd607c17" + integrity sha512-blx9S2EI49Ycuw6VZq+bkpaIoiJFhsDuvFGhBIoH3vJ5oYjJ2U0s3fAM5jYft99xVIAv6HqoPtlP9gpVA2IZtA== dependencies: - "@opentelemetry/api-logs" "0.207.0" - import-in-the-middle "^2.0.0" - require-in-the-middle "^8.0.0" + "@opentelemetry/core" "2.0.0" -"@opentelemetry/instrumentation@^0.212.0": - version "0.212.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.212.0.tgz#238b6e3e2131217ff4acfe7e8e7b6ce1f0ac0ba0" - integrity sha512-IyXmpNnifNouMOe0I/gX7ENfv2ZCNdYTF0FpCsoBcpbIHzk81Ww9rQTYTnvghszCg7qGrIhNvWC8dhEifgX9Jg== +"@opentelemetry/propagator-jaeger@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.0.0.tgz#288d6767dea554db684fd5e144ad8653d83fd2ea" + integrity sha512-Mbm/LSFyAtQKP0AQah4AfGgsD+vsZcyreZoQ5okFBk33hU7AquU4TltgyL9dvaO8/Zkoud8/0gEvwfOZ5d7EPA== dependencies: - "@opentelemetry/api-logs" "0.212.0" - import-in-the-middle "^2.0.6" - require-in-the-middle "^8.0.0" + "@opentelemetry/core" "2.0.0" "@opentelemetry/redis-common@^0.38.2": version "0.38.2" resolved "https://registry.yarnpkg.com/@opentelemetry/redis-common/-/redis-common-0.38.2.tgz#cefa4f3e79db1cd54f19e233b7dfb56621143955" integrity sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA== -"@opentelemetry/resources@2.6.0", "@opentelemetry/resources@^2.6.0": +"@opentelemetry/resources@2.0.0", "@opentelemetry/resources@2.6.0", "@opentelemetry/resources@^2.5.1", "@opentelemetry/resources@^2.6.0": version "2.6.0" resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-2.6.0.tgz#1a945dbb8986043d8b593c358d5d8e3de6becf5a" integrity sha512-D4y/+OGe3JSuYUCBxtH5T9DSAWNcvCb/nQWIga8HNtXTVPQn59j0nTBAgaAXxUVBDl40mG3Tc76b46wPlZaiJQ== @@ -6471,7 +6856,52 @@ "@opentelemetry/core" "2.6.0" "@opentelemetry/semantic-conventions" "^1.29.0" -"@opentelemetry/sdk-trace-base@^2.6.0": +"@opentelemetry/sdk-logs@0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-logs/-/sdk-logs-0.200.0.tgz#893d86cefa6f2c02a7cd03d5cb4a959eed3653d1" + integrity sha512-VZG870063NLfObmQQNtCVcdXXLzI3vOjjrRENmU37HYiPFa0ZXpXVDsTD02Nh3AT3xYJzQaWKl2X2lQ2l7TWJA== + dependencies: + "@opentelemetry/api-logs" "0.200.0" + "@opentelemetry/core" "2.0.0" + "@opentelemetry/resources" "2.0.0" + +"@opentelemetry/sdk-metrics@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.0.tgz#aba86060bc363c661ca286339c5b04590e298b69" + integrity sha512-Bvy8QDjO05umd0+j+gDeWcTaVa1/R2lDj/eOvjzpm8VQj1K1vVZJuyjThpV5/lSHyYW2JaHF2IQ7Z8twJFAhjA== + dependencies: + "@opentelemetry/core" "2.0.0" + "@opentelemetry/resources" "2.0.0" + +"@opentelemetry/sdk-node@^0.200.0": + version "0.200.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-node/-/sdk-node-0.200.0.tgz#033d0641da628f1537cf7442f41cd77c048923ae" + integrity sha512-S/YSy9GIswnhYoDor1RusNkmRughipvTCOQrlF1dzI70yQaf68qgf5WMnzUxdlCl3/et/pvaO75xfPfuEmCK5A== + dependencies: + "@opentelemetry/api-logs" "0.200.0" + "@opentelemetry/core" "2.0.0" + "@opentelemetry/exporter-logs-otlp-grpc" "0.200.0" + "@opentelemetry/exporter-logs-otlp-http" "0.200.0" + "@opentelemetry/exporter-logs-otlp-proto" "0.200.0" + "@opentelemetry/exporter-metrics-otlp-grpc" "0.200.0" + "@opentelemetry/exporter-metrics-otlp-http" "0.200.0" + "@opentelemetry/exporter-metrics-otlp-proto" "0.200.0" + "@opentelemetry/exporter-prometheus" "0.200.0" + "@opentelemetry/exporter-trace-otlp-grpc" "0.200.0" + "@opentelemetry/exporter-trace-otlp-http" "0.200.0" + "@opentelemetry/exporter-trace-otlp-proto" "0.200.0" + "@opentelemetry/exporter-zipkin" "2.0.0" + "@opentelemetry/instrumentation" "0.200.0" + "@opentelemetry/propagator-b3" "2.0.0" + "@opentelemetry/propagator-jaeger" "2.0.0" + "@opentelemetry/resources" "2.0.0" + "@opentelemetry/sdk-logs" "0.200.0" + "@opentelemetry/sdk-metrics" "2.0.0" + "@opentelemetry/sdk-trace-base" "2.0.0" + "@opentelemetry/sdk-trace-node" "2.0.0" + "@opentelemetry/semantic-conventions" "^1.29.0" + +"@opentelemetry/sdk-trace-base@2.0.0", "@opentelemetry/sdk-trace-base@2.6.0", "@opentelemetry/sdk-trace-base@^2.5.1", "@opentelemetry/sdk-trace-base@^2.6.0": version "2.6.0" resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.6.0.tgz#d7e752a0906f2bcae3c1261e224aef3e3b3746f9" integrity sha512-g/OZVkqlxllgFM7qMKqbPV9c1DUPhQ7d4n3pgZFcrnrNft9eJXZM2TNHTPYREJBrtNdRytYyvwjgL5geDKl3EQ== @@ -6480,7 +6910,16 @@ "@opentelemetry/resources" "2.6.0" "@opentelemetry/semantic-conventions" "^1.29.0" -"@opentelemetry/semantic-conventions@^1.24.0", "@opentelemetry/semantic-conventions@^1.27.0", "@opentelemetry/semantic-conventions@^1.28.0", "@opentelemetry/semantic-conventions@^1.29.0", "@opentelemetry/semantic-conventions@^1.30.0", "@opentelemetry/semantic-conventions@^1.33.0", "@opentelemetry/semantic-conventions@^1.33.1", "@opentelemetry/semantic-conventions@^1.34.0", "@opentelemetry/semantic-conventions@^1.36.0", "@opentelemetry/semantic-conventions@^1.40.0": +"@opentelemetry/sdk-trace-node@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.0.0.tgz#ef9f8ab77ccb41a9c9ff272f6bf4bb6999491f5b" + integrity sha512-omdilCZozUjQwY3uZRBwbaRMJ3p09l4t187Lsdf0dGMye9WKD4NGcpgZRvqhI1dwcH6og+YXQEtoO9Wx3ykilg== + dependencies: + "@opentelemetry/context-async-hooks" "2.0.0" + "@opentelemetry/core" "2.0.0" + "@opentelemetry/sdk-trace-base" "2.0.0" + +"@opentelemetry/semantic-conventions@^1.24.0", "@opentelemetry/semantic-conventions@^1.27.0", "@opentelemetry/semantic-conventions@^1.28.0", "@opentelemetry/semantic-conventions@^1.29.0", "@opentelemetry/semantic-conventions@^1.30.0", "@opentelemetry/semantic-conventions@^1.33.0", "@opentelemetry/semantic-conventions@^1.33.1", "@opentelemetry/semantic-conventions@^1.34.0", "@opentelemetry/semantic-conventions@^1.36.0", "@opentelemetry/semantic-conventions@^1.39.0", "@opentelemetry/semantic-conventions@^1.40.0": version "1.40.0" resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.40.0.tgz#10b2944ca559386590683392022a897eefd011d3" integrity sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw== @@ -7011,6 +7450,13 @@ dependencies: "@prisma/debug" "6.15.0" +"@prisma/instrumentation@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-7.2.0.tgz#9409a436d8f98e8950c8659aeeba045c4a07e891" + integrity sha512-Rh9Z4x5kEj1OdARd7U18AtVrnL6rmLSI0qYShaB4W7Wx5BKbgzndWF+QnuzMb7GLfVdlT5aYCXoPQVYuYtVu0g== + dependencies: + "@opentelemetry/instrumentation" "^0.207.0" + "@prisma/instrumentation@7.4.2": version "7.4.2" resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-7.4.2.tgz#b05e814d0647343febd26a8ccb039d27ccc69eca" @@ -7682,6 +8128,14 @@ resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-5.1.1.tgz#9eeef63099011155691a5ee59b0f796c141e8f85" integrity sha512-x2wEpBHwsTyTF2rWsLKJlzrRF1TTIGOfX+ngdE+Yd5DBkoS58HwQv824QOviPGQRla4/ypISqAXzjdDPL/zalg== +"@sentry/bun@10.43.0": + version "10.43.0" + resolved "https://registry.yarnpkg.com/@sentry/bun/-/bun-10.43.0.tgz#bb502e0ddf558e64063763bca304281730fe4d92" + integrity sha512-BMWmJNU4Bl2AClcXUpOhR+ZFxl8bCg3k797ESqUC+vzDe13i81iwhh8NAN8kHEoRY771fh/bIqe8n6KKFKIr0A== + dependencies: + "@sentry/core" "10.43.0" + "@sentry/node" "10.43.0" + "@sentry/bundler-plugin-core@5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@sentry/bundler-plugin-core/-/bundler-plugin-core-5.1.0.tgz#01bef91543eb42cd370288573291b9a02b240e84" @@ -7768,6 +8222,68 @@ "@sentry/cli-win32-i686" "2.58.5" "@sentry/cli-win32-x64" "2.58.5" +"@sentry/core@10.43.0": + version "10.43.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-10.43.0.tgz#48b7b2295f36097775b529c59712688c9087c7bc" + integrity sha512-l0SszQAPiQGWl/ferw8GP3ALyHXiGiRKJaOvNmhGO+PrTQyZTZ6OYyPnGijAFRg58dE1V3RCH/zw5d2xSUIiNg== + +"@sentry/node-core@10.43.0": + version "10.43.0" + resolved "https://registry.yarnpkg.com/@sentry/node-core/-/node-core-10.43.0.tgz#f8575be3ad09e86e8e18e54074f3bcafea344234" + integrity sha512-w2H3NSkNMoYOS7o7mR55BM7+xL++dPxMSv1/XDfsra9FYHGppO+Mxk667Ee5k+uDi+wNIioICIh+5XOvZh4+HQ== + dependencies: + "@sentry/core" "10.43.0" + "@sentry/opentelemetry" "10.43.0" + import-in-the-middle "^2.0.6" + +"@sentry/node@10.43.0": + version "10.43.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-10.43.0.tgz#466acf853565d92d972b7e012fab6558a32a739e" + integrity sha512-oNwXcuZUc4uTTr0WbHZBBIKsKwAKvNMTgbXwxfB37CfzV18wbTirbQABZ/Ir3WNxSgi6ZcnC6UE013jF5XWPqw== + dependencies: + "@fastify/otel" "0.16.0" + "@opentelemetry/api" "^1.9.0" + "@opentelemetry/context-async-hooks" "^2.5.1" + "@opentelemetry/core" "^2.5.1" + "@opentelemetry/instrumentation" "^0.211.0" + "@opentelemetry/instrumentation-amqplib" "0.58.0" + "@opentelemetry/instrumentation-connect" "0.54.0" + "@opentelemetry/instrumentation-dataloader" "0.28.0" + "@opentelemetry/instrumentation-express" "0.59.0" + "@opentelemetry/instrumentation-fs" "0.30.0" + "@opentelemetry/instrumentation-generic-pool" "0.54.0" + "@opentelemetry/instrumentation-graphql" "0.58.0" + "@opentelemetry/instrumentation-hapi" "0.57.0" + "@opentelemetry/instrumentation-http" "0.211.0" + "@opentelemetry/instrumentation-ioredis" "0.59.0" + "@opentelemetry/instrumentation-kafkajs" "0.20.0" + "@opentelemetry/instrumentation-knex" "0.55.0" + "@opentelemetry/instrumentation-koa" "0.59.0" + "@opentelemetry/instrumentation-lru-memoizer" "0.55.0" + "@opentelemetry/instrumentation-mongodb" "0.64.0" + "@opentelemetry/instrumentation-mongoose" "0.57.0" + "@opentelemetry/instrumentation-mysql" "0.57.0" + "@opentelemetry/instrumentation-mysql2" "0.57.0" + "@opentelemetry/instrumentation-pg" "0.63.0" + "@opentelemetry/instrumentation-redis" "0.59.0" + "@opentelemetry/instrumentation-tedious" "0.30.0" + "@opentelemetry/instrumentation-undici" "0.21.0" + "@opentelemetry/resources" "^2.5.1" + "@opentelemetry/sdk-trace-base" "^2.5.1" + "@opentelemetry/semantic-conventions" "^1.39.0" + "@prisma/instrumentation" "7.2.0" + "@sentry/core" "10.43.0" + "@sentry/node-core" "10.43.0" + "@sentry/opentelemetry" "10.43.0" + import-in-the-middle "^2.0.6" + +"@sentry/opentelemetry@10.43.0": + version "10.43.0" + resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-10.43.0.tgz#c2d3d58e943541a7ae81e79cf264b61c7fa20f1b" + integrity sha512-+fIcnnLdvBHdq4nKq23t9v/B9D4L97fPWEDksXbpGs11o6BsqY4Tlzmce6cP95iiQhPckCEag3FthSND+BYtYQ== + dependencies: + "@sentry/core" "10.43.0" + "@sentry/rollup-plugin@5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@sentry/rollup-plugin/-/rollup-plugin-5.1.0.tgz#16109d796dc3ed49dfeda53c804792b9e4d0fd36" @@ -9658,12 +10174,12 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@>=10.0.0", "@types/node@>=18": - version "22.10.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.2.tgz#a485426e6d1fdafc7b0d4c7b24e2c78182ddabb9" - integrity sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ== +"@types/node@*", "@types/node@>=10.0.0", "@types/node@>=13.7.0", "@types/node@>=18": + version "25.4.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-25.4.0.tgz#f25d8467984d6667cc4c1be1e2f79593834aaedb" + integrity sha512-9wLpoeWuBlcbBpOY3XmzSTG3oscB6xjBEEtn+pYXTfhyXhIxC5FsBer2KTopBlvKEiW9l13po9fq+SJY/5lkhw== dependencies: - undici-types "~6.20.0" + undici-types "~7.18.0" "@types/node@^14.8.0": version "14.18.63" @@ -13882,7 +14398,7 @@ cookie@^0.7.1, cookie@^0.7.2, cookie@~0.7.1, cookie@~0.7.2: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== -cookie@^1.0.1, cookie@^1.0.2: +cookie@^1.0.1, cookie@^1.0.2, cookie@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-1.1.1.tgz#3bb9bdfc82369db9c2f69c93c9c3ceb310c88b3c" integrity sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ== @@ -15050,6 +15566,16 @@ electron-to-chromium@^1.5.263: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz#142be1ab5e1cd5044954db0e5898f60a4960384e" integrity sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A== +elysia@^1.4.0: + version "1.4.27" + resolved "https://registry.yarnpkg.com/elysia/-/elysia-1.4.27.tgz#709f07f54c0d0400aab8a18bac4d94223203ec45" + integrity sha512-2UlmNEjPJVA/WZVPYKy+KdsrfFwwNlqSBW1lHz6i2AHc75k7gV4Rhm01kFeotH7PDiHIX2G8X3KnRPc33SGVIg== + dependencies: + cookie "^1.1.1" + exact-mirror "^0.2.7" + fast-decode-uri-component "^1.0.1" + memoirist "^0.4.0" + ember-auto-import@^2.5.0, ember-auto-import@^2.7.2: version "2.8.1" resolved "https://registry.yarnpkg.com/ember-auto-import/-/ember-auto-import-2.8.1.tgz#03977e87ce178e6f9e4f89809185ff8f0fee9fcb" @@ -16838,6 +17364,11 @@ events@^3.0.0, events@^3.2.0, events@^3.3.0: resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== +exact-mirror@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/exact-mirror/-/exact-mirror-0.2.7.tgz#ee8e75c362a67ca0e07cb13fea92b61adaabfa29" + integrity sha512-+MeEmDcLA4o/vjK2zujgk+1VTxPR4hdp23qLqkWfStbECtAq9gmsvQa3LW6z/0GXZyHJobrCnmy1cdeE7BjsYg== + exec-sh@^0.3.2, exec-sh@^0.3.4: version "0.3.6" resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" @@ -17107,6 +17638,11 @@ fast-content-type-parse@^3.0.0: resolved "https://registry.yarnpkg.com/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz#5590b6c807cc598be125e6740a9fde589d2b7afb" integrity sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg== +fast-decode-uri-component@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" + integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -19107,7 +19643,7 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -import-in-the-middle@^2.0.0, import-in-the-middle@^2.0.6: +import-in-the-middle@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-2.0.6.tgz#1972337bfe020d05f6b5e020c13334567436324f" integrity sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw== @@ -20819,7 +21355,7 @@ lodash.assign@^3.2.0: lodash._createassigner "^3.0.0" lodash.keys "^3.0.0" -lodash.camelcase@^4.1.1: +lodash.camelcase@^4.1.1, lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= @@ -21033,7 +21569,7 @@ long@^4.0.0: resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== -long@^5.3.2: +long@^5.0.0, long@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/long/-/long-5.3.2.tgz#1d84463095999262d7d7b7f8bfd4a8cc55167f83" integrity sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA== @@ -21548,6 +22084,11 @@ memfs@^3.4.3: dependencies: fs-monkey "^1.0.4" +memoirist@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/memoirist/-/memoirist-0.4.0.tgz#7677aa70f8c2f7f0791f8af1b689495c8dbc906d" + integrity sha512-zxTgA0mSYELa66DimuNQDvyLq36AwDlTuVRbnQtB+VuTcKWm5Qc4z3WkSpgsFWHNhexqkIooqpv4hdcqrX5Nmg== + memory-pager@^1.0.2: version "1.5.0" resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" @@ -22042,7 +22583,7 @@ minimalistic-assert@^1.0.0: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@10.1.1, minimatch@10.2.4, minimatch@^10.2.2, minimatch@^10.2.4: +minimatch@10.1.1, minimatch@10.2.4, minimatch@^10.0.3, minimatch@^10.2.2, minimatch@^10.2.4: version "10.2.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.2.4.tgz#465b3accbd0218b8281f5301e27cedc697f96fde" integrity sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg== @@ -25404,6 +25945,24 @@ property-information@^7.0.0: resolved "https://registry.yarnpkg.com/property-information/-/property-information-7.1.0.tgz#b622e8646e02b580205415586b40804d3e8bfd5d" integrity sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ== +protobufjs@^7.3.0, protobufjs@^7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.5.4.tgz#885d31fe9c4b37f25d1bb600da30b1c5b37d286a" + integrity sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/node" ">=13.7.0" + long "^5.0.0" + proxy-addr@^2.0.7, proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -29393,10 +29952,10 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== -undici-types@~6.20.0: - version "6.20.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" - integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== +undici-types@~7.18.0: + version "7.18.2" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.18.2.tgz#29357a89e7b7ca4aef3bf0fd3fd0cd73884229e9" + integrity sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w== undici@7.18.2: version "7.18.2" @@ -31113,7 +31672,7 @@ yargs@^16.1.1, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.2.1, yargs@^17.5.1, yargs@^17.6.0, yargs@^17.6.2: +yargs@^17.2.1, yargs@^17.5.1, yargs@^17.6.0, yargs@^17.6.2, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From da9558eeebdabe47d54bc5da3640c631d9dd5bf6 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 10:51:16 -0400 Subject: [PATCH 02/21] fix: add all required entries to craft --- .craft.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.craft.yml b/.craft.yml index b4499fbe2cd4..0e5c58708ca0 100644 --- a/.craft.yml +++ b/.craft.yml @@ -201,8 +201,6 @@ targets: onlyIfPresent: /^sentry-cloudflare-\d.*\.tgz$/ 'npm:@sentry/deno': onlyIfPresent: /^sentry-deno-\d.*\.tgz$/ - 'npm:@sentry/elysia': - onlyIfPresent: /^sentry-elysia-\d.*\.tgz$/ 'npm:@sentry/ember': onlyIfPresent: /^sentry-ember-\d.*\.tgz$/ 'npm:@sentry/gatsby': @@ -251,3 +249,8 @@ targets: sdkName: 'sentry.javascript.effect' packageUrl: 'https://www.npmjs.com/package/@sentry/effect' onlyIfPresent: /^sentry-effect-\d.*\.tgz$/ + 'npm:@sentry/elysia': + name: 'Sentry Elysia SDK' + packageUrl: 'https://www.npmjs.com/package/@sentry/elysia' + mainDocsUrl: 'https://docs.sentry.io/platforms/javascript/guides/elysia/' + onlyIfPresent: /^sentry-elysia-\d.*\.tgz$/ From cc505c25965025f89bc0648774b48f121881291f Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 10:53:45 -0400 Subject: [PATCH 03/21] fix: apply the sdk stack metadata --- packages/elysia/src/sdk.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/elysia/src/sdk.ts b/packages/elysia/src/sdk.ts index 567af8834c93..f8d8dd9d8a35 100644 --- a/packages/elysia/src/sdk.ts +++ b/packages/elysia/src/sdk.ts @@ -41,8 +41,6 @@ function getRuntime(): { name: string; version: string } { * ``` */ export function init(userOptions: ElysiaOptions = {}): NodeClient | undefined { - applySdkMetadata(userOptions, 'elysia'); - const options = { ...userOptions, platform: 'javascript', @@ -50,6 +48,8 @@ export function init(userOptions: ElysiaOptions = {}): NodeClient | undefined { serverName: userOptions.serverName || global.process.env.SENTRY_NAME || os.hostname(), }; + applySdkMetadata(userOptions, 'elysia', ['elysia', options.runtime.name]); + options.transport = options.transport || makeFetchTransport; if (options.defaultIntegrations === undefined) { From 8b5bffe932eaba29a7c38bd83be3e95f8381b16b Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 10:56:43 -0400 Subject: [PATCH 04/21] fix: error handling mechanism name --- packages/elysia/src/withElysia.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/elysia/src/withElysia.ts b/packages/elysia/src/withElysia.ts index 7e3b63c368c5..650e9d4e3907 100644 --- a/packages/elysia/src/withElysia.ts +++ b/packages/elysia/src/withElysia.ts @@ -96,7 +96,7 @@ export function withElysia(app: T, options?: Partial Date: Thu, 19 Mar 2026 10:56:58 -0400 Subject: [PATCH 05/21] fix: update versions --- packages/elysia/package.json | 6 +- yarn.lock | 356 +++++++---------------------------- 2 files changed, 72 insertions(+), 290 deletions(-) diff --git a/packages/elysia/package.json b/packages/elysia/package.json index 196208747dcc..bcadd795467e 100644 --- a/packages/elysia/package.json +++ b/packages/elysia/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/elysia", - "version": "10.43.0", + "version": "10.44.0", "description": "Official Sentry SDK for Elysia", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/elysia", @@ -39,8 +39,8 @@ "access": "public" }, "dependencies": { - "@sentry/bun": "10.43.0", - "@sentry/core": "10.43.0" + "@sentry/bun": "10.44.0", + "@sentry/core": "10.44.0" }, "peerDependencies": { "elysia": "^1.4.0", diff --git a/yarn.lock b/yarn.lock index 3e5a076b6e98..177a10facd7d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4433,16 +4433,6 @@ resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.0.0.tgz#f22824caff3ae506b18207bad4126dbc6ccdb6b8" integrity sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ== -"@fastify/otel@0.16.0": - version "0.16.0" - resolved "https://registry.yarnpkg.com/@fastify/otel/-/otel-0.16.0.tgz#e003c9b81039490af9141a7f1397de6b05baa768" - integrity sha512-2304BdM5Q/kUvQC9qJO1KZq3Zn1WWsw+WWkVmFEaj1UE2hEIiuFqrPeglQOwEtw/ftngisqfQ3v70TWMmwhhHA== - dependencies: - "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.208.0" - "@opentelemetry/semantic-conventions" "^1.28.0" - minimatch "^10.0.3" - "@fastify/otel@0.17.1": version "0.17.1" resolved "https://registry.yarnpkg.com/@fastify/otel/-/otel-0.17.1.tgz#a7f13edc40dbc2e0c2a59d54e388f11e4d2235ce" @@ -6251,12 +6241,12 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-2.0.0.tgz#c98a727238ca199cda943780acf6124af8d8cd80" integrity sha512-IEkJGzK1A9v3/EHjXh3s2IiFc6L4jfK+lNgKVgUjeUJQRRhnVFMIO3TAvKwonm9O1HebCuoOt98v8bZW7oVQHA== -"@opentelemetry/context-async-hooks@^2.5.1", "@opentelemetry/context-async-hooks@^2.6.0": +"@opentelemetry/context-async-hooks@^2.6.0": version "2.6.0" resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-2.6.0.tgz#6c824e900630b378233c1a78ca7f0dc5a3b460b2" integrity sha512-L8UyDwqpTcbkIK5cgwDRDYDoEhQoj8wp8BwsO19w3LB1Z41yEQm2VJyNfAi9DrLP/YTqXqWpKHyZfR9/tFYo1Q== -"@opentelemetry/core@2.0.0", "@opentelemetry/core@2.5.0", "@opentelemetry/core@2.6.0", "@opentelemetry/core@^2.0.0", "@opentelemetry/core@^2.5.1", "@opentelemetry/core@^2.6.0": +"@opentelemetry/core@2.0.0", "@opentelemetry/core@2.6.0", "@opentelemetry/core@^2.0.0", "@opentelemetry/core@^2.6.0": version "2.6.0" resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-2.6.0.tgz#719c829ed98bd7af808a2d2c83374df1fd1f3c66" integrity sha512-HLM1v2cbZ4TgYN6KEOj+Bbj8rAKriOdkF9Ed3tG25FoprSiQl7kYc+RRT6fUZGOvx0oMi5U67GoFdT+XUn8zEg== @@ -6390,15 +6380,6 @@ "@opentelemetry/sdk-trace-base" "2.0.0" "@opentelemetry/semantic-conventions" "^1.29.0" -"@opentelemetry/instrumentation-amqplib@0.58.0": - version "0.58.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.58.0.tgz#e3dc86ebfa7d72fe861a63b1c24a062faeb64a8c" - integrity sha512-fjpQtH18J6GxzUZ+cwNhWUpb71u+DzT7rFkg5pLssDGaEber91Y2WNGdpVpwGivfEluMlNMZumzjEqfg8DeKXQ== - dependencies: - "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/semantic-conventions" "^1.33.0" - "@opentelemetry/instrumentation-amqplib@0.60.0": version "0.60.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.60.0.tgz#a2b2abe3cf433bea166c18a703c8ddf6accf83da" @@ -6417,16 +6398,6 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.34.0" -"@opentelemetry/instrumentation-connect@0.54.0": - version "0.54.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.54.0.tgz#87312850844b6c57976d00bd3256d55650543772" - integrity sha512-43RmbhUhqt3uuPnc16cX6NsxEASEtn8z/cYV8Zpt6EP4p2h9s4FNuJ4Q9BbEQ2C0YlCCB/2crO1ruVz/hWt8fA== - dependencies: - "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/semantic-conventions" "^1.27.0" - "@types/connect" "3.4.38" - "@opentelemetry/instrumentation-connect@0.56.0": version "0.56.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.56.0.tgz#8d846d2f7cf1f6b2723e5b0ff5595e8d31cb7446" @@ -6437,13 +6408,6 @@ "@opentelemetry/semantic-conventions" "^1.27.0" "@types/connect" "3.4.38" -"@opentelemetry/instrumentation-dataloader@0.28.0": - version "0.28.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.28.0.tgz#b857bb038e4a2a3b7278f3da89a1e210bb15339e" - integrity sha512-ExXGBp0sUj8yhm6Znhf9jmuOaGDsYfDES3gswZnKr4MCqoBWQdEFn6EoDdt5u+RdbxQER+t43FoUihEfTSqsjA== - dependencies: - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/instrumentation-dataloader@0.30.0": version "0.30.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.30.0.tgz#7fbea57b27165324092639abf090ca3697eb7a80" @@ -6451,15 +6415,6 @@ dependencies: "@opentelemetry/instrumentation" "^0.213.0" -"@opentelemetry/instrumentation-express@0.59.0": - version "0.59.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.59.0.tgz#c2ac7dcb4f9904926518408cdf4efb046e724382" - integrity sha512-pMKV/qnHiW/Q6pmbKkxt0eIhuNEtvJ7sUAyee192HErlr+a1Jx+FZ3WjfmzhQL1geewyGEiPGkmjjAgNY8TgDA== - dependencies: - "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/semantic-conventions" "^1.27.0" - "@opentelemetry/instrumentation-express@0.61.0": version "0.61.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.61.0.tgz#49b4d144ab6e9d6e035941a51f5e573e84e3647f" @@ -6469,14 +6424,6 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.27.0" -"@opentelemetry/instrumentation-fs@0.30.0": - version "0.30.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.30.0.tgz#5e28edde0591dc4ffa471a86a68f91e737fe31fb" - integrity sha512-n3Cf8YhG7reaj5dncGlRIU7iT40bxPOjsBEA5Bc1a1g6e9Qvb+JFJ7SEiMlPbUw4PBmxE3h40ltE8LZ3zVt6OA== - dependencies: - "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/instrumentation-fs@0.32.0": version "0.32.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.32.0.tgz#2010d86da8ab3d543f8e44c8fff81b94f904d91d" @@ -6485,13 +6432,6 @@ "@opentelemetry/core" "^2.0.0" "@opentelemetry/instrumentation" "^0.213.0" -"@opentelemetry/instrumentation-generic-pool@0.54.0": - version "0.54.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.54.0.tgz#9f3ad0cedbfe5011efe4ebdc76c85a73a0b967a6" - integrity sha512-8dXMBzzmEdXfH/wjuRvcJnUFeWzZHUnExkmFJ2uPfa31wmpyBCMxO59yr8f/OXXgSogNgi/uPo9KW9H7LMIZ+g== - dependencies: - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/instrumentation-generic-pool@0.56.0": version "0.56.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.56.0.tgz#01560f52d5bac6fb6312a1f0bc74bf0939119894" @@ -6499,13 +6439,6 @@ dependencies: "@opentelemetry/instrumentation" "^0.213.0" -"@opentelemetry/instrumentation-graphql@0.58.0": - version "0.58.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.58.0.tgz#3ca294ba410e04c920dc82ab4caa23ec1c2e1a2e" - integrity sha512-+yWVVY7fxOs3j2RixCbvue8vUuJ1inHxN2q1sduqDB0Wnkr4vOzVKRYl/Zy7B31/dcPS72D9lo/kltdOTBM3bQ== - dependencies: - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/instrumentation-graphql@0.61.0": version "0.61.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.61.0.tgz#d1f896095a891c9576967645e7fcba935da82a94" @@ -6513,15 +6446,6 @@ dependencies: "@opentelemetry/instrumentation" "^0.213.0" -"@opentelemetry/instrumentation-hapi@0.57.0": - version "0.57.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.57.0.tgz#27b3a44a51444af3100a321f2e40623e89e5bb75" - integrity sha512-Os4THbvls8cTQTVA8ApLfZZztuuqGEeqog0XUnyRW7QVF0d/vOVBEcBCk1pazPFmllXGEdNbbat8e2fYIWdFbw== - dependencies: - "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/semantic-conventions" "^1.27.0" - "@opentelemetry/instrumentation-hapi@0.59.0": version "0.59.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.59.0.tgz#412ea19e97ead684c5737e1f1aaa19ff940512d3" @@ -6531,16 +6455,6 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.27.0" -"@opentelemetry/instrumentation-http@0.211.0": - version "0.211.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.211.0.tgz#2f12f83f0c21d37917fd9710fb5b755f28858cf6" - integrity sha512-n0IaQ6oVll9PP84SjbOCwDjaJasWRHi6BLsbMLiT6tNj7QbVOkuA5sk/EfZczwI0j5uTKl1awQPivO/ldVtsqA== - dependencies: - "@opentelemetry/core" "2.5.0" - "@opentelemetry/instrumentation" "0.211.0" - "@opentelemetry/semantic-conventions" "^1.29.0" - forwarded-parse "2.1.2" - "@opentelemetry/instrumentation-http@0.213.0": version "0.213.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.213.0.tgz#b379d6bcbae43a7d6d54070f3794527021f176c9" @@ -6551,15 +6465,6 @@ "@opentelemetry/semantic-conventions" "^1.29.0" forwarded-parse "2.1.2" -"@opentelemetry/instrumentation-ioredis@0.59.0": - version "0.59.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.59.0.tgz#530d06aa67b73ea732414557adebe1dde7de430f" - integrity sha512-875UxzBHWkW+P4Y45SoFM2AR8f8TzBMD8eO7QXGCyFSCUMP5s9vtt/BS8b/r2kqLyaRPK6mLbdnZznK3XzQWvw== - dependencies: - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/redis-common" "^0.38.2" - "@opentelemetry/semantic-conventions" "^1.33.0" - "@opentelemetry/instrumentation-ioredis@0.61.0": version "0.61.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.61.0.tgz#e862540cbf188d0ca368d3a75020d165cb8beefb" @@ -6569,14 +6474,6 @@ "@opentelemetry/redis-common" "^0.38.2" "@opentelemetry/semantic-conventions" "^1.33.0" -"@opentelemetry/instrumentation-kafkajs@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.20.0.tgz#521db06d10d39f42e842ce336e5c1e48b3da2956" - integrity sha512-yJXOuWZROzj7WmYCUiyT27tIfqBrVtl1/TwVbQyWPz7rL0r1Lu7kWjD0PiVeTCIL6CrIZ7M2s8eBxsTAOxbNvw== - dependencies: - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/semantic-conventions" "^1.30.0" - "@opentelemetry/instrumentation-kafkajs@0.22.0": version "0.22.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.22.0.tgz#a3cf7aca003f96211e514a348b7568799efdfba1" @@ -6585,14 +6482,6 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.30.0" -"@opentelemetry/instrumentation-knex@0.55.0": - version "0.55.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.55.0.tgz#fefc17d854a107d99ab0dbc8933d5897efce1abd" - integrity sha512-FtTL5DUx5Ka/8VK6P1VwnlUXPa3nrb7REvm5ddLUIeXXq4tb9pKd+/ThB1xM/IjefkRSN3z8a5t7epYw1JLBJQ== - dependencies: - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/semantic-conventions" "^1.33.1" - "@opentelemetry/instrumentation-knex@0.57.0": version "0.57.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.57.0.tgz#d46622a3f82f3df2ba29c64498d6ef828a40457e" @@ -6601,15 +6490,6 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.33.1" -"@opentelemetry/instrumentation-koa@0.59.0": - version "0.59.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.59.0.tgz#7df8850fa193a8f590e3fbcab00016e25db27041" - integrity sha512-K9o2skADV20Skdu5tG2bogPKiSpXh4KxfLjz6FuqIVvDJNibwSdu5UvyyBzRVp1rQMV6UmoIk6d3PyPtJbaGSg== - dependencies: - "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/semantic-conventions" "^1.36.0" - "@opentelemetry/instrumentation-koa@0.61.0": version "0.61.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.61.0.tgz#c12f57b023834afb1c142c11746d560bcc288b5b" @@ -6619,13 +6499,6 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.36.0" -"@opentelemetry/instrumentation-lru-memoizer@0.55.0": - version "0.55.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.55.0.tgz#776d5f10178adfbda7286b4f31adde8bb518d55a" - integrity sha512-FDBfT7yDGcspN0Cxbu/k8A0Pp1Jhv/m7BMTzXGpcb8ENl3tDj/51U65R5lWzUH15GaZA15HQ5A5wtafklxYj7g== - dependencies: - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/instrumentation-lru-memoizer@0.57.0": version "0.57.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.57.0.tgz#4da92ecd1bc5d5e9c7de28ea14ed57c9f29cfefd" @@ -6633,14 +6506,6 @@ dependencies: "@opentelemetry/instrumentation" "^0.213.0" -"@opentelemetry/instrumentation-mongodb@0.64.0": - version "0.64.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.64.0.tgz#0027c13fdd7506eb1f618998245edd244cc23cc7" - integrity sha512-pFlCJjweTqVp7B220mCvCld1c1eYKZfQt1p3bxSbcReypKLJTwat+wbL2YZoX9jPi5X2O8tTKFEOahO5ehQGsA== - dependencies: - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/semantic-conventions" "^1.33.0" - "@opentelemetry/instrumentation-mongodb@0.66.0": version "0.66.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.66.0.tgz#990bf4571382d3b02a9584927411c92c375d2fd4" @@ -6649,15 +6514,6 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.33.0" -"@opentelemetry/instrumentation-mongoose@0.57.0": - version "0.57.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.57.0.tgz#2ce3f3bbf66a255958c3a112a92079898d69f624" - integrity sha512-MthiekrU/BAJc5JZoZeJmo0OTX6ycJMiP6sMOSRTkvz5BrPMYDqaJos0OgsLPL/HpcgHP7eo5pduETuLguOqcg== - dependencies: - "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/semantic-conventions" "^1.33.0" - "@opentelemetry/instrumentation-mongoose@0.59.0": version "0.59.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.59.0.tgz#8446ece86df59f09c630e7df6d794c8cd08f58d8" @@ -6667,15 +6523,6 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.33.0" -"@opentelemetry/instrumentation-mysql2@0.57.0": - version "0.57.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.57.0.tgz#928eda47c6f4ab193d3363fcab01d81a70adc46b" - integrity sha512-nHSrYAwF7+aV1E1V9yOOP9TchOodb6fjn4gFvdrdQXiRE7cMuffyLLbCZlZd4wsspBzVwOXX8mpURdRserAhNA== - dependencies: - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/semantic-conventions" "^1.33.0" - "@opentelemetry/sql-common" "^0.41.2" - "@opentelemetry/instrumentation-mysql2@0.59.0": version "0.59.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.59.0.tgz#938cd4a294b7e4a6e8c3855b8cfe267c8d2e5493" @@ -6685,15 +6532,6 @@ "@opentelemetry/semantic-conventions" "^1.33.0" "@opentelemetry/sql-common" "^0.41.2" -"@opentelemetry/instrumentation-mysql@0.57.0": - version "0.57.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.57.0.tgz#74d42a1c6d20aee93996f8b6f6b7b69469748754" - integrity sha512-HFS/+FcZ6Q7piM7Il7CzQ4VHhJvGMJWjx7EgCkP5AnTntSN5rb5Xi3TkYJHBKeR27A0QqPlGaCITi93fUDs++Q== - dependencies: - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/semantic-conventions" "^1.33.0" - "@types/mysql" "2.15.27" - "@opentelemetry/instrumentation-mysql@0.59.0": version "0.59.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.59.0.tgz#bf43cafbac5928236ea53704a52c718349c22e38" @@ -6711,18 +6549,6 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.30.0" -"@opentelemetry/instrumentation-pg@0.63.0": - version "0.63.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.63.0.tgz#852ca5519d756c613bb9f3153a5e70c2b805e5cf" - integrity sha512-dKm/ODNN3GgIQVlbD6ZPxwRc3kleLf95hrRWXM+l8wYo+vSeXtEpQPT53afEf6VFWDVzJK55VGn8KMLtSve/cg== - dependencies: - "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/semantic-conventions" "^1.34.0" - "@opentelemetry/sql-common" "^0.41.2" - "@types/pg" "8.15.6" - "@types/pg-pool" "2.0.7" - "@opentelemetry/instrumentation-pg@0.65.0": version "0.65.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.65.0.tgz#f1f76f8c57c5c6fec68c77ce6ee104fee5de13e1" @@ -6735,15 +6561,6 @@ "@types/pg" "8.15.6" "@types/pg-pool" "2.0.7" -"@opentelemetry/instrumentation-redis@0.59.0": - version "0.59.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.59.0.tgz#44c1bd7852cdadbe77c1bdfa94185528012558cf" - integrity sha512-JKv1KDDYA2chJ1PC3pLP+Q9ISMQk6h5ey+99mB57/ARk0vQPGZTTEb4h4/JlcEpy7AYT8HIGv7X6l+br03Neeg== - dependencies: - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/redis-common" "^0.38.2" - "@opentelemetry/semantic-conventions" "^1.27.0" - "@opentelemetry/instrumentation-redis@0.61.0": version "0.61.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.61.0.tgz#b43b9c3b5d0b124f2e60b055e4529a3a4b55dbc4" @@ -6753,15 +6570,6 @@ "@opentelemetry/redis-common" "^0.38.2" "@opentelemetry/semantic-conventions" "^1.27.0" -"@opentelemetry/instrumentation-tedious@0.30.0": - version "0.30.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.30.0.tgz#4a8906b5322c4add4132e6e086c23e17bc23626b" - integrity sha512-bZy9Q8jFdycKQ2pAsyuHYUHNmCxCOGdG6eg1Mn75RvQDccq832sU5OWOBnc12EFUELI6icJkhR7+EQKMBam2GA== - dependencies: - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/semantic-conventions" "^1.33.0" - "@types/tedious" "^4.0.14" - "@opentelemetry/instrumentation-tedious@0.32.0": version "0.32.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.32.0.tgz#8204a14adb71adcbf7d72705244d606bb69e428a" @@ -6771,15 +6579,6 @@ "@opentelemetry/semantic-conventions" "^1.33.0" "@types/tedious" "^4.0.14" -"@opentelemetry/instrumentation-undici@0.21.0": - version "0.21.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.21.0.tgz#dcb43a364c39e78217946aeb7aa09156e55f4c6c" - integrity sha512-gok0LPUOTz2FQ1YJMZzaHcOzDFyT64XJ8M9rNkugk923/p6lDGms/cRW1cqgqp6N6qcd6K6YdVHwPEhnx9BWbw== - dependencies: - "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/semantic-conventions" "^1.24.0" - "@opentelemetry/instrumentation-undici@0.23.0": version "0.23.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.23.0.tgz#e328bf6e53847ba7baa2a345d02221cc62917cec" @@ -6789,7 +6588,7 @@ "@opentelemetry/instrumentation" "^0.213.0" "@opentelemetry/semantic-conventions" "^1.24.0" -"@opentelemetry/instrumentation@0.200.0", "@opentelemetry/instrumentation@0.211.0", "@opentelemetry/instrumentation@0.213.0", "@opentelemetry/instrumentation@^0.200.0", "@opentelemetry/instrumentation@^0.207.0", "@opentelemetry/instrumentation@^0.208.0", "@opentelemetry/instrumentation@^0.211.0", "@opentelemetry/instrumentation@^0.212.0", "@opentelemetry/instrumentation@^0.213.0": +"@opentelemetry/instrumentation@0.200.0", "@opentelemetry/instrumentation@0.213.0", "@opentelemetry/instrumentation@^0.200.0", "@opentelemetry/instrumentation@^0.207.0", "@opentelemetry/instrumentation@^0.212.0", "@opentelemetry/instrumentation@^0.213.0": version "0.213.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.213.0.tgz#55362569efd0cba00aab9921a78dd20dfddf70b6" integrity sha512-3i9NdkET/KvQomeh7UaR/F4r9P25Rx6ooALlWXPIjypcEOUxksCmVu0zA70NBJWlrMW1rPr/LRidFAflLI+s/w== @@ -6848,7 +6647,7 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/redis-common/-/redis-common-0.38.2.tgz#cefa4f3e79db1cd54f19e233b7dfb56621143955" integrity sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA== -"@opentelemetry/resources@2.0.0", "@opentelemetry/resources@2.6.0", "@opentelemetry/resources@^2.5.1", "@opentelemetry/resources@^2.6.0": +"@opentelemetry/resources@2.0.0", "@opentelemetry/resources@2.6.0", "@opentelemetry/resources@^2.6.0": version "2.6.0" resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-2.6.0.tgz#1a945dbb8986043d8b593c358d5d8e3de6becf5a" integrity sha512-D4y/+OGe3JSuYUCBxtH5T9DSAWNcvCb/nQWIga8HNtXTVPQn59j0nTBAgaAXxUVBDl40mG3Tc76b46wPlZaiJQ== @@ -6901,7 +6700,7 @@ "@opentelemetry/sdk-trace-node" "2.0.0" "@opentelemetry/semantic-conventions" "^1.29.0" -"@opentelemetry/sdk-trace-base@2.0.0", "@opentelemetry/sdk-trace-base@2.6.0", "@opentelemetry/sdk-trace-base@^2.5.1", "@opentelemetry/sdk-trace-base@^2.6.0": +"@opentelemetry/sdk-trace-base@2.0.0", "@opentelemetry/sdk-trace-base@2.6.0", "@opentelemetry/sdk-trace-base@^2.6.0": version "2.6.0" resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.6.0.tgz#d7e752a0906f2bcae3c1261e224aef3e3b3746f9" integrity sha512-g/OZVkqlxllgFM7qMKqbPV9c1DUPhQ7d4n3pgZFcrnrNft9eJXZM2TNHTPYREJBrtNdRytYyvwjgL5geDKl3EQ== @@ -6919,7 +6718,7 @@ "@opentelemetry/core" "2.0.0" "@opentelemetry/sdk-trace-base" "2.0.0" -"@opentelemetry/semantic-conventions@^1.24.0", "@opentelemetry/semantic-conventions@^1.27.0", "@opentelemetry/semantic-conventions@^1.28.0", "@opentelemetry/semantic-conventions@^1.29.0", "@opentelemetry/semantic-conventions@^1.30.0", "@opentelemetry/semantic-conventions@^1.33.0", "@opentelemetry/semantic-conventions@^1.33.1", "@opentelemetry/semantic-conventions@^1.34.0", "@opentelemetry/semantic-conventions@^1.36.0", "@opentelemetry/semantic-conventions@^1.39.0", "@opentelemetry/semantic-conventions@^1.40.0": +"@opentelemetry/semantic-conventions@^1.24.0", "@opentelemetry/semantic-conventions@^1.27.0", "@opentelemetry/semantic-conventions@^1.28.0", "@opentelemetry/semantic-conventions@^1.29.0", "@opentelemetry/semantic-conventions@^1.30.0", "@opentelemetry/semantic-conventions@^1.33.0", "@opentelemetry/semantic-conventions@^1.33.1", "@opentelemetry/semantic-conventions@^1.34.0", "@opentelemetry/semantic-conventions@^1.36.0", "@opentelemetry/semantic-conventions@^1.40.0": version "1.40.0" resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.40.0.tgz#10b2944ca559386590683392022a897eefd011d3" integrity sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw== @@ -7450,13 +7249,6 @@ dependencies: "@prisma/debug" "6.15.0" -"@prisma/instrumentation@7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-7.2.0.tgz#9409a436d8f98e8950c8659aeeba045c4a07e891" - integrity sha512-Rh9Z4x5kEj1OdARd7U18AtVrnL6rmLSI0qYShaB4W7Wx5BKbgzndWF+QnuzMb7GLfVdlT5aYCXoPQVYuYtVu0g== - dependencies: - "@opentelemetry/instrumentation" "^0.207.0" - "@prisma/instrumentation@7.4.2": version "7.4.2" resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-7.4.2.tgz#b05e814d0647343febd26a8ccb039d27ccc69eca" @@ -8128,13 +7920,13 @@ resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-5.1.1.tgz#9eeef63099011155691a5ee59b0f796c141e8f85" integrity sha512-x2wEpBHwsTyTF2rWsLKJlzrRF1TTIGOfX+ngdE+Yd5DBkoS58HwQv824QOviPGQRla4/ypISqAXzjdDPL/zalg== -"@sentry/bun@10.43.0": - version "10.43.0" - resolved "https://registry.yarnpkg.com/@sentry/bun/-/bun-10.43.0.tgz#bb502e0ddf558e64063763bca304281730fe4d92" - integrity sha512-BMWmJNU4Bl2AClcXUpOhR+ZFxl8bCg3k797ESqUC+vzDe13i81iwhh8NAN8kHEoRY771fh/bIqe8n6KKFKIr0A== +"@sentry/bun@10.44.0": + version "10.44.0" + resolved "https://registry.yarnpkg.com/@sentry/bun/-/bun-10.44.0.tgz#a6351785b4a062cb2f10389e3e0de67be364addc" + integrity sha512-abVguUvPi8e3uyWlwHKTQ4vMTikkaTV7gpN4Zk4TgGqab1go9sEVXabksQFoVdEiFha1HGYyg9uNjMpYdOV5EA== dependencies: - "@sentry/core" "10.43.0" - "@sentry/node" "10.43.0" + "@sentry/core" "10.44.0" + "@sentry/node" "10.44.0" "@sentry/bundler-plugin-core@5.1.0": version "5.1.0" @@ -8222,67 +8014,67 @@ "@sentry/cli-win32-i686" "2.58.5" "@sentry/cli-win32-x64" "2.58.5" -"@sentry/core@10.43.0": - version "10.43.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-10.43.0.tgz#48b7b2295f36097775b529c59712688c9087c7bc" - integrity sha512-l0SszQAPiQGWl/ferw8GP3ALyHXiGiRKJaOvNmhGO+PrTQyZTZ6OYyPnGijAFRg58dE1V3RCH/zw5d2xSUIiNg== +"@sentry/core@10.44.0": + version "10.44.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-10.44.0.tgz#a24cdf4742b064e3340cb1cd05146e39c9ab4746" + integrity sha512-aa7CiDaNFZvHpqd97LJhuskolfJ/4IH5xyuVVLnv7l6B0v9KTwskPUxb0tH1ej3FxuzfH+i8iTiTFuqpfHS3QA== -"@sentry/node-core@10.43.0": - version "10.43.0" - resolved "https://registry.yarnpkg.com/@sentry/node-core/-/node-core-10.43.0.tgz#f8575be3ad09e86e8e18e54074f3bcafea344234" - integrity sha512-w2H3NSkNMoYOS7o7mR55BM7+xL++dPxMSv1/XDfsra9FYHGppO+Mxk667Ee5k+uDi+wNIioICIh+5XOvZh4+HQ== +"@sentry/node-core@10.44.0": + version "10.44.0" + resolved "https://registry.yarnpkg.com/@sentry/node-core/-/node-core-10.44.0.tgz#d331f677b39cd42d9f0dcbbc7e1c0c4cfa74ea9e" + integrity sha512-jUGsadMrvZ08UMbqJBfjFFMk1k3VbyxfUypf0iDGGgyLmuHotYQPo/5aND+o2KxMDXR60LwcQrMoZFpanK6jXQ== dependencies: - "@sentry/core" "10.43.0" - "@sentry/opentelemetry" "10.43.0" - import-in-the-middle "^2.0.6" + "@sentry/core" "10.44.0" + "@sentry/opentelemetry" "10.44.0" + import-in-the-middle "^3.0.0" -"@sentry/node@10.43.0": - version "10.43.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-10.43.0.tgz#466acf853565d92d972b7e012fab6558a32a739e" - integrity sha512-oNwXcuZUc4uTTr0WbHZBBIKsKwAKvNMTgbXwxfB37CfzV18wbTirbQABZ/Ir3WNxSgi6ZcnC6UE013jF5XWPqw== +"@sentry/node@10.44.0": + version "10.44.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-10.44.0.tgz#4ff1aaceb69864b62b3e3bba7046b10c294f0c23" + integrity sha512-q+/WR9ZeF9Af8uyehOj2tQQOa7LH07mJfOuDus5X6G6cLuugdRUGUBB5Qhw+J/ULSxbzGADBZv6AYOyoGaNx7w== dependencies: - "@fastify/otel" "0.16.0" + "@fastify/otel" "0.17.1" "@opentelemetry/api" "^1.9.0" - "@opentelemetry/context-async-hooks" "^2.5.1" - "@opentelemetry/core" "^2.5.1" - "@opentelemetry/instrumentation" "^0.211.0" - "@opentelemetry/instrumentation-amqplib" "0.58.0" - "@opentelemetry/instrumentation-connect" "0.54.0" - "@opentelemetry/instrumentation-dataloader" "0.28.0" - "@opentelemetry/instrumentation-express" "0.59.0" - "@opentelemetry/instrumentation-fs" "0.30.0" - "@opentelemetry/instrumentation-generic-pool" "0.54.0" - "@opentelemetry/instrumentation-graphql" "0.58.0" - "@opentelemetry/instrumentation-hapi" "0.57.0" - "@opentelemetry/instrumentation-http" "0.211.0" - "@opentelemetry/instrumentation-ioredis" "0.59.0" - "@opentelemetry/instrumentation-kafkajs" "0.20.0" - "@opentelemetry/instrumentation-knex" "0.55.0" - "@opentelemetry/instrumentation-koa" "0.59.0" - "@opentelemetry/instrumentation-lru-memoizer" "0.55.0" - "@opentelemetry/instrumentation-mongodb" "0.64.0" - "@opentelemetry/instrumentation-mongoose" "0.57.0" - "@opentelemetry/instrumentation-mysql" "0.57.0" - "@opentelemetry/instrumentation-mysql2" "0.57.0" - "@opentelemetry/instrumentation-pg" "0.63.0" - "@opentelemetry/instrumentation-redis" "0.59.0" - "@opentelemetry/instrumentation-tedious" "0.30.0" - "@opentelemetry/instrumentation-undici" "0.21.0" - "@opentelemetry/resources" "^2.5.1" - "@opentelemetry/sdk-trace-base" "^2.5.1" - "@opentelemetry/semantic-conventions" "^1.39.0" - "@prisma/instrumentation" "7.2.0" - "@sentry/core" "10.43.0" - "@sentry/node-core" "10.43.0" - "@sentry/opentelemetry" "10.43.0" - import-in-the-middle "^2.0.6" - -"@sentry/opentelemetry@10.43.0": - version "10.43.0" - resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-10.43.0.tgz#c2d3d58e943541a7ae81e79cf264b61c7fa20f1b" - integrity sha512-+fIcnnLdvBHdq4nKq23t9v/B9D4L97fPWEDksXbpGs11o6BsqY4Tlzmce6cP95iiQhPckCEag3FthSND+BYtYQ== - dependencies: - "@sentry/core" "10.43.0" + "@opentelemetry/context-async-hooks" "^2.6.0" + "@opentelemetry/core" "^2.6.0" + "@opentelemetry/instrumentation" "^0.213.0" + "@opentelemetry/instrumentation-amqplib" "0.60.0" + "@opentelemetry/instrumentation-connect" "0.56.0" + "@opentelemetry/instrumentation-dataloader" "0.30.0" + "@opentelemetry/instrumentation-express" "0.61.0" + "@opentelemetry/instrumentation-fs" "0.32.0" + "@opentelemetry/instrumentation-generic-pool" "0.56.0" + "@opentelemetry/instrumentation-graphql" "0.61.0" + "@opentelemetry/instrumentation-hapi" "0.59.0" + "@opentelemetry/instrumentation-http" "0.213.0" + "@opentelemetry/instrumentation-ioredis" "0.61.0" + "@opentelemetry/instrumentation-kafkajs" "0.22.0" + "@opentelemetry/instrumentation-knex" "0.57.0" + "@opentelemetry/instrumentation-koa" "0.61.0" + "@opentelemetry/instrumentation-lru-memoizer" "0.57.0" + "@opentelemetry/instrumentation-mongodb" "0.66.0" + "@opentelemetry/instrumentation-mongoose" "0.59.0" + "@opentelemetry/instrumentation-mysql" "0.59.0" + "@opentelemetry/instrumentation-mysql2" "0.59.0" + "@opentelemetry/instrumentation-pg" "0.65.0" + "@opentelemetry/instrumentation-redis" "0.61.0" + "@opentelemetry/instrumentation-tedious" "0.32.0" + "@opentelemetry/instrumentation-undici" "0.23.0" + "@opentelemetry/resources" "^2.6.0" + "@opentelemetry/sdk-trace-base" "^2.6.0" + "@opentelemetry/semantic-conventions" "^1.40.0" + "@prisma/instrumentation" "7.4.2" + "@sentry/core" "10.44.0" + "@sentry/node-core" "10.44.0" + "@sentry/opentelemetry" "10.44.0" + import-in-the-middle "^3.0.0" + +"@sentry/opentelemetry@10.44.0": + version "10.44.0" + resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-10.44.0.tgz#4b5880597c2f35942170fcaaecb10e12086b151f" + integrity sha512-zP4vP8tBxjlmxQ4VcWOwZ0b3lPUxlYPg9FqJwANm9SRJN+7V5psm8TIaAtu9uqtIcJMRHdXkOM4cAggNiLk0KA== + dependencies: + "@sentry/core" "10.44.0" "@sentry/rollup-plugin@5.1.0": version "5.1.0" @@ -19643,16 +19435,6 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -import-in-the-middle@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-2.0.6.tgz#1972337bfe020d05f6b5e020c13334567436324f" - integrity sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw== - dependencies: - acorn "^8.15.0" - acorn-import-attributes "^1.9.5" - cjs-module-lexer "^2.2.0" - module-details-from-path "^1.0.4" - import-in-the-middle@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-3.0.0.tgz#720c12b4c07ea58b32a54667e70a022e18cc36a3" @@ -22583,7 +22365,7 @@ minimalistic-assert@^1.0.0: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@10.1.1, minimatch@10.2.4, minimatch@^10.0.3, minimatch@^10.2.2, minimatch@^10.2.4: +minimatch@10.1.1, minimatch@10.2.4, minimatch@^10.2.2, minimatch@^10.2.4: version "10.2.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.2.4.tgz#465b3accbd0218b8281f5301e27cedc697f96fde" integrity sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg== From 102e7e9f2d3b1cc8e8d0f25c5f6767d5670e8914 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 10:57:53 -0400 Subject: [PATCH 06/21] chore: license date --- packages/elysia/LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/elysia/LICENSE b/packages/elysia/LICENSE index b3c4b18a6317..0ecae617386e 100644 --- a/packages/elysia/LICENSE +++ b/packages/elysia/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Functional Software, Inc. dba Sentry +Copyright (c) 2026 Functional Software, Inc. dba Sentry Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in From f93f9a2866552afd51508124689fe0a36923f8a1 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 11:00:26 -0400 Subject: [PATCH 07/21] chore: use oxlint for elysia --- packages/elysia/.eslintrc.js | 9 --------- packages/elysia/.oxlintrc.json | 4 ++++ 2 files changed, 4 insertions(+), 9 deletions(-) delete mode 100644 packages/elysia/.eslintrc.js create mode 100644 packages/elysia/.oxlintrc.json diff --git a/packages/elysia/.eslintrc.js b/packages/elysia/.eslintrc.js deleted file mode 100644 index 6da218bd8641..000000000000 --- a/packages/elysia/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - env: { - node: true, - }, - extends: ['../../.eslintrc.js'], - rules: { - '@sentry-internal/sdk/no-class-field-initializers': 'off', - }, -}; diff --git a/packages/elysia/.oxlintrc.json b/packages/elysia/.oxlintrc.json new file mode 100644 index 000000000000..942f110037c2 --- /dev/null +++ b/packages/elysia/.oxlintrc.json @@ -0,0 +1,4 @@ +{ + "$schema": "../../node_modules/oxlint/configuration_schema.json", + "extends": ["../../.oxlintrc.json"], +} From 2471c27c661ccff93a583f017b1542ac7d64f112 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 11:08:41 -0400 Subject: [PATCH 08/21] refactor: one less ternary --- packages/elysia/src/withElysia.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/elysia/src/withElysia.ts b/packages/elysia/src/withElysia.ts index 650e9d4e3907..94c6da61ea84 100644 --- a/packages/elysia/src/withElysia.ts +++ b/packages/elysia/src/withElysia.ts @@ -21,7 +21,7 @@ function defaultShouldHandleError(context: ErrorContext): boolean { if (status === undefined) { return true; } - const statusCode = typeof status === 'string' ? parseInt(status, 10) : status; + const statusCode = parseInt(String(status), 10); if (Number.isNaN(statusCode)) { return true; } From b4923c1450e982ffe9db803a6426868651d7d79d Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 11:10:43 -0400 Subject: [PATCH 09/21] refactor: use optional prop type over partial for now --- packages/elysia/src/withElysia.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/elysia/src/withElysia.ts b/packages/elysia/src/withElysia.ts index 94c6da61ea84..4fc2a0e965d1 100644 --- a/packages/elysia/src/withElysia.ts +++ b/packages/elysia/src/withElysia.ts @@ -10,7 +10,7 @@ import type { Elysia, ErrorContext } from 'elysia'; import { setupClientHooks } from './clientHooks'; interface ElysiaHandlerOptions { - shouldHandleError: (context: ErrorContext) => boolean; + shouldHandleError?: (context: ErrorContext) => boolean; } let isClientHooksSetup = false; @@ -50,7 +50,7 @@ function defaultShouldHandleError(context: ErrorContext): boolean { * .listen(3000); * ``` */ -export function withElysia(app: T, options?: Partial): T { +export function withElysia(app: T, options: ElysiaHandlerOptions = {}): T { if (instrumentedApps.has(app)) { return app; } From 8bb47f93e8f5d75a94e3429d6b2c8e0390954a12 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 11:23:10 -0400 Subject: [PATCH 10/21] chore: cleanup left over consistent export assertion --- .../node-exports-test-app/scripts/consistentExports.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/node-exports-test-app/scripts/consistentExports.ts b/dev-packages/e2e-tests/test-applications/node-exports-test-app/scripts/consistentExports.ts index 1ddb8e57c0b3..f195206fb5b2 100644 --- a/dev-packages/e2e-tests/test-applications/node-exports-test-app/scripts/consistentExports.ts +++ b/dev-packages/e2e-tests/test-applications/node-exports-test-app/scripts/consistentExports.ts @@ -41,7 +41,6 @@ const DEPENDENTS: Dependent[] = [ ignoreExports: [ // Not needed for Astro 'setupFastifyErrorHandler', - 'elysiaIntegration', 'withElysia', ], }, @@ -77,7 +76,6 @@ const DEPENDENTS: Dependent[] = [ ignoreExports: [ // Not needed for Serverless 'setupFastifyErrorHandler', - 'elysiaIntegration', 'withElysia', ], }, @@ -88,7 +86,6 @@ const DEPENDENTS: Dependent[] = [ ignoreExports: [ // Not needed for Serverless 'setupFastifyErrorHandler', - 'elysiaIntegration', 'withElysia', ], }, From 742bfa79e4c982e27eecb3c6c1fda50e6ecc516c Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 11:26:17 -0400 Subject: [PATCH 11/21] ref: use one loop to filter out spans --- packages/elysia/src/clientHooks.ts | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/packages/elysia/src/clientHooks.ts b/packages/elysia/src/clientHooks.ts index 6d1cb0cd646b..df77d2ca2612 100644 --- a/packages/elysia/src/clientHooks.ts +++ b/packages/elysia/src/clientHooks.ts @@ -40,23 +40,28 @@ export function setupClientHooks(client: Client): void { client.on('beforeSendEvent', (event: Event) => { if (event.type === 'transaction' && event.spans) { const elysiaSpanIds = new Set(); + const filteredSpans: typeof event.spans = []; + for (const span of event.spans) { + // Accumulate IDs of Elysia lifecycle spans if (span.origin === ELYSIA_ORIGIN) { elysiaSpanIds.add(span.span_id); } + + // Decide whether to keep the span + if ( + (!span.description || span.description === '') && + span.parent_span_id && + elysiaSpanIds.has(span.parent_span_id) + ) { + continue; // filter out + } + filteredSpans.push(span); } + // Only update if we filtered something out (or could have) if (elysiaSpanIds.size > 0) { - event.spans = event.spans.filter(span => { - if ( - (!span.description || span.description === '') && - span.parent_span_id && - elysiaSpanIds.has(span.parent_span_id) - ) { - return false; - } - return true; - }); + event.spans = filteredSpans; } } }); From 7d9f06d01f3534a89e25dd7f64b9c265b707dd6f Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 11:34:24 -0400 Subject: [PATCH 12/21] chore: bump again --- packages/elysia/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/elysia/package.json b/packages/elysia/package.json index bcadd795467e..18206f0c91e4 100644 --- a/packages/elysia/package.json +++ b/packages/elysia/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/elysia", - "version": "10.44.0", + "version": "10.45.0", "description": "Official Sentry SDK for Elysia", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/elysia", @@ -39,8 +39,8 @@ "access": "public" }, "dependencies": { - "@sentry/bun": "10.44.0", - "@sentry/core": "10.44.0" + "@sentry/bun": "10.45.0", + "@sentry/core": "10.45.0" }, "peerDependencies": { "elysia": "^1.4.0", From 2bae677d32bed3e3b6769bdc5ee7daace66bdd1c Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 11:34:52 -0400 Subject: [PATCH 13/21] chore: regen lock --- yarn.lock | 70 ------------------------------------------------------- 1 file changed, 70 deletions(-) diff --git a/yarn.lock b/yarn.lock index 177a10facd7d..693e7c24b8b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7920,14 +7920,6 @@ resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-5.1.1.tgz#9eeef63099011155691a5ee59b0f796c141e8f85" integrity sha512-x2wEpBHwsTyTF2rWsLKJlzrRF1TTIGOfX+ngdE+Yd5DBkoS58HwQv824QOviPGQRla4/ypISqAXzjdDPL/zalg== -"@sentry/bun@10.44.0": - version "10.44.0" - resolved "https://registry.yarnpkg.com/@sentry/bun/-/bun-10.44.0.tgz#a6351785b4a062cb2f10389e3e0de67be364addc" - integrity sha512-abVguUvPi8e3uyWlwHKTQ4vMTikkaTV7gpN4Zk4TgGqab1go9sEVXabksQFoVdEiFha1HGYyg9uNjMpYdOV5EA== - dependencies: - "@sentry/core" "10.44.0" - "@sentry/node" "10.44.0" - "@sentry/bundler-plugin-core@5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@sentry/bundler-plugin-core/-/bundler-plugin-core-5.1.0.tgz#01bef91543eb42cd370288573291b9a02b240e84" @@ -8014,68 +8006,6 @@ "@sentry/cli-win32-i686" "2.58.5" "@sentry/cli-win32-x64" "2.58.5" -"@sentry/core@10.44.0": - version "10.44.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-10.44.0.tgz#a24cdf4742b064e3340cb1cd05146e39c9ab4746" - integrity sha512-aa7CiDaNFZvHpqd97LJhuskolfJ/4IH5xyuVVLnv7l6B0v9KTwskPUxb0tH1ej3FxuzfH+i8iTiTFuqpfHS3QA== - -"@sentry/node-core@10.44.0": - version "10.44.0" - resolved "https://registry.yarnpkg.com/@sentry/node-core/-/node-core-10.44.0.tgz#d331f677b39cd42d9f0dcbbc7e1c0c4cfa74ea9e" - integrity sha512-jUGsadMrvZ08UMbqJBfjFFMk1k3VbyxfUypf0iDGGgyLmuHotYQPo/5aND+o2KxMDXR60LwcQrMoZFpanK6jXQ== - dependencies: - "@sentry/core" "10.44.0" - "@sentry/opentelemetry" "10.44.0" - import-in-the-middle "^3.0.0" - -"@sentry/node@10.44.0": - version "10.44.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-10.44.0.tgz#4ff1aaceb69864b62b3e3bba7046b10c294f0c23" - integrity sha512-q+/WR9ZeF9Af8uyehOj2tQQOa7LH07mJfOuDus5X6G6cLuugdRUGUBB5Qhw+J/ULSxbzGADBZv6AYOyoGaNx7w== - dependencies: - "@fastify/otel" "0.17.1" - "@opentelemetry/api" "^1.9.0" - "@opentelemetry/context-async-hooks" "^2.6.0" - "@opentelemetry/core" "^2.6.0" - "@opentelemetry/instrumentation" "^0.213.0" - "@opentelemetry/instrumentation-amqplib" "0.60.0" - "@opentelemetry/instrumentation-connect" "0.56.0" - "@opentelemetry/instrumentation-dataloader" "0.30.0" - "@opentelemetry/instrumentation-express" "0.61.0" - "@opentelemetry/instrumentation-fs" "0.32.0" - "@opentelemetry/instrumentation-generic-pool" "0.56.0" - "@opentelemetry/instrumentation-graphql" "0.61.0" - "@opentelemetry/instrumentation-hapi" "0.59.0" - "@opentelemetry/instrumentation-http" "0.213.0" - "@opentelemetry/instrumentation-ioredis" "0.61.0" - "@opentelemetry/instrumentation-kafkajs" "0.22.0" - "@opentelemetry/instrumentation-knex" "0.57.0" - "@opentelemetry/instrumentation-koa" "0.61.0" - "@opentelemetry/instrumentation-lru-memoizer" "0.57.0" - "@opentelemetry/instrumentation-mongodb" "0.66.0" - "@opentelemetry/instrumentation-mongoose" "0.59.0" - "@opentelemetry/instrumentation-mysql" "0.59.0" - "@opentelemetry/instrumentation-mysql2" "0.59.0" - "@opentelemetry/instrumentation-pg" "0.65.0" - "@opentelemetry/instrumentation-redis" "0.61.0" - "@opentelemetry/instrumentation-tedious" "0.32.0" - "@opentelemetry/instrumentation-undici" "0.23.0" - "@opentelemetry/resources" "^2.6.0" - "@opentelemetry/sdk-trace-base" "^2.6.0" - "@opentelemetry/semantic-conventions" "^1.40.0" - "@prisma/instrumentation" "7.4.2" - "@sentry/core" "10.44.0" - "@sentry/node-core" "10.44.0" - "@sentry/opentelemetry" "10.44.0" - import-in-the-middle "^3.0.0" - -"@sentry/opentelemetry@10.44.0": - version "10.44.0" - resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-10.44.0.tgz#4b5880597c2f35942170fcaaecb10e12086b151f" - integrity sha512-zP4vP8tBxjlmxQ4VcWOwZ0b3lPUxlYPg9FqJwANm9SRJN+7V5psm8TIaAtu9uqtIcJMRHdXkOM4cAggNiLk0KA== - dependencies: - "@sentry/core" "10.44.0" - "@sentry/rollup-plugin@5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@sentry/rollup-plugin/-/rollup-plugin-5.1.0.tgz#16109d796dc3ed49dfeda53c804792b9e4d0fd36" From 3e658e3da79f344767b06366714ed0b0805253d5 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 11:39:56 -0400 Subject: [PATCH 14/21] chore: update tests and added node variant --- .../test-applications/bun-elysia/package.json | 16 +++++++++++++++- .../bun-elysia/playwright.config.mjs | 4 +++- .../bun-elysia/tests/errors.test.ts | 8 ++++---- packages/elysia/.oxlintrc.json | 2 +- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/package.json b/dev-packages/e2e-tests/test-applications/bun-elysia/package.json index 77fd6e13c0cb..8cc2b03cb73a 100644 --- a/dev-packages/e2e-tests/test-applications/bun-elysia/package.json +++ b/dev-packages/e2e-tests/test-applications/bun-elysia/package.json @@ -2,12 +2,16 @@ "name": "bun-elysia-app", "version": "1.0.0", "private": true, + "type": "module", "scripts": { "start": "bun src/app.ts", + "start:node": "node src/app.ts", "test": "playwright test", "clean": "npx rimraf node_modules pnpm-lock.yaml", "test:build": "pnpm install", - "test:assert": "pnpm test" + "test:build-node": "pnpm install", + "test:assert": "pnpm test", + "test:assert-node": "USE_NODE=true pnpm test" }, "dependencies": { "@elysiajs/opentelemetry": "^1.4.0", @@ -21,5 +25,15 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "pnpm test:build-node", + "assert-command": "pnpm test:assert-node", + "label": "bun-elysia (node)" + } + ], + "optionalVariants": [] } } diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/bun-elysia/playwright.config.mjs index e684456a1896..012ee3b2baa3 100644 --- a/dev-packages/e2e-tests/test-applications/bun-elysia/playwright.config.mjs +++ b/dev-packages/e2e-tests/test-applications/bun-elysia/playwright.config.mjs @@ -1,7 +1,9 @@ import { getPlaywrightConfig } from '@sentry-internal/test-utils'; +const isNode = process.env.USE_NODE === 'true'; + const config = getPlaywrightConfig({ - startCommand: `bun src/app.ts`, + startCommand: isNode ? 'node src/app.ts' : 'bun src/app.ts', }); export default config; diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/bun-elysia/tests/errors.test.ts index 1dc7a4e5c7c8..37bc0976bbd6 100644 --- a/dev-packages/e2e-tests/test-applications/bun-elysia/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/bun-elysia/tests/errors.test.ts @@ -14,7 +14,7 @@ test('Captures an error thrown in a route handler', async ({ baseURL, request }) const exception = errorEvent.exception?.values?.[0]; expect(exception?.value).toBe('This is an exception with id 123'); expect(exception?.mechanism).toEqual({ - type: 'elysia', + type: 'auto.http.elysia.on_error', handled: false, }); @@ -69,7 +69,7 @@ test('Captures errors even when status is <= 299 in error handler', async ({ bas expect(errorEvent.exception?.values?.[0]?.value).toBe('Error with 200 status'); expect(errorEvent.exception?.values?.[0]?.mechanism).toEqual({ - type: 'elysia', + type: 'auto.http.elysia.on_error', handled: false, }); }); @@ -85,7 +85,7 @@ test('Captures POST route errors', async ({ baseURL, request }) => { expect(errorEvent.exception?.values?.[0]?.value).toBe('Post error'); expect(errorEvent.exception?.values?.[0]?.mechanism).toEqual({ - type: 'elysia', + type: 'auto.http.elysia.on_error', handled: false, }); }); @@ -102,7 +102,7 @@ test('Captures thrown string errors', async ({ baseURL, request }) => { expect(errorEvent.exception?.values?.[0]?.value).toBe('String error message'); expect(errorEvent.exception?.values?.[0]?.mechanism).toEqual( expect.objectContaining({ - type: 'elysia', + type: 'auto.http.elysia.on_error', handled: false, }), ); diff --git a/packages/elysia/.oxlintrc.json b/packages/elysia/.oxlintrc.json index 942f110037c2..d38bbcf5c769 100644 --- a/packages/elysia/.oxlintrc.json +++ b/packages/elysia/.oxlintrc.json @@ -1,4 +1,4 @@ { "$schema": "../../node_modules/oxlint/configuration_schema.json", - "extends": ["../../.oxlintrc.json"], + "extends": ["../../.oxlintrc.json"] } From 8adbe732fcf0c2074d22d84be11b67b2c186550c Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 11:44:44 -0400 Subject: [PATCH 15/21] fix: avoid touching bun namespace for downstream packages --- packages/bun/src/sdk.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bun/src/sdk.ts b/packages/bun/src/sdk.ts index 7b79fa9383d6..6f9c06fdf88b 100644 --- a/packages/bun/src/sdk.ts +++ b/packages/bun/src/sdk.ts @@ -105,7 +105,7 @@ export function init(userOptions: BunOptions = {}): NodeClient | undefined { const options = { ...userOptions, platform: 'javascript', - runtime: { name: 'bun', version: Bun.version }, + runtime: { name: 'bun', version: typeof Bun !== 'undefined' ? Bun.version : 'unknown' }, serverName: userOptions.serverName || global.process.env.SENTRY_NAME || os.hostname(), }; From e9f96576ee5b6645e1dd4b650c181f726f50e04e Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 11:52:34 -0400 Subject: [PATCH 16/21] test: added an eslysia node app --- .github/workflows/build.yml | 2 +- .../{bun-elysia => elysia-bun}/.gitignore | 0 .../{bun-elysia => elysia-bun}/.npmrc | 0 .../{bun-elysia => elysia-bun}/package.json | 16 +- .../playwright.config.mjs | 4 +- .../{bun-elysia => elysia-bun}/src/app.ts | 0 .../start-event-proxy.mjs | 2 +- .../tests/errors.test.ts | 12 +- .../tests/isolation.test.ts | 0 .../tests/propagation.test.ts | 8 +- .../tests/transactions.test.ts | 18 +- .../{bun-elysia => elysia-bun}/tsconfig.json | 0 .../test-applications/elysia-node/.gitignore | 1 + .../test-applications/elysia-node/.npmrc | 2 + .../elysia-node/package.json | 28 +++ .../elysia-node/playwright.config.mjs | 7 + .../test-applications/elysia-node/src/app.ts | 142 ++++++++++++ .../elysia-node/start-event-proxy.mjs | 6 + .../elysia-node/tests/errors.test.ts | 109 +++++++++ .../elysia-node/tests/isolation.test.ts | 30 +++ .../elysia-node/tests/propagation.test.ts | 113 ++++++++++ .../elysia-node/tests/transactions.test.ts | 211 ++++++++++++++++++ .../elysia-node/tsconfig.json | 11 + 23 files changed, 684 insertions(+), 38 deletions(-) rename dev-packages/e2e-tests/test-applications/{bun-elysia => elysia-bun}/.gitignore (100%) rename dev-packages/e2e-tests/test-applications/{bun-elysia => elysia-bun}/.npmrc (100%) rename dev-packages/e2e-tests/test-applications/{bun-elysia => elysia-bun}/package.json (61%) rename dev-packages/e2e-tests/test-applications/{bun-elysia => elysia-bun}/playwright.config.mjs (54%) rename dev-packages/e2e-tests/test-applications/{bun-elysia => elysia-bun}/src/app.ts (100%) rename dev-packages/e2e-tests/test-applications/{bun-elysia => elysia-bun}/start-event-proxy.mjs (77%) rename dev-packages/e2e-tests/test-applications/{bun-elysia => elysia-bun}/tests/errors.test.ts (89%) rename dev-packages/e2e-tests/test-applications/{bun-elysia => elysia-bun}/tests/isolation.test.ts (100%) rename dev-packages/e2e-tests/test-applications/{bun-elysia => elysia-bun}/tests/propagation.test.ts (91%) rename dev-packages/e2e-tests/test-applications/{bun-elysia => elysia-bun}/tests/transactions.test.ts (92%) rename dev-packages/e2e-tests/test-applications/{bun-elysia => elysia-bun}/tsconfig.json (100%) create mode 100644 dev-packages/e2e-tests/test-applications/elysia-node/.gitignore create mode 100644 dev-packages/e2e-tests/test-applications/elysia-node/.npmrc create mode 100644 dev-packages/e2e-tests/test-applications/elysia-node/package.json create mode 100644 dev-packages/e2e-tests/test-applications/elysia-node/playwright.config.mjs create mode 100644 dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts create mode 100644 dev-packages/e2e-tests/test-applications/elysia-node/start-event-proxy.mjs create mode 100644 dev-packages/e2e-tests/test-applications/elysia-node/tests/errors.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/elysia-node/tests/isolation.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/elysia-node/tests/propagation.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/elysia-node/tests/transactions.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/elysia-node/tsconfig.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ed3f2d8678b8..dea6b4802dc5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -961,7 +961,7 @@ jobs: with: node-version-file: 'dev-packages/e2e-tests/test-applications/${{ matrix.test-application }}/package.json' - name: Set up Bun - if: contains(fromJSON('["node-exports-test-app","nextjs-16-bun", "bun-elysia"]'), matrix.test-application) + if: contains(fromJSON('["node-exports-test-app","nextjs-16-bun", "elysia-bun"]'), matrix.test-application) uses: oven-sh/setup-bun@v2 - name: Set up AWS SAM if: matrix.test-application == 'aws-serverless' diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/.gitignore b/dev-packages/e2e-tests/test-applications/elysia-bun/.gitignore similarity index 100% rename from dev-packages/e2e-tests/test-applications/bun-elysia/.gitignore rename to dev-packages/e2e-tests/test-applications/elysia-bun/.gitignore diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/.npmrc b/dev-packages/e2e-tests/test-applications/elysia-bun/.npmrc similarity index 100% rename from dev-packages/e2e-tests/test-applications/bun-elysia/.npmrc rename to dev-packages/e2e-tests/test-applications/elysia-bun/.npmrc diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/package.json b/dev-packages/e2e-tests/test-applications/elysia-bun/package.json similarity index 61% rename from dev-packages/e2e-tests/test-applications/bun-elysia/package.json rename to dev-packages/e2e-tests/test-applications/elysia-bun/package.json index 8cc2b03cb73a..e41f24030046 100644 --- a/dev-packages/e2e-tests/test-applications/bun-elysia/package.json +++ b/dev-packages/e2e-tests/test-applications/elysia-bun/package.json @@ -1,5 +1,5 @@ { - "name": "bun-elysia-app", + "name": "elysia-bun-app", "version": "1.0.0", "private": true, "type": "module", @@ -9,9 +9,7 @@ "test": "playwright test", "clean": "npx rimraf node_modules pnpm-lock.yaml", "test:build": "pnpm install", - "test:build-node": "pnpm install", - "test:assert": "pnpm test", - "test:assert-node": "USE_NODE=true pnpm test" + "test:assert": "pnpm test" }, "dependencies": { "@elysiajs/opentelemetry": "^1.4.0", @@ -25,15 +23,5 @@ }, "volta": { "extends": "../../package.json" - }, - "sentryTest": { - "variants": [ - { - "build-command": "pnpm test:build-node", - "assert-command": "pnpm test:assert-node", - "label": "bun-elysia (node)" - } - ], - "optionalVariants": [] } } diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/elysia-bun/playwright.config.mjs similarity index 54% rename from dev-packages/e2e-tests/test-applications/bun-elysia/playwright.config.mjs rename to dev-packages/e2e-tests/test-applications/elysia-bun/playwright.config.mjs index 012ee3b2baa3..44d3b834833d 100644 --- a/dev-packages/e2e-tests/test-applications/bun-elysia/playwright.config.mjs +++ b/dev-packages/e2e-tests/test-applications/elysia-bun/playwright.config.mjs @@ -1,9 +1,7 @@ import { getPlaywrightConfig } from '@sentry-internal/test-utils'; -const isNode = process.env.USE_NODE === 'true'; - const config = getPlaywrightConfig({ - startCommand: isNode ? 'node src/app.ts' : 'bun src/app.ts', + startCommand: 'bun src/app.ts', }); export default config; diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/src/app.ts b/dev-packages/e2e-tests/test-applications/elysia-bun/src/app.ts similarity index 100% rename from dev-packages/e2e-tests/test-applications/bun-elysia/src/app.ts rename to dev-packages/e2e-tests/test-applications/elysia-bun/src/app.ts diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/elysia-bun/start-event-proxy.mjs similarity index 77% rename from dev-packages/e2e-tests/test-applications/bun-elysia/start-event-proxy.mjs rename to dev-packages/e2e-tests/test-applications/elysia-bun/start-event-proxy.mjs index 400ce8a5e380..7519e8a3f650 100644 --- a/dev-packages/e2e-tests/test-applications/bun-elysia/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/elysia-bun/start-event-proxy.mjs @@ -2,5 +2,5 @@ import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, - proxyServerName: 'bun-elysia', + proxyServerName: 'elysia-bun', }); diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/elysia-bun/tests/errors.test.ts similarity index 89% rename from dev-packages/e2e-tests/test-applications/bun-elysia/tests/errors.test.ts rename to dev-packages/e2e-tests/test-applications/elysia-bun/tests/errors.test.ts index 37bc0976bbd6..8bd544e6f9c2 100644 --- a/dev-packages/e2e-tests/test-applications/bun-elysia/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/elysia-bun/tests/errors.test.ts @@ -2,7 +2,7 @@ import { expect, test } from '@playwright/test'; import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Captures an error thrown in a route handler', async ({ baseURL, request }) => { - const errorEventPromise = waitForError('bun-elysia', event => { + const errorEventPromise = waitForError('elysia-bun', event => { return !event.type && event.exception?.values?.[0]?.value === 'This is an exception with id 123'; }); @@ -29,7 +29,7 @@ test('Captures an error thrown in a route handler', async ({ baseURL, request }) }); test('Error event includes request metadata', async ({ baseURL, request }) => { - const errorEventPromise = waitForError('bun-elysia', event => { + const errorEventPromise = waitForError('elysia-bun', event => { return !event.type && event.exception?.values?.[0]?.value === 'This is an exception with id 456'; }); @@ -47,7 +47,7 @@ test('Error event includes request metadata', async ({ baseURL, request }) => { }); test('Does not capture errors for 4xx responses', async ({ baseURL, request }) => { - const transactionPromise = waitForTransaction('bun-elysia', transactionEvent => { + const transactionPromise = waitForTransaction('elysia-bun', transactionEvent => { return transactionEvent?.transaction === 'GET /test-4xx'; }); @@ -59,7 +59,7 @@ test('Does not capture errors for 4xx responses', async ({ baseURL, request }) = }); test('Captures errors even when status is <= 299 in error handler', async ({ baseURL, request }) => { - const errorEventPromise = waitForError('bun-elysia', event => { + const errorEventPromise = waitForError('elysia-bun', event => { return !event.type && event.exception?.values?.[0]?.value === 'Error with 200 status'; }); @@ -75,7 +75,7 @@ test('Captures errors even when status is <= 299 in error handler', async ({ bas }); test('Captures POST route errors', async ({ baseURL, request }) => { - const errorEventPromise = waitForError('bun-elysia', event => { + const errorEventPromise = waitForError('elysia-bun', event => { return !event.type && event.exception?.values?.[0]?.value === 'Post error'; }); @@ -91,7 +91,7 @@ test('Captures POST route errors', async ({ baseURL, request }) => { }); test('Captures thrown string errors', async ({ baseURL, request }) => { - const errorEventPromise = waitForError('bun-elysia', event => { + const errorEventPromise = waitForError('elysia-bun', event => { return !event.type && event.exception?.values?.[0]?.value === 'String error message'; }); diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/tests/isolation.test.ts b/dev-packages/e2e-tests/test-applications/elysia-bun/tests/isolation.test.ts similarity index 100% rename from dev-packages/e2e-tests/test-applications/bun-elysia/tests/isolation.test.ts rename to dev-packages/e2e-tests/test-applications/elysia-bun/tests/isolation.test.ts diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/tests/propagation.test.ts b/dev-packages/e2e-tests/test-applications/elysia-bun/tests/propagation.test.ts similarity index 91% rename from dev-packages/e2e-tests/test-applications/bun-elysia/tests/propagation.test.ts rename to dev-packages/e2e-tests/test-applications/elysia-bun/tests/propagation.test.ts index b7af9b893a6d..c07dea3c9dc6 100644 --- a/dev-packages/e2e-tests/test-applications/bun-elysia/tests/propagation.test.ts +++ b/dev-packages/e2e-tests/test-applications/elysia-bun/tests/propagation.test.ts @@ -21,14 +21,14 @@ test('Includes sentry-trace and baggage in response headers', async ({ baseURL } test.fixme('Propagates trace for outgoing fetch requests', async ({ baseURL }) => { const id = randomUUID(); - const inboundTransactionPromise = waitForTransaction('bun-elysia', transactionEvent => { + const inboundTransactionPromise = waitForTransaction('elysia-bun', transactionEvent => { return ( transactionEvent.contexts?.trace?.op === 'http.server' && transactionEvent.transaction === 'GET /test-inbound-headers/:id' ); }); - const outboundTransactionPromise = waitForTransaction('bun-elysia', transactionEvent => { + const outboundTransactionPromise = waitForTransaction('elysia-bun', transactionEvent => { return ( transactionEvent.contexts?.trace?.op === 'http.server' && transactionEvent.transaction === 'GET /test-outgoing-fetch/:id' @@ -65,7 +65,7 @@ test.fixme('Propagates trace for outgoing fetch requests', async ({ baseURL }) = }); test.fixme('Propagates trace for outgoing fetch to external allowed URL', async ({ baseURL }) => { - const inboundTransactionPromise = waitForTransaction('bun-elysia', transactionEvent => { + const inboundTransactionPromise = waitForTransaction('elysia-bun', transactionEvent => { return ( transactionEvent.contexts?.trace?.op === 'http.server' && transactionEvent.transaction === 'GET /test-outgoing-fetch-external-allowed' @@ -95,7 +95,7 @@ test.fixme('Propagates trace for outgoing fetch to external allowed URL', async }); test('Does not propagate outgoing fetch requests not covered by tracePropagationTargets', async ({ baseURL }) => { - const inboundTransactionPromise = waitForTransaction('bun-elysia', transactionEvent => { + const inboundTransactionPromise = waitForTransaction('elysia-bun', transactionEvent => { return ( transactionEvent.contexts?.trace?.op === 'http.server' && transactionEvent.transaction === 'GET /test-outgoing-fetch-external-disallowed' diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/elysia-bun/tests/transactions.test.ts similarity index 92% rename from dev-packages/e2e-tests/test-applications/bun-elysia/tests/transactions.test.ts rename to dev-packages/e2e-tests/test-applications/elysia-bun/tests/transactions.test.ts index fd3166b2fea1..e0f05a1be483 100644 --- a/dev-packages/e2e-tests/test-applications/bun-elysia/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/elysia-bun/tests/transactions.test.ts @@ -2,7 +2,7 @@ import { expect, test } from '@playwright/test'; import { waitForTransaction } from '@sentry-internal/test-utils'; test('Sends a transaction for a successful route', async ({ baseURL, request }) => { - const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + const transactionEventPromise = waitForTransaction('elysia-bun', transactionEvent => { return ( transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /test-success' ); @@ -33,7 +33,7 @@ test('Sends a transaction for a successful route', async ({ baseURL, request }) }); test('Sends a transaction with parameterized route name', async ({ baseURL, request }) => { - const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + const transactionEventPromise = waitForTransaction('elysia-bun', transactionEvent => { return ( transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /test-param/:param' @@ -49,7 +49,7 @@ test('Sends a transaction with parameterized route name', async ({ baseURL, requ }); test('Sends a transaction with multiple parameterized segments', async ({ baseURL, request }) => { - const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + const transactionEventPromise = waitForTransaction('elysia-bun', transactionEvent => { return ( transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /test-multi-param/:param1/:param2' @@ -65,7 +65,7 @@ test('Sends a transaction with multiple parameterized segments', async ({ baseUR }); test('Sends a transaction for an errored route', async ({ baseURL, request }) => { - const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + const transactionEventPromise = waitForTransaction('elysia-bun', transactionEvent => { return ( transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /test-exception/:id' @@ -81,7 +81,7 @@ test('Sends a transaction for an errored route', async ({ baseURL, request }) => }); test('Includes manually started spans with parent-child relationship', async ({ baseURL, request }) => { - const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + const transactionEventPromise = waitForTransaction('elysia-bun', transactionEvent => { return ( transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /test-transaction' @@ -113,7 +113,7 @@ test('Includes manually started spans with parent-child relationship', async ({ }); test('Creates lifecycle spans for Elysia hooks', async ({ baseURL, request }) => { - const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + const transactionEventPromise = waitForTransaction('elysia-bun', transactionEvent => { return ( transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /test-success' ); @@ -139,7 +139,7 @@ test('Creates lifecycle spans for Elysia hooks', async ({ baseURL, request }) => }); test('Filters out empty anonymous Elysia spans but keeps all other spans', async ({ baseURL, request }) => { - const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + const transactionEventPromise = waitForTransaction('elysia-bun', transactionEvent => { return ( transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /test-success' ); @@ -160,7 +160,7 @@ test('Filters out empty anonymous Elysia spans but keeps all other spans', async }); test('Creates lifecycle spans for route-specific middleware', async ({ baseURL, request }) => { - const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + const transactionEventPromise = waitForTransaction('elysia-bun', transactionEvent => { return ( transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /with-middleware/test' @@ -183,7 +183,7 @@ test('Creates lifecycle spans for route-specific middleware', async ({ baseURL, }); test('Captures request metadata for POST requests', async ({ baseURL, request }) => { - const transactionEventPromise = waitForTransaction('bun-elysia', transactionEvent => { + const transactionEventPromise = waitForTransaction('elysia-bun', transactionEvent => { return ( transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'POST /test-post' ); diff --git a/dev-packages/e2e-tests/test-applications/bun-elysia/tsconfig.json b/dev-packages/e2e-tests/test-applications/elysia-bun/tsconfig.json similarity index 100% rename from dev-packages/e2e-tests/test-applications/bun-elysia/tsconfig.json rename to dev-packages/e2e-tests/test-applications/elysia-bun/tsconfig.json diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/.gitignore b/dev-packages/e2e-tests/test-applications/elysia-node/.gitignore new file mode 100644 index 000000000000..1521c8b7652b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/elysia-node/.gitignore @@ -0,0 +1 @@ +dist diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/.npmrc b/dev-packages/e2e-tests/test-applications/elysia-node/.npmrc new file mode 100644 index 000000000000..070f80f05092 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/elysia-node/.npmrc @@ -0,0 +1,2 @@ +@sentry:registry=http://127.0.0.1:4873 +@sentry-internal:registry=http://127.0.0.1:4873 diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/package.json b/dev-packages/e2e-tests/test-applications/elysia-node/package.json new file mode 100644 index 000000000000..3570307e0e61 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/elysia-node/package.json @@ -0,0 +1,28 @@ +{ + "name": "elysia-node-app", + "version": "1.0.0", + "private": true, + "type": "module", + "scripts": { + "start": "bun src/app.ts", + "start:node": "node src/app.ts", + "test": "playwright test", + "clean": "npx rimraf node_modules pnpm-lock.yaml", + "test:build": "pnpm install", + "test:assert": "pnpm test" + }, + "dependencies": { + "@elysiajs/opentelemetry": "^1.4.0", + "@sentry/elysia": "latest || *", + "elysia": "^1.4.0", + "@elysiajs/node": "^1.4.5" + }, + "devDependencies": { + "@playwright/test": "~1.56.0", + "@sentry-internal/test-utils": "link:../../../test-utils", + "bun-types": "^1.2.9" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/elysia-node/playwright.config.mjs new file mode 100644 index 000000000000..7b08eab8ba80 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/elysia-node/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: 'node src/app.ts', +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts b/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts new file mode 100644 index 000000000000..db6a5fff8bd1 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts @@ -0,0 +1,142 @@ +import * as Sentry from '@sentry/elysia'; +import { Elysia } from 'elysia'; + +Sentry.init({ + environment: 'qa', // dynamic sampling bias to keep transactions + dsn: process.env.E2E_TEST_DSN, + tunnel: `http://localhost:3031/`, // proxy server + tracesSampleRate: 1, + tracePropagationTargets: ['http://localhost:3030', '/external-allowed'], +}); + +const app = Sentry.withElysia(new Elysia()); + +// Simple success route +app.get('/test-success', () => ({ version: 'v1' })); + +// Parameterized route +app.get('/test-param/:param', ({ params }) => ({ paramWas: params.param })); + +// Multiple params +app.get('/test-multi-param/:param1/:param2', ({ params }) => ({ + param1: params.param1, + param2: params.param2, +})); + +// Route that throws an error (will be caught by onError) +app.get('/test-exception/:id', ({ params }) => { + throw new Error(`This is an exception with id ${params.id}`); +}); + +// Route with a custom span +app.get('/test-transaction', () => { + Sentry.startSpan({ name: 'test-span' }, () => { + Sentry.startSpan({ name: 'child-span' }, () => {}); + }); + return { status: 'ok' }; +}); + +// Route with specific middleware via .guard or .use +app.group('/with-middleware', app => + app + .onBeforeHandle(() => { + // This is a route-specific middleware + }) + .get('/test', () => ({ middleware: true })), +); + +// Error with specific status code +app.post('/test-post-error', () => { + throw new Error('Post error'); +}); + +// Route that returns a non-500 error +app.get('/test-4xx', ({ set }) => { + set.status = 400; + return { error: 'Bad Request' }; +}); + +// Error that reaches the error handler with status still set to 200 (unusual, should still be captured) +app.get('/test-error-with-200-status', ({ set }) => { + set.status = 200; + throw new Error('Error with 200 status'); +}); + +// POST route that echoes body +app.post('/test-post', ({ body }) => ({ status: 'ok', body })); + +// Route that returns inbound headers (for propagation tests) +app.get('/test-inbound-headers/:id', ({ params, request }) => { + const headers = Object.fromEntries(request.headers.entries()); + return { headers, id: params.id }; +}); + +// Outgoing fetch propagation +app.get('/test-outgoing-fetch/:id', async ({ params }) => { + const id = params.id; + const response = await fetch(`http://localhost:3030/test-inbound-headers/${id}`); + const data = await response.json(); + return data; +}); + +// Outgoing fetch to external (allowed by tracePropagationTargets) +app.get('/test-outgoing-fetch-external-allowed', async () => { + const response = await fetch(`http://localhost:3040/external-allowed`); + const data = await response.json(); + return data; +}); + +// Outgoing fetch to external (disallowed by tracePropagationTargets) +app.get('/test-outgoing-fetch-external-disallowed', async () => { + const response = await fetch(`http://localhost:3040/external-disallowed`); + const data = await response.json(); + return data; +}); + +// Route that throws a string (not an Error object) +app.get('/test-string-error', () => { + // eslint-disable-next-line no-throw-literal + throw 'String error message'; +}); + +// Route for concurrent isolation tests — returns scope data in response +app.get('/test-isolation/:userId', async ({ params }) => { + Sentry.setUser({ id: params.userId }); + Sentry.setTag('user_id', params.userId); + + // Simulate async work to increase overlap between concurrent requests + await new Promise(resolve => setTimeout(resolve, 200)); + + return { + userId: params.userId, + isolationScopeUserId: Sentry.getIsolationScope().getUser()?.id, + isolationScopeTag: Sentry.getIsolationScope().getScopeData().tags?.user_id, + }; +}); + +// Flush route for waiting on events +app.get('/flush', async () => { + await Sentry.flush(); + return { ok: true }; +}); + +app.listen(3030, () => { + console.log('Elysia app listening on port 3030'); +}); + +// Second app for external propagation tests +const app2 = new Elysia(); + +app2.get('/external-allowed', ({ request }) => { + const headers = Object.fromEntries(request.headers.entries()); + return { headers, route: '/external-allowed' }; +}); + +app2.get('/external-disallowed', ({ request }) => { + const headers = Object.fromEntries(request.headers.entries()); + return { headers, route: '/external-disallowed' }; +}); + +app2.listen(3040, () => { + console.log('External app listening on port 3040'); +}); diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/elysia-node/start-event-proxy.mjs new file mode 100644 index 000000000000..85dfff25b5a6 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/elysia-node/start-event-proxy.mjs @@ -0,0 +1,6 @@ +import { startEventProxyServer } from '@sentry-internal/test-utils'; + +startEventProxyServer({ + port: 3031, + proxyServerName: 'elysia-node', +}); diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/elysia-node/tests/errors.test.ts new file mode 100644 index 000000000000..aac83b65e703 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/elysia-node/tests/errors.test.ts @@ -0,0 +1,109 @@ +import { expect, test } from '@playwright/test'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; + +test('Captures an error thrown in a route handler', async ({ baseURL, request }) => { + const errorEventPromise = waitForError('elysia-node', event => { + return !event.type && event.exception?.values?.[0]?.value === 'This is an exception with id 123'; + }); + + await request.get(`${baseURL}/test-exception/123`); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.exception?.values).toHaveLength(1); + const exception = errorEvent.exception?.values?.[0]; + expect(exception?.value).toBe('This is an exception with id 123'); + expect(exception?.mechanism).toEqual({ + type: 'auto.http.elysia.on_error', + handled: false, + }); + + expect(errorEvent.transaction).toEqual('GET /test-exception/:id'); + + expect(errorEvent.contexts?.trace).toEqual( + expect.objectContaining({ + trace_id: expect.stringMatching(/[a-f0-9]{32}/), + span_id: expect.stringMatching(/[a-f0-9]{16}/), + }), + ); +}); + +test('Error event includes request metadata', async ({ baseURL, request }) => { + const errorEventPromise = waitForError('elysia-node', event => { + return !event.type && event.exception?.values?.[0]?.value === 'This is an exception with id 456'; + }); + + await request.get(`${baseURL}/test-exception/456`); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.request).toEqual( + expect.objectContaining({ + method: 'GET', + url: expect.stringContaining('/test-exception/456'), + headers: expect.any(Object), + }), + ); +}); + +test('Does not capture errors for 4xx responses', async ({ baseURL, request }) => { + const transactionPromise = waitForTransaction('elysia-node', transactionEvent => { + return transactionEvent?.transaction === 'GET /test-4xx'; + }); + + const response = await request.get(`${baseURL}/test-4xx`); + // Wait for the transaction to ensure the request was processed + await transactionPromise; + + expect(response.status()).toBe(400); +}); + +test('Captures errors even when status is <= 299 in error handler', async ({ baseURL, request }) => { + const errorEventPromise = waitForError('elysia-node', event => { + return !event.type && event.exception?.values?.[0]?.value === 'Error with 200 status'; + }); + + await request.get(`${baseURL}/test-error-with-200-status`); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.exception?.values?.[0]?.value).toBe('Error with 200 status'); + expect(errorEvent.exception?.values?.[0]?.mechanism).toEqual({ + type: 'auto.http.elysia.on_error', + handled: false, + }); +}); + +test('Captures POST route errors', async ({ baseURL, request }) => { + const errorEventPromise = waitForError('elysia-node', event => { + return !event.type && event.exception?.values?.[0]?.value === 'Post error'; + }); + + await request.post(`${baseURL}/test-post-error`); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.exception?.values?.[0]?.value).toBe('Post error'); + expect(errorEvent.exception?.values?.[0]?.mechanism).toEqual({ + type: 'auto.http.elysia.on_error', + handled: false, + }); +}); + +test('Captures thrown string errors', async ({ baseURL, request }) => { + const errorEventPromise = waitForError('elysia-node', event => { + return !event.type && event.exception?.values?.[0]?.value === 'String error message'; + }); + + await request.get(`${baseURL}/test-string-error`); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.exception?.values?.[0]?.value).toBe('String error message'); + expect(errorEvent.exception?.values?.[0]?.mechanism).toEqual( + expect.objectContaining({ + type: 'auto.http.elysia.on_error', + handled: false, + }), + ); +}); diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/tests/isolation.test.ts b/dev-packages/e2e-tests/test-applications/elysia-node/tests/isolation.test.ts new file mode 100644 index 000000000000..3bdc1cc2e99d --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/elysia-node/tests/isolation.test.ts @@ -0,0 +1,30 @@ +import { expect, test } from '@playwright/test'; + +// The Elysia integration currently does not fork isolation scopes per request, +// so `setUser`/`setTag` on the isolation scope leaks between concurrent requests. +// This test documents the expected behavior once per-request isolation is implemented. +test.fixme('Concurrent requests have isolated scope data', async ({ baseURL }) => { + // Fire 3 concurrent requests with different user IDs + const [response1, response2, response3] = await Promise.all([ + fetch(`${baseURL}/test-isolation/user-1`), + fetch(`${baseURL}/test-isolation/user-2`), + fetch(`${baseURL}/test-isolation/user-3`), + ]); + + const data1 = await response1.json(); + const data2 = await response2.json(); + const data3 = await response3.json(); + + // Each response should have its own user ID — no leaking between requests + expect(data1.userId).toBe('user-1'); + expect(data1.isolationScopeUserId).toBe('user-1'); + expect(data1.isolationScopeTag).toBe('user-1'); + + expect(data2.userId).toBe('user-2'); + expect(data2.isolationScopeUserId).toBe('user-2'); + expect(data2.isolationScopeTag).toBe('user-2'); + + expect(data3.userId).toBe('user-3'); + expect(data3.isolationScopeUserId).toBe('user-3'); + expect(data3.isolationScopeTag).toBe('user-3'); +}); diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/tests/propagation.test.ts b/dev-packages/e2e-tests/test-applications/elysia-node/tests/propagation.test.ts new file mode 100644 index 000000000000..14bdbdf7ca6b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/elysia-node/tests/propagation.test.ts @@ -0,0 +1,113 @@ +import { randomUUID } from 'node:crypto'; +import { expect, test } from '@playwright/test'; +import { waitForTransaction } from '@sentry-internal/test-utils'; + +test('Includes sentry-trace and baggage in response headers', async ({ baseURL }) => { + const response = await fetch(`${baseURL}/test-success`); + + const sentryTrace = response.headers.get('sentry-trace'); + const baggage = response.headers.get('baggage'); + + expect(sentryTrace).toMatch(/[a-f0-9]{32}-[a-f0-9]{16}-[01]/); + expect(baggage).toContain('sentry-environment=qa'); + expect(baggage).toContain('sentry-trace_id='); +}); + +// Bun's native fetch does not emit undici diagnostics channels, +// so the nativeNodeFetchIntegration cannot inject sentry-trace/baggage headers. +// These tests document the desired behavior and will pass once Bun adds support +// for undici diagnostics channels or an alternative propagation mechanism is added. + +test.fixme('Propagates trace for outgoing fetch requests', async ({ baseURL }) => { + const id = randomUUID(); + + const inboundTransactionPromise = waitForTransaction('elysia-node', transactionEvent => { + return ( + transactionEvent.contexts?.trace?.op === 'http.server' && + transactionEvent.transaction === 'GET /test-inbound-headers/:id' + ); + }); + + const outboundTransactionPromise = waitForTransaction('elysia-node', transactionEvent => { + return ( + transactionEvent.contexts?.trace?.op === 'http.server' && + transactionEvent.transaction === 'GET /test-outgoing-fetch/:id' + ); + }); + + const response = await fetch(`${baseURL}/test-outgoing-fetch/${id}`); + const data = await response.json(); + + const inboundTransaction = await inboundTransactionPromise; + const outboundTransaction = await outboundTransactionPromise; + + const traceId = outboundTransaction?.contexts?.trace?.trace_id; + expect(traceId).toEqual(expect.any(String)); + + // Verify sentry-trace header was propagated to the inbound request + const inboundHeaderSentryTrace = data.headers?.['sentry-trace']; + const inboundHeaderBaggage = data.headers?.['baggage']; + + expect(inboundHeaderSentryTrace).toMatch(new RegExp(`^${traceId}-[a-f0-9]{16}-1$`)); + expect(inboundHeaderBaggage).toBeDefined(); + + const baggage = (inboundHeaderBaggage || '').split(','); + expect(baggage).toEqual( + expect.arrayContaining([ + 'sentry-environment=qa', + `sentry-trace_id=${traceId}`, + expect.stringMatching(/sentry-public_key=/), + ]), + ); + + // Both transactions should share the same trace ID + expect(inboundTransaction.contexts?.trace?.trace_id).toBe(traceId); +}); + +test.fixme('Propagates trace for outgoing fetch to external allowed URL', async ({ baseURL }) => { + const inboundTransactionPromise = waitForTransaction('elysia-node', transactionEvent => { + return ( + transactionEvent.contexts?.trace?.op === 'http.server' && + transactionEvent.transaction === 'GET /test-outgoing-fetch-external-allowed' + ); + }); + + const response = await fetch(`${baseURL}/test-outgoing-fetch-external-allowed`); + const data = await response.json(); + + const inboundTransaction = await inboundTransactionPromise; + const traceId = inboundTransaction?.contexts?.trace?.trace_id; + + expect(traceId).toEqual(expect.any(String)); + + expect(data.route).toBe('/external-allowed'); + expect(data.headers?.['sentry-trace']).toMatch(/[a-f0-9]{32}-[a-f0-9]{16}-1/); + expect(data.headers?.baggage).toBeDefined(); + + const baggage = (data.headers.baggage || '').split(','); + expect(baggage).toEqual( + expect.arrayContaining([ + 'sentry-environment=qa', + `sentry-trace_id=${traceId}`, + expect.stringMatching(/sentry-public_key=/), + ]), + ); +}); + +test('Does not propagate outgoing fetch requests not covered by tracePropagationTargets', async ({ baseURL }) => { + const inboundTransactionPromise = waitForTransaction('elysia-node', transactionEvent => { + return ( + transactionEvent.contexts?.trace?.op === 'http.server' && + transactionEvent.transaction === 'GET /test-outgoing-fetch-external-disallowed' + ); + }); + + const response = await fetch(`${baseURL}/test-outgoing-fetch-external-disallowed`); + const data = await response.json(); + + await inboundTransactionPromise; + + expect(data.route).toBe('/external-disallowed'); + expect(data.headers?.['sentry-trace']).toBeUndefined(); + expect(data.headers?.baggage).toBeUndefined(); +}); diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/elysia-node/tests/transactions.test.ts new file mode 100644 index 000000000000..69ee7c48acf3 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/elysia-node/tests/transactions.test.ts @@ -0,0 +1,211 @@ +import { expect, test } from '@playwright/test'; +import { waitForTransaction } from '@sentry-internal/test-utils'; + +test('Sends a transaction for a successful route', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('elysia-node', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /test-success' + ); + }); + + await request.get(`${baseURL}/test-success`); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent).toEqual( + expect.objectContaining({ + transaction: 'GET /test-success', + type: 'transaction', + transaction_info: { + source: 'route', + }, + }), + ); + + expect(transactionEvent.contexts?.trace).toEqual( + expect.objectContaining({ + op: 'http.server', + status: 'ok', + trace_id: expect.stringMatching(/[a-f0-9]{32}/), + span_id: expect.stringMatching(/[a-f0-9]{16}/), + }), + ); +}); + +test('Sends a transaction with parameterized route name', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('elysia-node', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && + transactionEvent?.transaction === 'GET /test-param/:param' + ); + }); + + await request.get(`${baseURL}/test-param/123`); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent.transaction).toBe('GET /test-param/:param'); + expect(transactionEvent.transaction_info?.source).toBe('route'); +}); + +test('Sends a transaction with multiple parameterized segments', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('elysia-node', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && + transactionEvent?.transaction === 'GET /test-multi-param/:param1/:param2' + ); + }); + + await request.get(`${baseURL}/test-multi-param/foo/bar`); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent.transaction).toBe('GET /test-multi-param/:param1/:param2'); + expect(transactionEvent.transaction_info?.source).toBe('route'); +}); + +test('Sends a transaction for an errored route', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('elysia-node', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && + transactionEvent?.transaction === 'GET /test-exception/:id' + ); + }); + + await request.get(`${baseURL}/test-exception/777`); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent.transaction).toBe('GET /test-exception/:id'); + expect(transactionEvent.contexts?.trace?.status).toBe('internal_error'); +}); + +test('Includes manually started spans with parent-child relationship', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('elysia-node', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && + transactionEvent?.transaction === 'GET /test-transaction' + ); + }); + + await request.get(`${baseURL}/test-transaction`); + + const transactionEvent = await transactionEventPromise; + const spans = transactionEvent.spans || []; + + const testSpan = spans.find(span => span.description === 'test-span'); + const childSpan = spans.find(span => span.description === 'child-span'); + + expect(testSpan).toEqual( + expect.objectContaining({ + description: 'test-span', + origin: 'manual', + }), + ); + + expect(childSpan).toEqual( + expect.objectContaining({ + description: 'child-span', + origin: 'manual', + parent_span_id: testSpan?.span_id, + }), + ); +}); + +test('Creates lifecycle spans for Elysia hooks', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('elysia-node', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /test-success' + ); + }); + + await request.get(`${baseURL}/test-success`); + + const transactionEvent = await transactionEventPromise; + const spans = transactionEvent.spans || []; + + // Elysia should produce lifecycle spans enriched with sentry attributes + const elysiaSpans = spans.filter(span => span.origin === 'auto.http.otel.elysia'); + expect(elysiaSpans.length).toBeGreaterThan(0); + + // The Handle span should be present as a request handler + expect(spans).toContainEqual( + expect.objectContaining({ + description: 'Handle', + op: 'request_handler.elysia', + origin: 'auto.http.otel.elysia', + }), + ); +}); + +test('Filters out empty anonymous Elysia spans but keeps all other spans', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('elysia-node', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /test-success' + ); + }); + + await request.get(`${baseURL}/test-success`); + + const transactionEvent = await transactionEventPromise; + const spans = transactionEvent.spans || []; + + // Elysia produces empty anonymous spans for arrow function handlers that show up as . + // These should be filtered out by our beforeSendEvent hook. + const unknownSpans = spans.filter(span => span.description === ''); + expect(unknownSpans).toHaveLength(0); + + // But named Elysia lifecycle spans should still be present + expect(spans.filter(span => span.origin === 'auto.http.otel.elysia').length).toBeGreaterThan(0); +}); + +test('Creates lifecycle spans for route-specific middleware', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('elysia-node', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && + transactionEvent?.transaction === 'GET /with-middleware/test' + ); + }); + + await request.get(`${baseURL}/with-middleware/test`); + + const transactionEvent = await transactionEventPromise; + const spans = transactionEvent.spans || []; + + // BeforeHandle span should be present from the route-specific middleware + expect(spans).toContainEqual( + expect.objectContaining({ + description: 'BeforeHandle', + op: 'middleware.elysia', + origin: 'auto.http.otel.elysia', + }), + ); +}); + +test('Captures request metadata for POST requests', async ({ baseURL, request }) => { + const transactionEventPromise = waitForTransaction('elysia-node', transactionEvent => { + return ( + transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'POST /test-post' + ); + }); + + const response = await request.post(`${baseURL}/test-post`, { + data: { foo: 'bar', other: 1 }, + headers: { 'Content-Type': 'application/json' }, + }); + const resBody = await response.json(); + + expect(resBody).toEqual({ status: 'ok', body: { foo: 'bar', other: 1 } }); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent.request).toEqual( + expect.objectContaining({ + method: 'POST', + url: expect.stringContaining('/test-post'), + headers: expect.objectContaining({ + 'content-type': 'application/json', + }), + }), + ); +}); diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/tsconfig.json b/dev-packages/e2e-tests/test-applications/elysia-node/tsconfig.json new file mode 100644 index 000000000000..869427e44d4d --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/elysia-node/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "types": ["bun-types"], + "esModuleInterop": true, + "lib": ["es2020"], + "strict": true, + "outDir": "dist", + "skipLibCheck": true + }, + "include": ["src/**/*.ts"] +} From fa54c95286534248bcbb4b07325bccd015b4f354 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 12:01:56 -0400 Subject: [PATCH 17/21] test: use the node adapter --- .../e2e-tests/test-applications/elysia-node/src/app.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts b/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts index db6a5fff8bd1..459ed0cf3ae6 100644 --- a/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts @@ -1,5 +1,6 @@ import * as Sentry from '@sentry/elysia'; import { Elysia } from 'elysia'; +import { node } from '@elysiajs/node'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions @@ -9,7 +10,7 @@ Sentry.init({ tracePropagationTargets: ['http://localhost:3030', '/external-allowed'], }); -const app = Sentry.withElysia(new Elysia()); +const app = Sentry.withElysia(new Elysia({ adapter: node() })); // Simple success route app.get('/test-success', () => ({ version: 'v1' })); From 116043a55635ed58cb6065f78b6e76bf3d492347 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 12:14:12 -0400 Subject: [PATCH 18/21] test: fix test assertion --- packages/elysia/test/sdk.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/elysia/test/sdk.test.ts b/packages/elysia/test/sdk.test.ts index c85cae154a38..d27011f0e416 100644 --- a/packages/elysia/test/sdk.test.ts +++ b/packages/elysia/test/sdk.test.ts @@ -37,6 +37,7 @@ describe('init', () => { expect(mockApplySdkMetadata).toHaveBeenCalledWith( expect.objectContaining({ dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' }), 'elysia', + ['elysia', 'node'], ); }); From ac1c6080c62948c11864f2cda5f4e07fb72f7d77 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 12:49:18 -0400 Subject: [PATCH 19/21] fix: update root span with parameterized route name on Node.js On Node.js, the root HTTP span is created by Node's HTTP instrumentation with only the raw URL. The Elysia OTel plugin creates a child span with route info but doesn't propagate it up. This updates the root span and isolation scope with the parameterized route name in onAfterHandle (for successful requests on Node.js) and onError (for all runtimes). Co-Authored-By: Claude Opus 4.6 (1M context) --- .../test-applications/elysia-bun/package.json | 1 - .../elysia-node/package.json | 10 +++--- .../test-applications/elysia-node/src/app.ts | 2 +- packages/elysia/src/withElysia.ts | 36 +++++++++++++++++-- 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/elysia-bun/package.json b/dev-packages/e2e-tests/test-applications/elysia-bun/package.json index e41f24030046..dd0123725147 100644 --- a/dev-packages/e2e-tests/test-applications/elysia-bun/package.json +++ b/dev-packages/e2e-tests/test-applications/elysia-bun/package.json @@ -5,7 +5,6 @@ "type": "module", "scripts": { "start": "bun src/app.ts", - "start:node": "node src/app.ts", "test": "playwright test", "clean": "npx rimraf node_modules pnpm-lock.yaml", "test:build": "pnpm install", diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/package.json b/dev-packages/e2e-tests/test-applications/elysia-node/package.json index 3570307e0e61..1c11c6e719b1 100644 --- a/dev-packages/e2e-tests/test-applications/elysia-node/package.json +++ b/dev-packages/e2e-tests/test-applications/elysia-node/package.json @@ -4,23 +4,21 @@ "private": true, "type": "module", "scripts": { - "start": "bun src/app.ts", - "start:node": "node src/app.ts", + "start": "node src/app.ts", "test": "playwright test", "clean": "npx rimraf node_modules pnpm-lock.yaml", "test:build": "pnpm install", "test:assert": "pnpm test" }, "dependencies": { - "@elysiajs/opentelemetry": "^1.4.0", + "@elysiajs/opentelemetry": "^1.4.10", "@sentry/elysia": "latest || *", - "elysia": "^1.4.0", + "elysia": "latest", "@elysiajs/node": "^1.4.5" }, "devDependencies": { "@playwright/test": "~1.56.0", - "@sentry-internal/test-utils": "link:../../../test-utils", - "bun-types": "^1.2.9" + "@sentry-internal/test-utils": "link:../../../test-utils" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts b/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts index 459ed0cf3ae6..375ca9a29c6d 100644 --- a/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts @@ -126,7 +126,7 @@ app.listen(3030, () => { }); // Second app for external propagation tests -const app2 = new Elysia(); +const app2 = new Elysia({ adapter: node() }); app2.get('/external-allowed', ({ request }) => { const headers = Object.fromEntries(request.headers.entries()); diff --git a/packages/elysia/src/withElysia.ts b/packages/elysia/src/withElysia.ts index 4fc2a0e965d1..9efeee39481a 100644 --- a/packages/elysia/src/withElysia.ts +++ b/packages/elysia/src/withElysia.ts @@ -1,9 +1,13 @@ import { opentelemetry } from '@elysiajs/opentelemetry'; import { captureException, + getActiveSpan, getClient, getIsolationScope, + getRootSpan, getTraceData, + SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, + updateSpanName, winterCGRequestToRequestData, } from '@sentry/core'; import type { Elysia, ErrorContext } from 'elysia'; @@ -13,9 +17,30 @@ interface ElysiaHandlerOptions { shouldHandleError?: (context: ErrorContext) => boolean; } +function isBun(): boolean { + return typeof Bun !== 'undefined'; +} + let isClientHooksSetup = false; const instrumentedApps = new WeakSet(); +/** + * Updates the root span and isolation scope with the parameterized route name. + * Only needed on Node.js where the root span comes from HTTP instrumentation. + */ +function updateRouteTransactionName(method: string, route: string): void { + const transactionName = `${method} ${route}`; + + const activeSpan = getActiveSpan(); + if (activeSpan) { + const rootSpan = getRootSpan(activeSpan); + updateSpanName(rootSpan, transactionName); + rootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'route'); + } + + getIsolationScope().setTransactionName(transactionName); +} + function defaultShouldHandleError(context: ErrorContext): boolean { const status = context.set.status; if (status === undefined) { @@ -75,8 +100,15 @@ export function withElysia(app: T, options: ElysiaHandlerOptio }); }); - // Propagate trace data to all response headers + // Propagate trace data to all response headers and update transaction name app.onAfterHandle({ as: 'global' }, context => { + // On Node.js, the root span is created by the HTTP instrumentation and only has the raw URL. + // The Elysia OTel plugin creates a child span with route info, but we need to propagate it up. + // On Bun, the Elysia OTel plugin already handles the root span correctly. + if (!isBun() && context.route) { + updateRouteTransactionName(context.request.method, context.route); + } + const traceData = getTraceData(); if (traceData['sentry-trace']) { context.set.headers['sentry-trace'] = traceData['sentry-trace']; @@ -89,7 +121,7 @@ export function withElysia(app: T, options: ElysiaHandlerOptio // Register the error handler for all routes app.onError({ as: 'global' }, context => { if (context.route) { - getIsolationScope().setTransactionName(`${context.request.method} ${context.route}`); + updateRouteTransactionName(context.request.method, context.route); } const shouldHandleError = options?.shouldHandleError || defaultShouldHandleError; From 38ac16b52cdb407b673486dd9d5384f26f7668d3 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 13:08:19 -0400 Subject: [PATCH 20/21] chore: bump test node version --- .../e2e-tests/test-applications/elysia-node/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/package.json b/dev-packages/e2e-tests/test-applications/elysia-node/package.json index 1c11c6e719b1..677963d3e288 100644 --- a/dev-packages/e2e-tests/test-applications/elysia-node/package.json +++ b/dev-packages/e2e-tests/test-applications/elysia-node/package.json @@ -21,6 +21,7 @@ "@sentry-internal/test-utils": "link:../../../test-utils" }, "volta": { - "extends": "../../package.json" + "extends": "../../package.json", + "node": "20.19.2" } } From e35f5233c7654d3f60b3266ead35a81e9ab35ec2 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Thu, 19 Mar 2026 13:56:25 -0400 Subject: [PATCH 21/21] chore: bump elysia-node test app to Node 24 for native TS support Node 20 does not support running .ts files directly. Node 24 has TypeScript stripping enabled by default. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../e2e-tests/test-applications/elysia-node/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/package.json b/dev-packages/e2e-tests/test-applications/elysia-node/package.json index 677963d3e288..920c1fb019ce 100644 --- a/dev-packages/e2e-tests/test-applications/elysia-node/package.json +++ b/dev-packages/e2e-tests/test-applications/elysia-node/package.json @@ -22,6 +22,6 @@ }, "volta": { "extends": "../../package.json", - "node": "20.19.2" + "node": "24.11.0" } }