Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ module.exports = [
import: createImport('init'),
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
gzip: true,
limit: '156 KB',
limit: '157 KB',
disablePlugins: ['@size-limit/esbuild'],
},
{
Expand Down Expand Up @@ -465,7 +465,7 @@ module.exports = [
path: 'packages/node/build/esm/index.js',
import: createImport('init'),
gzip: true,
limit: '135 KB',
limit: '137 KB',
disablePlugins: ['@size-limit/esbuild'],
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
modifyWebpackConfig: function (config) {
Expand Down
3 changes: 3 additions & 0 deletions dev-packages/node-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"generic-pool": "^3.9.0",
"graphql": "^16.11.0",
"groq-sdk": "1.6.0",
"h3": "2.0.1-rc.22",
"graphql-tag": "^2.12.7",
"hono": "^4.13.7",
"http-terminator": "^3.2.0",
Expand Down Expand Up @@ -103,7 +104,9 @@
"reflect-metadata": "0.2.2",
"together-ai": "0.54.0",
"rxjs": "^7.8.2",
"srvx": "^0.11.22",
"tedious": "^19.2.1",
"unstorage": "2.0.0-alpha.7",
"winston": "^3.17.0",
"ws": "^8.20.1",
"yargs": "^16.2.0"
Expand Down
5 changes: 3 additions & 2 deletions dev-packages/node-integration-tests/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import type { AddressInfo } from 'net';
export function loggingTransport(_options: BaseTransportOptions): Transport {
return {
send(request: Envelope): Promise<TransportMakeRequestResponse> {
// eslint-disable-next-line no-console
console.log(JSON.stringify(request));
// Not `console.log`: Bun 1.3 drops its newline for a string of exactly 4096 bytes, merging two
// envelopes into one line the runner can't parse.
process.stdout.write(`${JSON.stringify(request)}\n`);
return Promise.resolve({ statusCode: 200 });
},
flush(): PromiseLike<boolean> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as Sentry from '@sentry/node';
import { loggingTransport } from '@sentry-internal/node-integration-tests';

Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
release: '1.0',
tracesSampleRate: 1.0,
transport: loggingTransport,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { sendPortToRunner } from '@sentry-internal/node-integration-tests';
import { H3, serve } from 'h3';
import { tracingPlugin as h3TracingPlugin } from 'h3/tracing';
import { tracingPlugin as srvxTracingPlugin } from 'srvx/tracing';
import { createStorage } from 'unstorage';
import { withTracing } from 'unstorage/tracing';

// Enables the same diagnostics channels a Nitro app publishes, without a Nitro build.
const storage = withTracing(createStorage());

const app = new H3({ plugins: [h3TracingPlugin()] });

app.get('/hello/:name', event => `Hello, ${event.context.params.name}!`);

app.get('/cache', async () => {
await storage.setItem('cache:key', 'value');
return storage.getItem('cache:key');
});

const server = serve(app, { port: 0, silent: true, plugins: [srvxTracingPlugin()] });

await server.ready();
sendPortToRunner(new URL(server.url).port);
115 changes: 115 additions & 0 deletions dev-packages/node-integration-tests/suites/tracing/nitro/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import {
CACHE_HIT,
CACHE_KEY,
DB_OPERATION_NAME,
DB_SYSTEM_NAME,
HTTP_RESPONSE_STATUS_CODE,
HTTP_ROUTE,
SENTRY_OP,
SENTRY_ORIGIN,
} from '@sentry/conventions/attributes';
import { CACHE_GET, CACHE_PUT, HTTP_SERVER } from '@sentry/conventions/op';
import { afterAll, describe, expect, vi } from 'vitest';
import { supports } from '../../../utils';
import { cleanupChildProcesses, createEsmTests } from '../../../utils/runner';

// h3 v2 and srvx are ESM-only and require Node >= 20.
describe.runIf(supports({ min: 20 }))('nitro integrations', () => {
afterAll(() => {
cleanupChildProcesses();
});

createEsmTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => {
test('creates h3 and srvx spans and sets Server-Timing headers', async () => {
let traceId: string | undefined;

const runner = createRunner()
.expect({
span: container => {
const segment = container.items.find(span => span.is_segment);
const srvxSpan = container.items.find(
span => span.attributes[SENTRY_ORIGIN]?.value === 'auto.http.nitro.srvx',
);
const h3Span = container.items.find(span => span.attributes[SENTRY_ORIGIN]?.value === 'auto.http.nitro.h3');

traceId = segment?.trace_id;

expect(segment?.name).toBe('GET /hello/:name');
expect(segment?.attributes[HTTP_ROUTE]).toEqual({ type: 'string', value: '/hello/:name' });

// Bun publishes no `http.server.request.start`, so there the srvx span is the segment itself.
expect(srvxSpan).toMatchObject({
status: 'ok',
attributes: expect.objectContaining({
[SENTRY_OP]: { type: 'string', value: HTTP_SERVER },
[HTTP_RESPONSE_STATUS_CODE]: { type: 'integer', value: 200 },
}),
});

expect(h3Span).toMatchObject({
name: 'GET /hello/:name',
parent_span_id: srvxSpan?.span_id,
status: 'ok',
attributes: expect.objectContaining({
[SENTRY_OP]: { type: 'string', value: HTTP_SERVER },
[HTTP_ROUTE]: { type: 'string', value: '/hello/:name' },
}),
});
},
})
.start();

const port = await vi.waitFor(() => runner.getPort() ?? Promise.reject(new Error('port not ready')), {
timeout: 30_000,
});
const response = await fetch(`http://localhost:${port}/hello/world`);
expect(await response.text()).toBe('Hello, world!');

await runner.completed();

const serverTiming = response.headers.get('server-timing');
expect(serverTiming).toContain(`sentry-trace;desc="${traceId}-`);
expect(serverTiming).toContain('baggage;desc="');
});

test('creates cache spans for unstorage operations', async () => {
const runner = createRunner()
.expect({
span: container => {
const segment = container.items.find(span => span.is_segment);
const cacheSpans = container.items.filter(
span => span.attributes[SENTRY_ORIGIN]?.value === 'auto.cache.nitro',
);

expect(segment?.name).toBe('GET /cache');
expect(cacheSpans).toEqual([
expect.objectContaining({
name: 'cache.put',
status: 'ok',
attributes: expect.objectContaining({
[SENTRY_OP]: { type: 'string', value: CACHE_PUT },
[CACHE_KEY]: { type: 'string', value: 'cache:key' },
[DB_OPERATION_NAME]: { type: 'string', value: 'setItem' },
[DB_SYSTEM_NAME]: { type: 'string', value: 'memory' },
}),
}),
expect.objectContaining({
name: 'cache.get',
status: 'ok',
attributes: expect.objectContaining({
[SENTRY_OP]: { type: 'string', value: CACHE_GET },
[CACHE_KEY]: { type: 'string', value: 'cache:key' },
[CACHE_HIT]: { type: 'boolean', value: true },
[DB_OPERATION_NAME]: { type: 'string', value: 'getItem' },
}),
}),
Comment thread
cursor[bot] marked this conversation as resolved.
]);
},
})
.start();

expect(await runner.makeRequest('get', '/cache')).toBe('value');
await runner.completed();
});
});
});
2 changes: 2 additions & 0 deletions packages/astro/src/index.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ export {
mongoIntegration,
mongooseIntegration,
mysql2Integration,
nitroIntegration,
nitroServerTimingIntegration,
mysqlIntegration,
nativeNodeFetchIntegration,
NodeClient,
Expand Down
2 changes: 2 additions & 0 deletions packages/aws-serverless/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ export {
mongooseIntegration,
mysqlIntegration,
mysql2Integration,
nitroIntegration,
nitroServerTimingIntegration,
redisIntegration,
tediousIntegration,
pinoIntegration,
Expand Down
2 changes: 2 additions & 0 deletions packages/bun/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ export {
mongooseIntegration,
mysqlIntegration,
mysql2Integration,
nitroIntegration,
nitroServerTimingIntegration,
redisIntegration,
tediousIntegration,
postgresIntegration,
Expand Down
2 changes: 2 additions & 0 deletions packages/deno/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ export {
mongooseIntegration,
mysqlIntegration,
mysql2Integration,
nitroIntegration,
nitroServerTimingIntegration,
mistralAIIntegration,
openAIIntegration,
groqIntegration,
Expand Down
63 changes: 3 additions & 60 deletions packages/deno/test/__snapshots__/mod.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,7 @@ snapshot[`captureMessage 1`] = `
platform: "javascript",
sdk: {
integrations: [
"EventFilters",
"RequestData",
"FunctionToString",
"LinkedErrors",
"Dedupe",
"ConversationId",
"Breadcrumbs",
"Console",
"DenoContext",
"DenoServe",
"Fetch",
"DenoHttp",
"ContextLines",
"NormalizePaths",
"GlobalHandlers",
"Express",
"Fastify",
"Hapi",
"Hono",
"Koa",
"{{integrations}}",
],
name: "sentry.javascript.deno",
packages: [
Expand Down Expand Up @@ -136,26 +117,7 @@ snapshot[`captureMessage twice 1`] = `
platform: "javascript",
sdk: {
integrations: [
"EventFilters",
"RequestData",
"FunctionToString",
"LinkedErrors",
"Dedupe",
"ConversationId",
"Breadcrumbs",
"Console",
"DenoContext",
"DenoServe",
"Fetch",
"DenoHttp",
"ContextLines",
"NormalizePaths",
"GlobalHandlers",
"Express",
"Fastify",
"Hapi",
"Hono",
"Koa",
"{{integrations}}",
],
name: "sentry.javascript.deno",
packages: [
Expand Down Expand Up @@ -232,26 +194,7 @@ snapshot[`captureMessage twice 2`] = `
platform: "javascript",
sdk: {
integrations: [
"EventFilters",
"RequestData",
"FunctionToString",
"LinkedErrors",
"Dedupe",
"ConversationId",
"Breadcrumbs",
"Console",
"DenoContext",
"DenoServe",
"Fetch",
"DenoHttp",
"ContextLines",
"NormalizePaths",
"GlobalHandlers",
"Express",
"Fastify",
"Hapi",
"Hono",
"Koa",
"{{integrations}}",
],
name: "sentry.javascript.deno",
packages: [
Expand Down
6 changes: 6 additions & 0 deletions packages/deno/test/normalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ function normalizeEvent(event: Event): Event {
}
}

// The default integration list is incidental to these snapshots, so collapse it to a placeholder.
// This keeps the snapshots stable when integrations are added to or removed from the defaults.
if (event.sdk?.integrations) {
event.sdk.integrations = ['{{integrations}}'];
}

if (event.contexts?.app?.app_start_time) {
event.contexts.app.app_start_time = '{{time}}';
}
Expand Down
2 changes: 2 additions & 0 deletions packages/elysia/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ export {
mongooseIntegration,
mysqlIntegration,
mysql2Integration,
nitroIntegration,
nitroServerTimingIntegration,
redisIntegration,
tediousIntegration,
postgresIntegration,
Expand Down
2 changes: 2 additions & 0 deletions packages/google-cloud-serverless/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ export {
mongooseIntegration,
mysqlIntegration,
mysql2Integration,
nitroIntegration,
nitroServerTimingIntegration,
redisIntegration,
tediousIntegration,
pinoIntegration,
Expand Down
27 changes: 0 additions & 27 deletions packages/nitro/src/runtime/hooks/setServerTimingHeaders.ts

This file was deleted.

5 changes: 0 additions & 5 deletions packages/nitro/src/runtime/plugins/server.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { definePlugin } from 'nitro';
import { captureErrorHook } from '../hooks/captureErrorHook';
import { captureStorageEvents } from '../hooks/captureStorageEvents';
import { captureTracingEvents } from '../hooks/captureTracingEvents';

export default definePlugin(nitroApp => {
nitroApp.hooks.hook('error', captureErrorHook);

captureTracingEvents();
captureStorageEvents();
});
Loading
Loading