Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
2 changes: 1 addition & 1 deletion .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ module.exports = [
import: createImport('init'),
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
gzip: true,
limit: '57 KB',
limit: '59 KB',
},
// Node SDK (ESM)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as Sentry from '@sentry/node-core';
import { loggingTransport } from '@sentry-internal/node-integration-tests';
import { setupOtel } from '../../../../utils/setupOtel';

const client = Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
tracesSampleRate: 1.0,
traceLifecycle: 'stream',
integrations: [Sentry.spanStreamingIntegration()],
transport: loggingTransport,
});

setupOtel(client);

Sentry.startSpan({ name: 'test-span', op: 'test' }, segmentSpan => {
Sentry.startSpan({ name: 'test-child-span', op: 'test-child' }, () => {
// noop
});

const inactiveSpan = Sentry.startInactiveSpan({ name: 'test-inactive-span' });
inactiveSpan.addLink({ context: segmentSpan.spanContext(), attributes: { 'sentry.link.type': 'some_relation' } });
inactiveSpan.end();

Sentry.startSpanManual({ name: 'test-manual-span' }, span => {
span.end();
});
});

void Sentry.flush();
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import {
SDK_VERSION,
SEMANTIC_ATTRIBUTE_SENTRY_OP,
SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE,
SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME,
SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION,
SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID,
SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME,
} from '@sentry/core';
import { expect, test } from 'vitest';
import { createRunner } from '../../../../utils/runner';

test('sends a streamed span envelope with correct envelope header', async () => {
await createRunner(__dirname, 'scenario.ts')
.expectHeader({
span: {
sent_at: expect.any(String),
sdk: {
name: 'sentry.javascript.node-core',
version: SDK_VERSION,
},
trace: expect.objectContaining({
public_key: 'public',
sample_rate: '1',
sampled: 'true',
trace_id: expect.stringMatching(/^[\da-f]{32}$/),
transaction: 'test-span',
}),
},
})
.start()
.completed();
});

test('sends a streamed span envelope with correct spans for a manually started span with children', async () => {
await createRunner(__dirname, 'scenario.ts')
.expect({
span: container => {
const spans = container.items;
expect(spans.length).toBe(4);

const segmentSpan = spans.find(s => !!s.is_segment);
expect(segmentSpan).toBeDefined();

const segmentSpanId = segmentSpan!.span_id;
const traceId = segmentSpan!.trace_id;

const childSpan = spans.find(s => s.name === 'test-child-span');
expect(childSpan).toBeDefined();
expect(childSpan).toEqual({
attributes: expect.objectContaining({
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: {
type: 'string',
value: 'test-child',
},
[SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME]: { type: 'string', value: 'sentry.javascript.node-core' },
[SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION },
[SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId },
[SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME]: { type: 'string', value: 'test-span' },
}),
name: 'test-child-span',
is_segment: false,
parent_span_id: segmentSpanId,
trace_id: traceId,
span_id: expect.stringMatching(/^[\da-f]{16}$/),
start_timestamp: expect.any(Number),
end_timestamp: expect.any(Number),
status: 'ok',
});

const inactiveSpan = spans.find(s => s.name === 'test-inactive-span');
expect(inactiveSpan).toBeDefined();
expect(inactiveSpan).toEqual({
attributes: expect.objectContaining({
[SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME]: { type: 'string', value: 'sentry.javascript.node-core' },
[SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION },
[SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId },
[SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME]: { type: 'string', value: 'test-span' },
}),
links: [
{
attributes: {
'sentry.link.type': {
type: 'string',
value: 'some_relation',
},
},
sampled: true,
span_id: segmentSpanId,
trace_id: traceId,
},
],
name: 'test-inactive-span',
is_segment: false,
parent_span_id: segmentSpanId,
trace_id: traceId,
span_id: expect.stringMatching(/^[\da-f]{16}$/),
start_timestamp: expect.any(Number),
end_timestamp: expect.any(Number),
status: 'ok',
});

const manualSpan = spans.find(s => s.name === 'test-manual-span');
expect(manualSpan).toBeDefined();
expect(manualSpan).toEqual({
attributes: expect.objectContaining({
[SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME]: { type: 'string', value: 'sentry.javascript.node-core' },
[SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION },
[SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId },
[SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME]: { type: 'string', value: 'test-span' },
}),
name: 'test-manual-span',
is_segment: false,
parent_span_id: segmentSpanId,
trace_id: traceId,
span_id: expect.stringMatching(/^[\da-f]{16}$/),
start_timestamp: expect.any(Number),
end_timestamp: expect.any(Number),
status: 'ok',
});

expect(segmentSpan).toEqual({
attributes: expect.objectContaining({
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: { type: 'string', value: 'test' },
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: { type: 'integer', value: 1 },
[SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME]: { type: 'string', value: 'sentry.javascript.node-core' },
[SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION },
[SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId },
[SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME]: { type: 'string', value: 'test-span' },
}),
name: 'test-span',
is_segment: true,
trace_id: traceId,
span_id: segmentSpanId,
start_timestamp: expect.any(Number),
end_timestamp: expect.any(Number),
status: 'ok',
});
},
})
.start()
.completed();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as Sentry from '@sentry/node-core';
import { loggingTransport } from '@sentry-internal/node-core-integration-tests';
import { setupOtel } from '../../../../utils/setupOtel';

const client = Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
release: '1.0',
tracesSampleRate: 1.0,
traceLifecycle: 'stream',
transport: loggingTransport,
});

