diff --git a/.craft.yml b/.craft.yml
index aa9119014db4..19480826c78f 100644
--- a/.craft.yml
+++ b/.craft.yml
@@ -94,6 +94,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$/
@@ -194,6 +197,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 c09984de5c3b..d5e202ea714b 100644
--- a/.github/ISSUE_TEMPLATE/bug.yml
+++ b/.github/ISSUE_TEMPLATE/bug.yml
@@ -45,6 +45,7 @@ body:
- '@sentry/cloudflare'
- '@sentry/cloudflare - hono'
- '@sentry/deno'
+ - '@sentry/elysia'
- '@sentry/ember'
- '@sentry/gatsby'
- '@sentry/google-cloud-serverless'
diff --git a/README.md b/README.md
index 5a3453dbe004..390420e52224 100644
--- a/README.md
+++ b/README.md
@@ -70,6 +70,7 @@ package. Please refer to the README and instructions of those SDKs for more deta
- [`@sentry/capacitor`](https://github.com/getsentry/sentry-capacitor): SDK for Capacitor Apps and Ionic with support
for native crashes
- [`@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..fe9dc4b609b9
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/bun-elysia/tests/transactions.test.ts
@@ -0,0 +1,190 @@
+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('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 6e57ee2ea812..df4181565e13 100644
--- a/dev-packages/e2e-tests/verdaccio-config/config.yaml
+++ b/dev-packages/e2e-tests/verdaccio-config/config.yaml
@@ -74,6 +74,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 01c52cfd6a36..e57f96957b05 100644
--- a/package.json
+++ b/package.json
@@ -60,6 +60,7 @@
"packages/core",
"packages/cloudflare",
"packages/deno",
+ "packages/elysia",
"packages/ember",
"packages/eslint-config-sdk",
"packages/eslint-plugin-sdk",
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 @@
+
+
+
+
+
+
+# Official Sentry SDK for Elysia
+
+[](https://www.npmjs.com/package/@sentry/elysia)
+[](https://www.npmjs.com/package/@sentry/elysia)
+[](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..43d14ab6ec94
--- /dev/null
+++ b/packages/elysia/package.json
@@ -0,0 +1,75 @@
+{
+ "name": "@sentry/elysia",
+ "version": "10.42.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": {
+ "@elysiajs/opentelemetry": "^1.4.0",
+ "@sentry/bun": "10.42.0",
+ "@sentry/core": "10.42.0",
+ "@sentry/node": "10.42.0",
+ "elysia": "^1.4.0"
+ },
+ "devDependencies": {
+ "bun-types": "^1.2.9"
+ },
+ "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..84a06f2fb64a
--- /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/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..17318dc1e514
--- /dev/null
+++ b/packages/elysia/src/sdk.ts
@@ -0,0 +1,61 @@
+import * as os from 'node:os';
+import type { NodeClient } from '@sentry/bun';
+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 } from '@sentry/node';
+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..9106762b7bbc
--- /dev/null
+++ b/packages/elysia/src/withElysia.ts
@@ -0,0 +1,159 @@
+import { opentelemetry } from '@elysiajs/opentelemetry';
+import {
+ captureException,
+ getClient,
+ getIsolationScope,
+ getTraceData,
+ SEMANTIC_ATTRIBUTE_SENTRY_OP,
+ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
+ spanToJSON,
+ winterCGHeadersToDict,
+} from '@sentry/core';
+import type { Elysia, ErrorContext } from 'elysia';
+
+interface ElysiaHandlerOptions {
+ shouldHandleError: (context: ErrorContext) => boolean;
+}
+
+const ELYSIA_ORIGIN = 'auto.http.otel.elysia';
+
+let isClientHooksSetup = false;
+const emptySpanIds = new Set();
+
+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',
+};
+
+function defaultShouldHandleError(context: ErrorContext): boolean {
+ const status = context.set.status;
+ if (status === undefined) {
+ return true;
+ }
+ const statusCode = typeof status === 'string' ? parseInt(status, 10) : status;
+ // 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 {
+ // Register the opentelemetry plugin
+ // https://elysiajs.com/plugins/opentelemetry
+ app.use(opentelemetry());
+
+ if (!isClientHooksSetup) {
+ const client = getClient();
+ if (client) {
+ isClientHooksSetup = true;
+
+ // Enrich Elysia lifecycle spans with semantic op and origin,
+ // and mark empty spans that Elysia produces as children of lifecycle spans.
+ client.on('spanEnd', span => {
+ const spanData = spanToJSON(span);
+
+ // Elysia produces empty spans for each function handler
+ // users usually use arrow functions for handlers so they will show up as
+ // here we drop them so they don't clutter the transaction, if they get named by the user
+ // they will still show up as the name of the function
+ if (!spanData.description && (!spanData.data || Object.keys(spanData.data).length === 0)) {
+ emptySpanIds.add(spanData.span_id);
+ return;
+ }
+
+ // 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.
+ 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 the empty spans we marked above before sending the transaction,
+ // and delete matched IDs individually to avoid clearing IDs from concurrent transactions.
+ client.on('beforeSendEvent', event => {
+ if (event.type === 'transaction' && event.spans) {
+ event.spans = event.spans.filter(span => {
+ if (!emptySpanIds.has(span.span_id)) {
+ return true;
+ }
+
+ emptySpanIds.delete(span.span_id);
+
+ return false;
+ });
+ }
+ });
+ }
+ }
+
+ // Set SDK processing metadata for all requests
+ app.onRequest(context => {
+ getIsolationScope().setSDKProcessingMetadata({
+ normalizedRequest: {
+ method: context.request.method,
+ url: context.request.url,
+ headers: winterCGHeadersToDict(context.request.headers),
+ },
+ });
+ });
+
+ // 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..dee537acd008
--- /dev/null
+++ b/packages/elysia/test/sdk.test.ts
@@ -0,0 +1,126 @@
+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/node', () => ({
+ init: mockInitNode,
+}));
+
+vi.mock('@sentry/bun', () => ({
+ 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..acc4b66e13cf
--- /dev/null
+++ b/packages/elysia/test/withElysia.test.ts
@@ -0,0 +1,178 @@
+import type { ErrorContext } from 'elysia';
+import { afterEach, describe, expect, it, vi } from 'vitest';
+
+// Capture the handlers registered by withElysia
+let onAfterHandleHandler: (context: unknown) => void;
+let onErrorHandler: (context: unknown) => void;
+
+const mockApp = {
+ use: vi.fn().mockReturnThis(),
+ onRequest: vi.fn(() => {
+ return mockApp;
+ }),
+ onAfterHandle: vi.fn((_opts: unknown, handler: (context: unknown) => void) => {
+ onAfterHandleHandler = handler;
+ return mockApp;
+ }),
+ onError: vi.fn((_opts: unknown, handler: (context: unknown) => void) => {
+ onErrorHandler = handler;
+ return mockApp;
+ }),
+};
+
+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', () => {
+ 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/packages/node-core/src/utils/ensureIsWrapped.ts b/packages/node-core/src/utils/ensureIsWrapped.ts
index 921d01da8207..3d7e34c428fd 100644
--- a/packages/node-core/src/utils/ensureIsWrapped.ts
+++ b/packages/node-core/src/utils/ensureIsWrapped.ts
@@ -9,7 +9,7 @@ import { isCjs } from './detection';
*/
export function ensureIsWrapped(
maybeWrappedFunction: unknown,
- name: 'express' | 'connect' | 'fastify' | 'hapi' | 'koa' | 'hono',
+ name: 'express' | 'connect' | 'fastify' | 'hapi' | 'koa' | 'hono' | 'elysia',
): void {
const clientOptions = getClient()?.getOptions();
if (
diff --git a/yarn.lock b/yarn.lock
index 0802c0c39941..80b951af68c0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3269,6 +3269,15 @@
dependencies:
"@edge-runtime/primitives" "6.0.0"
+"@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"
@@ -4633,6 +4642,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"
@@ -5202,6 +5229,11 @@
resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-5.6.3.tgz#41ae1c07de1ebe0f6dde1abcbc9700a09b9c6056"
integrity sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA==
+"@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"
@@ -6175,6 +6207,13 @@
dependencies:
"@octokit/openapi-types" "^12.11.0"
+"@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"
+
"@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"
@@ -6201,10 +6240,22 @@
resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe"
integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==
+"@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":
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-2.5.1.tgz#457b8f9c1e219bf6e22b549d90f773db0a38fe06"
- integrity sha512-MHbu8XxCHcBn6RwvCt2Vpn1WnLMNECfNKYB14LI5XypcgH4IE0/DiVifVR9tAkwPMyLXN8dOoPJfya3IryLQVw==
+ 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":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-2.0.0.tgz#37e9f0e9ddec4479b267aca6f32d88757c941b3a"
+ integrity sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ==
+ dependencies:
+ "@opentelemetry/semantic-conventions" "^1.29.0"
"@opentelemetry/core@2.5.0":
version "2.5.0"
@@ -6213,13 +6264,140 @@
dependencies:
"@opentelemetry/semantic-conventions" "^1.29.0"
-"@opentelemetry/core@2.5.1", "@opentelemetry/core@^2.0.0", "@opentelemetry/core@^2.5.1":
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-2.5.1.tgz#b5d830ab499bc13e29f6efa88a165630f25d2ad2"
- integrity sha512-Dwlc+3HAZqpgTYq0MUyZABjFkcrKTePwuiFVLjahGD8cx3enqihmpAmdgNFO1R4m/sIe5afjJrA25Prqy4NXlA==
+"@opentelemetry/core@2.6.0", "@opentelemetry/core@^2.0.0", "@opentelemetry/core@^2.5.1":
+ 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"
@@ -6428,6 +6606,17 @@
"@opentelemetry/instrumentation" "^0.211.0"
"@opentelemetry/semantic-conventions" "^1.24.0"
+"@opentelemetry/instrumentation@0.200.0", "@opentelemetry/instrumentation@^0.200.0":
+ version "0.200.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.200.0.tgz#29d1d4f70cbf0cb1ca9f2f78966379b0be96bddc"
+ integrity sha512-pmPlzfJd+vvgaZd/reMsC8RWgTXn2WY1OWT5RT42m3aOn5532TozwXNDhg1vzqJ+jnvmkREcdLr27ebJEQt0Jg==
+ dependencies:
+ "@opentelemetry/api-logs" "0.200.0"
+ "@types/shimmer" "^1.2.0"
+ import-in-the-middle "^1.8.1"
+ require-in-the-middle "^7.1.1"
+ shimmer "^1.2.1"
+
"@opentelemetry/instrumentation@0.211.0", "@opentelemetry/instrumentation@^0.211.0":
version "0.211.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.211.0.tgz#d45e20eafa75b5d3e8a9745a6205332893c55f37"
@@ -6455,28 +6644,144 @@
import-in-the-middle "^2.0.0"
require-in-the-middle "^8.0.0"
+"@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/core" "2.0.0"
+
+"@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/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.5.1", "@opentelemetry/resources@^2.5.1":
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-2.5.1.tgz#90ccc27cea02b543f20a7db9834852ec11784c1a"
- integrity sha512-BViBCdE/GuXRlp9k7nS1w6wJvY5fnFX5XvuEtWsTAOQFIO89Eru7lGW3WbfbxtCuZ/GbrJfAziXG0w0dpxL7eQ==
+"@opentelemetry/resources@2.0.0":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-2.0.0.tgz#15c04794c32b7d0b3c7589225ece6ae9bba25989"
+ integrity sha512-rnZr6dML2z4IARI4zPGQV4arDikF/9OXZQzrC01dLmn0CZxU5U5OLd/m1T7YkGRj5UitjeoCtg/zorlgMQcdTg==
+ dependencies:
+ "@opentelemetry/core" "2.0.0"
+ "@opentelemetry/semantic-conventions" "^1.29.0"
+
+"@opentelemetry/resources@2.6.0", "@opentelemetry/resources@^2.5.1":
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-2.6.0.tgz#1a945dbb8986043d8b593c358d5d8e3de6becf5a"
+ integrity sha512-D4y/+OGe3JSuYUCBxtH5T9DSAWNcvCb/nQWIga8HNtXTVPQn59j0nTBAgaAXxUVBDl40mG3Tc76b46wPlZaiJQ==
+ dependencies:
+ "@opentelemetry/core" "2.6.0"
+ "@opentelemetry/semantic-conventions" "^1.29.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":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.0.tgz#ebc06ea7537dea62f3882f8236c1234f4faf6b23"
+ integrity sha512-qQnYdX+ZCkonM7tA5iU4fSRsVxbFGml8jbxOgipRGMFHKaXKHQ30js03rTobYjKjIfnOsZSbHKWF0/0v0OQGfw==
dependencies:
- "@opentelemetry/core" "2.5.1"
+ "@opentelemetry/core" "2.0.0"
+ "@opentelemetry/resources" "2.0.0"
"@opentelemetry/semantic-conventions" "^1.29.0"
"@opentelemetry/sdk-trace-base@^2.5.1":
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.5.1.tgz#4f55f37e18ac3f971936d4717b6bfd43cfd72d61"
- integrity sha512-iZH3Gw8cxQn0gjpOjJMmKLd9GIaNh/E3v3ST67vyzLSxHBs14HsG4dy7jMYyC5WXGdBVEcM7U/XTF5hCQxjDMw==
+ 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==
dependencies:
- "@opentelemetry/core" "2.5.1"
- "@opentelemetry/resources" "2.5.1"
+ "@opentelemetry/core" "2.6.0"
+ "@opentelemetry/resources" "2.6.0"
"@opentelemetry/semantic-conventions" "^1.29.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.37.0", "@opentelemetry/semantic-conventions@^1.39.0":
version "1.39.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.39.0.tgz#f653b2752171411feb40310b8a8953d7e5c543b7"
@@ -9505,12 +9810,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.3.3"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-25.3.3.tgz#605862544ee7ffd7a936bcbf0135a14012f1e549"
+ integrity sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==
dependencies:
- undici-types "~6.20.0"
+ undici-types "~7.18.0"
"@types/node@^14.8.0":
version "14.18.63"
@@ -9692,6 +9997,11 @@
"@types/mime" "*"
"@types/node" "*"
+"@types/shimmer@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.2.0.tgz#9b706af96fa06416828842397a70dfbbf1c14ded"
+ integrity sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==
+
"@types/sinon@^17.0.3":
version "17.0.3"
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-17.0.3.tgz#9aa7e62f0a323b9ead177ed23a36ea757141a5fa"
@@ -13161,6 +13471,11 @@ citty@^0.2.0:
resolved "https://registry.yarnpkg.com/citty/-/citty-0.2.0.tgz#2426b145c4bf2a2c5c33bd66a634dfe3d5ea67ea"
integrity sha512-8csy5IBFI2ex2hTVpaHN2j+LNE199AgiI7y4dMintrr8i0lQiFn+0AWMZrWdHKIgMOer65f8IThysYhoReqjWA==
+cjs-module-lexer@^1.2.2:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz#0f79731eb8cfe1ec72acd4066efac9d61991b00d"
+ integrity sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==
+
cjs-module-lexer@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz#b3ca5101843389259ade7d88c77bd06ce55849ca"
@@ -13729,7 +14044,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==
@@ -14889,6 +15204,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"
@@ -16677,6 +17002,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"
@@ -16946,6 +17276,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"
@@ -18956,6 +19291,16 @@ import-fresh@^3.2.1:
parent-module "^1.0.0"
resolve-from "^4.0.0"
+import-in-the-middle@^1.8.1:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz#9e20827a322bbadaeb5e3bac49ea8f6d4685fdd8"
+ integrity sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==
+ dependencies:
+ acorn "^8.14.0"
+ acorn-import-attributes "^1.9.5"
+ cjs-module-lexer "^1.2.2"
+ module-details-from-path "^1.0.3"
+
import-in-the-middle@^2.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"
@@ -20658,7 +21003,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=
@@ -20872,10 +21217,10 @@ long@^4.0.0:
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
-long@^5.2.1:
- version "5.2.3"
- resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1"
- integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==
+long@^5.0.0, long@^5.2.1:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/long/-/long-5.3.2.tgz#1d84463095999262d7d7b7f8bfd4a8cc55167f83"
+ integrity sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==
longest-streak@^3.0.0:
version "3.1.0"
@@ -21387,6 +21732,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"
@@ -25207,6 +25557,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"
@@ -26010,6 +26378,15 @@ require-from-string@^2.0.2:
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+require-in-the-middle@^7.1.1:
+ version "7.5.2"
+ resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz#dc25b148affad42e570cf0e41ba30dc00f1703ec"
+ integrity sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==
+ dependencies:
+ debug "^4.3.5"
+ module-details-from-path "^1.0.3"
+ resolve "^1.22.8"
+
require-in-the-middle@^8.0.0:
version "8.0.1"
resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-8.0.1.tgz#dbde2587f669398626d56b20c868ab87bf01cce4"
@@ -27045,6 +27422,11 @@ shikiji@^0.6.8:
dependencies:
hast-util-to-html "^9.0.0"
+shimmer@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337"
+ integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==
+
side-channel-list@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad"
@@ -29200,10 +29582,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"
@@ -30920,7 +31302,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==