diff --git a/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLink-nested.ts b/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLink-nested.ts index 5eb3cb141e8d..660afb9ba1f7 100644 --- a/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLink-nested.ts +++ b/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLink-nested.ts @@ -1,8 +1,8 @@ +import { SENTRY_LINK_TYPE } from '@sentry/conventions/attributes'; import * as Sentry from '@sentry/node'; import { loggingTransport } from '@sentry-internal/node-integration-tests'; Sentry.init({ - traceLifecycle: 'static', dsn: 'https://public@dsn.ingest.sentry.io/1337', release: '1.0', tracesSampleRate: 1.0, @@ -16,7 +16,7 @@ Sentry.startSpan({ name: 'parent1' }, async parentSpan1 => { Sentry.startSpan({ name: 'child1.1' }, async childSpan1 => { childSpan1.addLink({ context: parentSpan1.spanContext(), - attributes: { 'sentry.link.type': 'previous_trace' }, + attributes: { [SENTRY_LINK_TYPE]: 'previous_trace' }, }); childSpan1.end(); @@ -26,7 +26,7 @@ Sentry.startSpan({ name: 'parent1' }, async parentSpan1 => { Sentry.startSpan({ name: 'child1.2' }, async childSpan2 => { childSpan2.addLink({ context: parentSpan1.spanContext(), - attributes: { 'sentry.link.type': 'previous_trace' }, + attributes: { [SENTRY_LINK_TYPE]: 'previous_trace' }, }); childSpan2.end(); diff --git a/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLink.ts b/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLink.ts index c8ca1605d307..47537edafb1f 100644 --- a/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLink.ts +++ b/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLink.ts @@ -1,8 +1,8 @@ +import { SENTRY_LINK_TYPE } from '@sentry/conventions/attributes'; import * as Sentry from '@sentry/node'; import { loggingTransport } from '@sentry-internal/node-integration-tests'; Sentry.init({ - traceLifecycle: 'static', dsn: 'https://public@dsn.ingest.sentry.io/1337', release: '1.0', tracesSampleRate: 1.0, @@ -16,6 +16,6 @@ span1.end(); Sentry.startSpan({ name: 'rootSpan' }, rootSpan => { rootSpan.addLink({ context: span1.spanContext(), - attributes: { 'sentry.link.type': 'previous_trace' }, + attributes: { [SENTRY_LINK_TYPE]: 'previous_trace' }, }); }); diff --git a/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLinks-nested.ts b/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLinks-nested.ts index 6d8c85412892..84d1680e95cf 100644 --- a/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLinks-nested.ts +++ b/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLinks-nested.ts @@ -1,8 +1,8 @@ +import { SENTRY_LINK_TYPE } from '@sentry/conventions/attributes'; import * as Sentry from '@sentry/node'; import { loggingTransport } from '@sentry-internal/node-integration-tests'; Sentry.init({ - traceLifecycle: 'static', dsn: 'https://public@dsn.ingest.sentry.io/1337', release: '1.0', tracesSampleRate: 1.0, @@ -20,7 +20,7 @@ Sentry.startSpan({ name: 'parent1' }, async parentSpan1 => { { context: parentSpan1.spanContext() }, { context: childSpan1.spanContext(), - attributes: { 'sentry.link.type': 'previous_trace' }, + attributes: { [SENTRY_LINK_TYPE]: 'previous_trace' }, }, ]); diff --git a/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLinks.ts b/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLinks.ts index 9ee7af7856bd..d401994901ef 100644 --- a/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLinks.ts +++ b/dev-packages/node-integration-tests/suites/tracing/linking/scenario-addLinks.ts @@ -1,8 +1,8 @@ +import { SENTRY_LINK_TYPE } from '@sentry/conventions/attributes'; import * as Sentry from '@sentry/node'; import { loggingTransport } from '@sentry-internal/node-integration-tests'; Sentry.init({ - traceLifecycle: 'static', dsn: 'https://public@dsn.ingest.sentry.io/1337', release: '1.0', tracesSampleRate: 1.0, @@ -21,7 +21,7 @@ Sentry.startSpan({ name: 'rootSpan' }, rootSpan => { { context: span1.spanContext() }, { context: span2.spanContext(), - attributes: { 'sentry.link.type': 'previous_trace' }, + attributes: { [SENTRY_LINK_TYPE]: 'previous_trace' }, }, ]); }); diff --git a/dev-packages/node-integration-tests/suites/tracing/linking/scenario-span-options.ts b/dev-packages/node-integration-tests/suites/tracing/linking/scenario-span-options.ts index 7b28c3f6992c..b00b18c82405 100644 --- a/dev-packages/node-integration-tests/suites/tracing/linking/scenario-span-options.ts +++ b/dev-packages/node-integration-tests/suites/tracing/linking/scenario-span-options.ts @@ -1,8 +1,8 @@ +import { SENTRY_LINK_TYPE } from '@sentry/conventions/attributes'; import * as Sentry from '@sentry/node'; import { loggingTransport } from '@sentry-internal/node-integration-tests'; Sentry.init({ - traceLifecycle: 'static', dsn: 'https://public@dsn.ingest.sentry.io/1337', release: '1.0', tracesSampleRate: 1.0, @@ -17,7 +17,7 @@ parentSpan1.end(); Sentry.startSpan( { name: 'parent2', - links: [{ context: parentSpan1.spanContext(), attributes: { 'sentry.link.type': 'previous_trace' } }], + links: [{ context: parentSpan1.spanContext(), attributes: { [SENTRY_LINK_TYPE]: 'previous_trace' } }], }, async () => { // eslint-disable-next-line @typescript-eslint/no-floating-promises diff --git a/dev-packages/node-integration-tests/suites/tracing/linking/test.ts b/dev-packages/node-integration-tests/suites/tracing/linking/test.ts index a0874274d2bd..84ed6d94314e 100644 --- a/dev-packages/node-integration-tests/suites/tracing/linking/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/linking/test.ts @@ -1,31 +1,25 @@ +import { SENTRY_LINK_TYPE, SENTRY_SEGMENT_ID } from '@sentry/conventions/attributes'; import { describe, expect, test } from 'vitest'; import { createRunner } from '../../../utils/runner'; describe('span links', () => { test('should link spans by adding "links" to span options', async () => { - let span1_traceId: string, span1_spanId: string; - await createRunner(__dirname, 'scenario-span-options.ts') .expect({ - transaction: event => { - expect(event.transaction).toBe('parent1'); - - const traceContext = event.contexts?.trace; - span1_traceId = traceContext?.trace_id as string; - span1_spanId = traceContext?.span_id as string; - }, - }) - .expect({ - transaction: event => { - expect(event.transaction).toBe('parent2'); - - const traceContext = event.contexts?.trace; - expect(traceContext).toBeDefined(); - expect(traceContext?.links).toEqual([ - expect.objectContaining({ - trace_id: expect.stringMatching(span1_traceId), - span_id: expect.stringMatching(span1_spanId), - }), + span: container => { + const parent1 = container.items.find(span => span.is_segment && span.name === 'parent1'); + expect(parent1).toBeDefined(); + + const parent2 = container.items.find(span => span.is_segment && span.name === 'parent2'); + expect(parent2).toBeDefined(); + + expect(parent2?.links).toEqual([ + { + trace_id: parent1?.trace_id, + span_id: parent1?.span_id, + sampled: true, + attributes: { [SENTRY_LINK_TYPE]: { type: 'string', value: 'previous_trace' } }, + }, ]); }, }) @@ -34,31 +28,30 @@ describe('span links', () => { }); test('should link spans with addLink() in trace context', async () => { - let span1_traceId: string, span1_spanId: string; - await createRunner(__dirname, 'scenario-addLink.ts') .expect({ - transaction: event => { - expect(event.transaction).toBe('span1'); - - span1_traceId = event.contexts?.trace?.trace_id as string; - span1_spanId = event.contexts?.trace?.span_id as string; - - expect(event.spans).toEqual([]); - }, - }) - .expect({ - transaction: event => { - expect(event.transaction).toBe('rootSpan'); - - expect(event.contexts?.trace?.links).toEqual([ - expect.objectContaining({ - trace_id: expect.stringMatching(span1_traceId), - span_id: expect.stringMatching(span1_spanId), - attributes: expect.objectContaining({ - 'sentry.link.type': 'previous_trace', - }), - }), + span: container => { + const span1 = container.items.find(span => span.is_segment && span.name === 'span1'); + expect(span1).toBeDefined(); + + expect( + container.items.filter( + span => !span.is_segment && span.attributes[SENTRY_SEGMENT_ID]?.value === span1?.span_id, + ), + ).toEqual([]); + + const rootSpan = container.items.find(span => span.is_segment && span.name === 'rootSpan'); + expect(rootSpan).toBeDefined(); + + expect(rootSpan?.links).toEqual([ + { + trace_id: span1?.trace_id, + span_id: span1?.span_id, + sampled: true, + attributes: { + [SENTRY_LINK_TYPE]: { type: 'string', value: 'previous_trace' }, + }, + }, ]); }, }) @@ -67,46 +60,45 @@ describe('span links', () => { }); test('should link spans with addLinks() in trace context', async () => { - let span1_traceId: string, span1_spanId: string, span2_traceId: string, span2_spanId: string; - await createRunner(__dirname, 'scenario-addLinks.ts') .expect({ - transaction: event => { - expect(event.transaction).toBe('span1'); - - span1_traceId = event.contexts?.trace?.trace_id as string; - span1_spanId = event.contexts?.trace?.span_id as string; - - expect(event.spans).toEqual([]); - }, - }) - .expect({ - transaction: event => { - expect(event.transaction).toBe('span2'); - - span2_traceId = event.contexts?.trace?.trace_id as string; - span2_spanId = event.contexts?.trace?.span_id as string; - - expect(event.spans).toEqual([]); - }, - }) - .expect({ - transaction: event => { - expect(event.transaction).toBe('rootSpan'); - - expect(event.contexts?.trace?.links).toEqual([ - expect.not.objectContaining({ attributes: expect.anything() }) && - expect.objectContaining({ - trace_id: expect.stringMatching(span1_traceId), - span_id: expect.stringMatching(span1_spanId), - }), - expect.objectContaining({ - trace_id: expect.stringMatching(span2_traceId), - span_id: expect.stringMatching(span2_spanId), - attributes: expect.objectContaining({ - 'sentry.link.type': 'previous_trace', - }), - }), + span: container => { + const span1 = container.items.find(span => span.is_segment && span.name === 'span1'); + expect(span1).toBeDefined(); + + expect( + container.items.filter( + span => !span.is_segment && span.attributes[SENTRY_SEGMENT_ID]?.value === span1?.span_id, + ), + ).toEqual([]); + + const span2 = container.items.find(span => span.is_segment && span.name === 'span2'); + expect(span2).toBeDefined(); + + expect( + container.items.filter( + span => !span.is_segment && span.attributes[SENTRY_SEGMENT_ID]?.value === span2?.span_id, + ), + ).toEqual([]); + + const rootSpan = container.items.find(span => span.is_segment && span.name === 'rootSpan'); + expect(rootSpan).toBeDefined(); + + expect(rootSpan?.links).toEqual([ + { + trace_id: span1?.trace_id, + span_id: span1?.span_id, + sampled: true, + attributes: {}, + }, + { + trace_id: span2?.trace_id, + span_id: span2?.span_id, + sampled: true, + attributes: { + [SENTRY_LINK_TYPE]: { type: 'string', value: 'previous_trace' }, + }, + }, ]); }, }) @@ -117,36 +109,36 @@ describe('span links', () => { test('should link spans with addLink() in nested startSpan() calls', async () => { await createRunner(__dirname, 'scenario-addLink-nested.ts') .expect({ - transaction: event => { - expect(event.transaction).toBe('parent1'); - - const parent1_traceId = event.contexts?.trace?.trace_id as string; - const parent1_spanId = event.contexts?.trace?.span_id as string; + span: container => { + const parent1 = container.items.find(span => span.is_segment && span.name === 'parent1'); + expect(parent1).toBeDefined(); - const spans = event.spans || []; - const child1_1 = spans.find(span => span.description === 'child1.1'); - const child1_2 = spans.find(span => span.description === 'child1.2'); + const spans = container.items.filter(span => !span.is_segment); + const child1_1 = spans.find(span => span.name === 'child1.1'); + const child1_2 = spans.find(span => span.name === 'child1.2'); expect(child1_1).toBeDefined(); expect(child1_1?.links).toEqual([ - expect.objectContaining({ - trace_id: expect.stringMatching(parent1_traceId), - span_id: expect.stringMatching(parent1_spanId), - attributes: expect.objectContaining({ - 'sentry.link.type': 'previous_trace', - }), - }), + { + trace_id: parent1?.trace_id, + span_id: parent1?.span_id, + sampled: true, + attributes: { + [SENTRY_LINK_TYPE]: { type: 'string', value: 'previous_trace' }, + }, + }, ]); expect(child1_2).toBeDefined(); expect(child1_2?.links).toEqual([ - expect.objectContaining({ - trace_id: expect.stringMatching(parent1_traceId), - span_id: expect.stringMatching(parent1_spanId), - attributes: expect.objectContaining({ - 'sentry.link.type': 'previous_trace', - }), - }), + { + trace_id: parent1?.trace_id, + span_id: parent1?.span_id, + sampled: true, + attributes: { + [SENTRY_LINK_TYPE]: { type: 'string', value: 'previous_trace' }, + }, + }, ]); }, }) @@ -157,33 +149,33 @@ describe('span links', () => { test('should link spans with addLinks() in nested startSpan() calls', async () => { await createRunner(__dirname, 'scenario-addLinks-nested.ts') .expect({ - transaction: event => { - expect(event.transaction).toBe('parent1'); - - const parent1_traceId = event.contexts?.trace?.trace_id as string; - const parent1_spanId = event.contexts?.trace?.span_id as string; + span: container => { + const parent1 = container.items.find(span => span.is_segment && span.name === 'parent1'); + expect(parent1).toBeDefined(); - const spans = event.spans || []; - const child1_1 = spans.find(span => span.description === 'child1.1'); - const child2_1 = spans.find(span => span.description === 'child2.1'); + const spans = container.items.filter(span => !span.is_segment); + const child1_1 = spans.find(span => span.name === 'child1.1'); + const child2_1 = spans.find(span => span.name === 'child2.1'); expect(child1_1).toBeDefined(); expect(child2_1).toBeDefined(); expect(child2_1?.links).toEqual([ - expect.not.objectContaining({ attributes: expect.anything() }) && - expect.objectContaining({ - trace_id: expect.stringMatching(parent1_traceId), - span_id: expect.stringMatching(parent1_spanId), - }), - expect.objectContaining({ - trace_id: expect.stringMatching(child1_1?.trace_id || 'non-existent-id-fallback'), - span_id: expect.stringMatching(child1_1?.span_id || 'non-existent-id-fallback'), - attributes: expect.objectContaining({ - 'sentry.link.type': 'previous_trace', - }), - }), + { + trace_id: parent1?.trace_id, + span_id: parent1?.span_id, + sampled: true, + attributes: {}, + }, + { + trace_id: child1_1?.trace_id, + span_id: child1_1?.span_id, + sampled: true, + attributes: { + [SENTRY_LINK_TYPE]: { type: 'string', value: 'previous_trace' }, + }, + }, ]); }, }) diff --git a/dev-packages/node-integration-tests/suites/tracing/tracer-start-active-span-error/instrument.mjs b/dev-packages/node-integration-tests/suites/tracing/tracer-start-active-span-error/instrument.mjs index a618d72f4469..5c80a151a31e 100644 --- a/dev-packages/node-integration-tests/suites/tracing/tracer-start-active-span-error/instrument.mjs +++ b/dev-packages/node-integration-tests/suites/tracing/tracer-start-active-span-error/instrument.mjs @@ -2,7 +2,6 @@ import * as Sentry from '@sentry/node'; import { loggingTransport } from '@sentry-internal/node-integration-tests'; Sentry.init({ - traceLifecycle: 'static', dsn: 'https://public@dsn.ingest.sentry.io/1337', tracesSampleRate: 1.0, transport: loggingTransport, diff --git a/dev-packages/node-integration-tests/suites/tracing/tracer-start-active-span-error/test.ts b/dev-packages/node-integration-tests/suites/tracing/tracer-start-active-span-error/test.ts index c315cf866900..b8d33d7976cf 100644 --- a/dev-packages/node-integration-tests/suites/tracing/tracer-start-active-span-error/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/tracer-start-active-span-error/test.ts @@ -1,4 +1,4 @@ -import { afterAll, describe } from 'vitest'; +import { afterAll, describe, expect } from 'vitest'; import { cleanupChildProcesses, createEsmAndCjsTests } from '../../../utils/runner'; describe('tracer.startActiveSpan errors', () => { @@ -17,16 +17,19 @@ describe('tracer.startActiveSpan errors', () => { test('does NOT mark span errored when uncaught error escapes raw tracer.startActiveSpan callback', async () => { await createRunner() // The rejection is captured as an error event, which can reach the transport before the - // transaction. + // span envelope. .ignore('event') .expect({ - transaction: { - transaction: 'test span name', - contexts: { - trace: { + span: { + items: [ + { + name: 'test span name', + is_segment: true, + start_timestamp: expect.any(Number), + end_timestamp: expect.any(Number), status: 'ok', }, - }, + ], }, }) .start()