setupOtel(client);

Sentry.getCurrentScope().setPropagationContext({
parentSpanId: '1234567890123456',
traceId: '12345678901234567890123456789012',
sampleRand: Math.random(),
});

const spanIdTraceId = Sentry.startSpan(
{
name: 'test_span_1',
},
span1 => span1.spanContext().traceId,
);

Sentry.startSpan(
{
name: 'test_span_2',
attributes: { spanIdTraceId },
},
() => undefined,
);

Sentry.flush();
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { afterAll, expect, test } from 'vitest';
import { cleanupChildProcesses, createRunner } from '../../../../utils/runner';

afterAll(() => {
cleanupChildProcesses();
});

test('sends manually started streamed parallel root spans in root context', async () => {
expect.assertions(7);

await createRunner(__dirname, 'scenario.ts')
.expect({ span: { items: [{ name: 'test_span_1' }] } })
.expect({
span: spanContainer => {
expect(spanContainer).toBeDefined();
const traceId = spanContainer.items[0]!.trace_id;
expect(traceId).toMatch(/^[0-9a-f]{32}$/);

// It ignores propagation context of the root context
expect(traceId).not.toBe('12345678901234567890123456789012');
expect(spanContainer.items[0]!.parent_span_id).toBeUndefined();

// Different trace ID than the first span
const trace1Id = spanContainer.items[0]!.attributes?.spanIdTraceId;
expect(trace1Id).toBeDefined();
expect(trace1Id).not.toBe(traceId);
Comment thread
cursor[bot] marked this conversation as resolved.
},
})
.start()
.completed();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as Sentry from '@sentry/node-core';
import { loggingTransport } from '@sentry-internal/node-core-integration-tests';
import { setupOtel } from '../../../../utils/setupOtel';

const client = Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
release: '1.0',
tracesSampleRate: 1.0,
traceLifecycle: 'stream',
transport: loggingTransport,
});

setupOtel(client);

Sentry.withScope(() => {
const spanIdTraceId = Sentry.startSpan(
{
name: 'test_span_1',
},
span1 => span1.spanContext().traceId,
);

Sentry.startSpan(
{
name: 'test_span_2',
attributes: { spanIdTraceId },
},
() => undefined,
);
});

Sentry.flush();
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { afterAll, expect, test } from 'vitest';
import { cleanupChildProcesses, createRunner } from '../../../../utils/runner';

afterAll(() => {
cleanupChildProcesses();
});

test('sends manually started streamed parallel root spans outside of root context', async () => {
expect.assertions(6);

await createRunner(__dirname, 'scenario.ts')
.expect({ span: { items: [{ name: 'test_span_1' }] } })
.expect({
span: spanContainer => {
expect(spanContainer).toBeDefined();
const traceId = spanContainer.items[0]!.trace_id;
expect(traceId).toMatch(/^[0-9a-f]{32}$/);
expect(spanContainer.items[0]!.parent_span_id).toBeUndefined();

const trace1Id = spanContainer.items[0]!.attributes?.spanIdTraceId;
expect(trace1Id).toBeDefined();

// Different trace ID as the first span
expect(trace1Id).not.toBe(traceId);
},
})
.start()
.completed();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import * as Sentry from '@sentry/node-core';
import { loggingTransport } from '@sentry-internal/node-core-integration-tests';
import { setupOtel } from '../../../../utils/setupOtel';

const client = Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
release: '1.0',
tracesSampleRate: 1.0,
traceLifecycle: 'stream',
transport: loggingTransport,
});

setupOtel(client);

Sentry.withScope(scope => {
scope.setPropagationContext({
parentSpanId: '1234567890123456',
traceId: '12345678901234567890123456789012',
sampleRand: Math.random(),
});

const spanIdTraceId = Sentry.startSpan(
{
name: 'test_span_1',
},
span1 => span1.spanContext().traceId,
);

Sentry.startSpan(
{
name: 'test_span_2',
attributes: { spanIdTraceId },
},
() => undefined,
);
});

Sentry.flush();
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { afterAll, expect, test } from 'vitest';
import { cleanupChildProcesses, createRunner } from '../../../../utils/runner';

afterAll(() => {
cleanupChildProcesses();
});

test('sends manually started streamed parallel root spans outside of root context with parentSpanId', async () => {
expect.assertions(6);

await createRunner(__dirname, 'scenario.ts')
.expect({ span: { items: [{ name: 'test_span_1' }] } })
.expect({
span: spanContainer => {
expect(spanContainer).toBeDefined();
const traceId = spanContainer.items[0]!.trace_id;
expect(traceId).toMatch(/^[0-9a-f]{32}$/);
expect(spanContainer.items[0]!.parent_span_id).toBeUndefined();

const trace1Id = spanContainer.items[0]!.attributes?.spanIdTraceId;
expect(trace1Id).toBeDefined();

// Different trace ID as the first span
expect(trace1Id).not.toBe(traceId);
},
})
.start()
.completed();
});
Loading
Loading