diff --git a/packages/core/package.json b/packages/core/package.json index f898caa41e31..f54a5e984958 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -54,6 +54,7 @@ "lint:fix": "OXLINT_TSGOLINT_DANGEROUSLY_SUPPRESS_PROGRAM_DIAGNOSTICS=true oxlint . --fix --type-aware", "lint": "OXLINT_TSGOLINT_DANGEROUSLY_SUPPRESS_PROGRAM_DIAGNOSTICS=true oxlint . --type-aware", "lint:es-compatibility": "es-check es2020 ./build/cjs/*.js && es-check es2020 ./build/esm/*.js --module", + "bench": "vitest bench", "test": "vitest run", "test:watch": "vitest --watch", "yalc:publish": "yalc publish --push --sig" diff --git a/packages/core/test/bench/capture-exception.bench.ts b/packages/core/test/bench/capture-exception.bench.ts new file mode 100644 index 000000000000..a4f8dab1697f --- /dev/null +++ b/packages/core/test/bench/capture-exception.bench.ts @@ -0,0 +1,53 @@ +import { bench, describe } from 'vitest'; +import { + addBreadcrumb, + captureException, + getCurrentScope, + getIsolationScope, + setCurrentClient, +} from '../../src'; +import { getDefaultTestClientOptions, TestClient } from '../mocks/client'; +import { clearGlobalScope } from '../testutils'; + +function setupClient() { + clearGlobalScope(); + getCurrentScope().clear(); + getIsolationScope().clear(); + + const client = new TestClient( + getDefaultTestClientOptions({ + dsn: 'https://username@domain/123', + enableSend: true, + release: '1.0.0', + environment: 'production', + }), + ); + setCurrentClient(client); + client.init(); + return client; +} + +describe('captureException - minimal scope', () => { + setupClient(); + + bench('captureException(new Error(...))', () => { + captureException(new Error('Something went wrong')); + }); +}); + +describe('captureException - realistic scope', () => { + setupClient(); + + getCurrentScope().setUser({ id: '123', email: 'user@example.com' }); + getCurrentScope().setTag('service', 'api-gateway'); + getCurrentScope().setTag('region', 'us-east-1'); + getCurrentScope().setTag('version', '2.1.0'); + getCurrentScope().setExtra('request_id', 'req-abc-123'); + for (let i = 0; i < 10; i++) { + addBreadcrumb({ message: `Action ${i}`, category: 'http', level: 'info' }); + } + + bench('captureException(new Error(...))', () => { + captureException(new Error('Something went wrong')); + }); +}); diff --git a/packages/core/test/bench/startSpan.bench.ts b/packages/core/test/bench/startSpan.bench.ts new file mode 100644 index 000000000000..b090d13c994a --- /dev/null +++ b/packages/core/test/bench/startSpan.bench.ts @@ -0,0 +1,105 @@ +import { bench, describe } from 'vitest'; +import { + addBreadcrumb, + getCurrentScope, + getIsolationScope, + setCurrentClient, + startSpan, +} from '../../src'; +import { getDefaultTestClientOptions, TestClient } from '../mocks/client'; +import { clearGlobalScope } from '../testutils'; + +function setupClient() { + clearGlobalScope(); + getCurrentScope().clear(); + getIsolationScope().clear(); + + const client = new TestClient( + getDefaultTestClientOptions({ + dsn: 'https://username@domain/123', + enableSend: true, + tracesSampleRate: 1, + release: '1.0.0', + environment: 'production', + }), + ); + setCurrentClient(client); + client.init(); + return client; +} + +function addRealisticScopeData() { + getCurrentScope().setUser({ id: '123', email: 'user@example.com' }); + getCurrentScope().setTag('service', 'api-gateway'); + getCurrentScope().setTag('region', 'us-east-1'); + getCurrentScope().setTag('version', '2.1.0'); + getCurrentScope().setExtra('request_id', 'req-abc-123'); + for (let i = 0; i < 10; i++) { + addBreadcrumb({ message: `Action ${i}`, category: 'http', level: 'info' }); + } +} + +describe('startSpan pipeline - realistic scope', () => { + setupClient(); + addRealisticScopeData(); + + bench('single root span', () => { + startSpan({ name: 'GET /api/users', op: 'http.server' }, () => { + // span lifecycle only + }); + }); + + bench('root span + 5 child spans', () => { + startSpan({ name: 'GET /api/users', op: 'http.server' }, () => { + for (let i = 0; i < 5; i++) { + startSpan({ name: `SELECT * FROM users WHERE id = $${i + 1}`, op: 'db' }, span => { + span.setAttribute('db.system', 'postgresql'); + span.setAttribute('db.name', 'mydb'); + }); + } + }); + }); + + bench('root span + 10 child spans', () => { + startSpan({ name: 'GET /api/users', op: 'http.server' }, () => { + for (let i = 0; i < 10; i++) { + startSpan( + { name: i < 5 ? `db.query.${i}` : `http.request.${i}`, op: i < 5 ? 'db' : 'http.client' }, + span => { + span.setAttribute('key', 'value'); + }, + ); + } + }); + }); + + bench('root span + 100 child spans', () => { + startSpan({ name: 'GET /api/users', op: 'http.server' }, () => { + for (let i = 0; i < 100; i++) { + startSpan({ name: `operation.${i}`, op: 'db' }, span => { + span.setAttribute('db.system', 'postgresql'); + }); + } + }); + }); + + bench('root span + 1000 child spans', () => { + startSpan({ name: 'GET /api/users', op: 'http.server' }, () => { + for (let i = 0; i < 1000; i++) { + startSpan({ name: `operation.${i}`, op: 'db' }, span => { + span.setAttribute('db.system', 'postgresql'); + }); + } + }); + }); + + bench('root span + 10000 child spans', () => { + startSpan({ name: 'GET /api/users', op: 'http.server' }, () => { + for (let i = 0; i < 10000; i++) { + startSpan({ name: `operation.${i}`, op: 'db' }, span => { + span.setAttribute('db.system', 'postgresql'); + }); + } + }); + }); +});