Skip to content

ref: Read propagation context off of scope and isolation scope when propagating and applying trace context #10297

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jan 29, 2024
Merged
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
9 changes: 5 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ able to use it. From the top level of the repo, there are three commands availab
dependencies (`utils`, `core`, `browser`, etc), and all packages which depend on it (currently `gatsby` and `nextjs`))
- `yarn build:dev:watch`, which runs `yarn build:dev` in watch mode (recommended)

You can also run a production build via `yarn build`, which will build everything except for the tarballs for publishing to NPM.
You can use this if you want to bundle Sentry yourself. The build output can be found in the packages `build/` folder, e.g. `packages/browser/build`.
Bundled files can be found in `packages/browser/build/bundles`.
Note that there are no guarantees about the produced file names etc., so make sure to double check which files are generated after upgrading.
You can also run a production build via `yarn build`, which will build everything except for the tarballs for publishing
to NPM. You can use this if you want to bundle Sentry yourself. The build output can be found in the packages `build/`
folder, e.g. `packages/browser/build`. Bundled files can be found in `packages/browser/build/bundles`. Note that there
are no guarantees about the produced file names etc., so make sure to double check which files are generated after
upgrading.

## Testing SDK Packages Locally

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ afterAll(() => {
cleanupChildProcesses();
});

test('Should not overwrite baggage if the incoming request already has Sentry baggage data.', async () => {
test('Should overwrite baggage if the incoming request already has Sentry baggage data but no sentry-trace', async () => {
const runner = createRunner(__dirname, '..', 'server.ts').start();

const response = await runner.makeRequest<TestAPIResponse>('get', '/test/express', {
baggage: 'sentry-release=2.0.0,sentry-environment=myEnv',
});

expect(response).toBeDefined();
expect(response).toMatchObject({
expect(response).not.toMatchObject({
test_data: {
host: 'somewhere.not.sentry',
baggage: 'sentry-release=2.0.0,sentry-environment=myEnv',
Expand All @@ -25,7 +25,7 @@ test('Should propagate sentry trace baggage data from an incoming to an outgoing
const runner = createRunner(__dirname, '..', 'server.ts').start();

const response = await runner.makeRequest<TestAPIResponse>('get', '/test/express', {
'sentry-trace': '',
'sentry-trace': '12312012123120121231201212312012-1121201211212012-1',
baggage: 'sentry-release=2.0.0,sentry-environment=myEnv,dogs=great',
});

Expand All @@ -38,11 +38,28 @@ test('Should propagate sentry trace baggage data from an incoming to an outgoing
});
});

test('Should not propagate baggage if sentry-trace header is present in incoming request but no baggage header', async () => {
test('Should not propagate baggage data from an incoming to an outgoing request if sentry-trace is faulty.', async () => {
const runner = createRunner(__dirname, '..', 'server.ts').start();

const response = await runner.makeRequest<TestAPIResponse>('get', '/test/express', {
'sentry-trace': '',
baggage: 'sentry-release=2.0.0,sentry-environment=myEnv,dogs=great',
});

expect(response).toBeDefined();
expect(response).not.toMatchObject({
test_data: {
host: 'somewhere.not.sentry',
baggage: 'sentry-release=2.0.0,sentry-environment=myEnv',
},
});
});

test('Should not propagate baggage if sentry-trace header is present in incoming request but no baggage header', async () => {
const runner = createRunner(__dirname, '..', 'server.ts').start();

const response = await runner.makeRequest<TestAPIResponse>('get', '/test/express', {
'sentry-trace': '12312012123120121231201212312012-1121201211212012-1',
});

expect(response).toBeDefined();
Expand All @@ -57,7 +74,7 @@ test('Should not propagate baggage and ignore original 3rd party baggage entries
const runner = createRunner(__dirname, '..', 'server.ts').start();

const response = await runner.makeRequest<TestAPIResponse>('get', '/test/express', {
'sentry-trace': '',
'sentry-trace': '12312012123120121231201212312012-1121201211212012-1',
baggage: 'foo=bar',
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ test('should ignore sentry-values in `baggage` header of a third party vendor an
const runner = createRunner(__dirname, 'server.ts').start();

const response = await runner.makeRequest<TestAPIResponse>('get', '/test/express', {
'sentry-trace': '',
'sentry-trace': '12312012123120121231201212312012-1121201211212012-1',
baggage: 'sentry-release=2.1.0,sentry-environment=myEnv',
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ test('should merge `baggage` header of a third party vendor with the Sentry DSC
const runner = createRunner(__dirname, 'server.ts').start();

const response = await runner.makeRequest<TestAPIResponse>('get', '/test/express', {
'sentry-trace': '',
'sentry-trace': '12312012123120121231201212312012-1121201211212012-1',
baggage: 'sentry-release=2.0.0,sentry-environment=myEnv',
});

Expand Down
12 changes: 6 additions & 6 deletions packages/core/src/baseclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import type {
MetricsAggregator,
Outcome,
ParameterizedString,
PropagationContext,
SdkMetadata,
Session,
SessionAggregates,
Expand Down Expand Up @@ -662,13 +661,14 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
return evt;
}

// If a trace context is not set on the event, we use the propagationContext set on the event to
// generate a trace context. If the propagationContext does not have a dynamic sampling context, we
// also generate one for it.
const { propagationContext } = evt.sdkProcessingMetadata || {};
const propagationContext = {
...isolationScope.getPropagationContext(),
...(scope ? scope.getPropagationContext() : undefined),
};

const trace = evt.contexts && evt.contexts.trace;
if (!trace && propagationContext) {
const { traceId: trace_id, spanId, parentSpanId, dsc } = propagationContext as PropagationContext;
const { traceId: trace_id, spanId, parentSpanId, dsc } = propagationContext;
evt.contexts = {
trace: {
trace_id,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/tracing/trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ export function continueTrace<V>(
const transactionContext: Partial<TransactionContext> = {
...traceparentData,
metadata: dropUndefinedKeys({
dynamicSamplingContext: traceparentData && !dynamicSamplingContext ? {} : dynamicSamplingContext,
dynamicSamplingContext,
}),
};

Expand Down
13 changes: 4 additions & 9 deletions packages/core/src/utils/applyScopeDataToEvent.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Breadcrumb, Event, PropagationContext, ScopeData, Span } from '@sentry/types';
import type { Breadcrumb, Event, ScopeData, Span } from '@sentry/types';
import { arrayify, dropUndefinedKeys } from '@sentry/utils';
import { getDynamicSamplingContextFromSpan } from '../tracing/dynamicSamplingContext';
import { getRootSpan } from './getRootSpan';
Expand All @@ -8,7 +8,7 @@ import { spanToJSON, spanToTraceContext } from './spanUtils';
* Applies data from the scope to the event and runs all event processors on it.
*/
export function applyScopeDataToEvent(event: Event, data: ScopeData): void {
const { fingerprint, span, breadcrumbs, sdkProcessingMetadata, propagationContext } = data;
const { fingerprint, span, breadcrumbs, sdkProcessingMetadata } = data;

// Apply general data
applyDataToEvent(event, data);
Expand All @@ -22,7 +22,7 @@ export function applyScopeDataToEvent(event: Event, data: ScopeData): void {

applyFingerprintToEvent(event, fingerprint);
applyBreadcrumbsToEvent(event, breadcrumbs);
applySdkMetadataToEvent(event, sdkProcessingMetadata, propagationContext);
applySdkMetadataToEvent(event, sdkProcessingMetadata);
}

/** Merge data of two scopes together. */
Expand Down Expand Up @@ -163,15 +163,10 @@ function applyBreadcrumbsToEvent(event: Event, breadcrumbs: Breadcrumb[]): void
event.breadcrumbs = mergedBreadcrumbs.length ? mergedBreadcrumbs : undefined;
}

function applySdkMetadataToEvent(
event: Event,
sdkProcessingMetadata: ScopeData['sdkProcessingMetadata'],
propagationContext: PropagationContext,
): void {
function applySdkMetadataToEvent(event: Event, sdkProcessingMetadata: ScopeData['sdkProcessingMetadata']): void {
event.sdkProcessingMetadata = {
...event.sdkProcessingMetadata,
...sdkProcessingMetadata,
propagationContext: propagationContext,
};
}

Expand Down
17 changes: 5 additions & 12 deletions packages/core/test/lib/prepareEvent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,7 @@ describe('prepareEvent', () => {
event_id: expect.any(String),
environment: 'production',
message: 'foo',
sdkProcessingMetadata: {
propagationContext: {
spanId: expect.any(String),
traceId: expect.any(String),
},
},
sdkProcessingMetadata: {},
});
});

Expand Down Expand Up @@ -309,16 +304,15 @@ describe('prepareEvent', () => {
user: { id: '1', email: '[email protected]' },
tags: { tag1: 'aa', tag2: 'aa' },
extra: { extra1: 'aa', extra2: 'aa' },
contexts: { os: { name: 'os1' }, culture: { display_name: 'name1' } },
contexts: {
os: { name: 'os1' },
culture: { display_name: 'name1' },
},
fingerprint: ['dd', 'aa'],
breadcrumbs: [breadcrumb4, breadcrumb2, breadcrumb3, breadcrumb1],
sdkProcessingMetadata: {
aa: 'aa',
bb: 'bb',
propagationContext: {
spanId: '1',
traceId: '1',
},
},
});
});
Expand Down Expand Up @@ -382,7 +376,6 @@ describe('prepareEvent', () => {
sdkProcessingMetadata: {
aa: 'aa',
bb: 'bb',
propagationContext: isolationScope.getPropagationContext(),
},
});
});
Expand Down
16 changes: 5 additions & 11 deletions packages/core/test/lib/scope.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,7 @@ describe('Scope', () => {

expect(event).toEqual({
message: 'foo',
sdkProcessingMetadata: {
propagationContext: {
spanId: expect.any(String),
traceId: expect.any(String),
},
},
sdkProcessingMetadata: {},
});
});

Expand Down Expand Up @@ -166,15 +161,14 @@ describe('Scope', () => {
user: { id: '1', email: '[email protected]' },
tags: { tag1: 'aa', tag2: 'aa' },
extra: { extra1: 'aa', extra2: 'aa' },
contexts: { os: { name: 'os1' }, culture: { display_name: 'name1' } },
contexts: {
os: { name: 'os1' },
culture: { display_name: 'name1' },
},
fingerprint: ['dd', 'aa'],
breadcrumbs: [breadcrumb2, breadcrumb1],
sdkProcessingMetadata: {
aa: 'aa',
propagationContext: {
spanId: '1',
traceId: '1',
},
},
});
});
Expand Down
1 change: 1 addition & 0 deletions packages/core/test/lib/tracing/trace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ describe('continueTrace', () => {
const scope = getCurrentScope();

expect(scope.getPropagationContext()).toEqual({
dsc: {}, // DSC should be an empty object (frozen), because there was an incoming trace
sampled: false,
parentSpanId: '1121201211212012',
spanId: expect.any(String),
Expand Down
2 changes: 0 additions & 2 deletions packages/hub/test/scope.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,6 @@ describe('Scope', () => {
expect(processedEvent!.contexts).toEqual({ os: { id: '1' } });
expect(processedEvent!.sdkProcessingMetadata).toEqual({
dogs: 'are great!',
// @ts-expect-error accessing private property for test
propagationContext: scope._propagationContext,
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,6 @@ describe('Integration | Transactions', () => {
trace_id: expect.any(String),
transaction: 'test name',
}),
propagationContext: {
sampled: undefined,
spanId: expect.any(String),
traceId: expect.any(String),
},
sampleRate: 1,
source: 'task',
spanMetadata: expect.any(Object),
Expand Down
16 changes: 5 additions & 11 deletions packages/node-experimental/test/sdk/scope.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,7 @@ describe('Unit | Scope', () => {
event_id: expect.any(String),
environment: 'production',
message: 'foo',
sdkProcessingMetadata: {
propagationContext: {
spanId: expect.any(String),
traceId: expect.any(String),
},
},
sdkProcessingMetadata: {},
});
});

Expand Down Expand Up @@ -213,16 +208,15 @@ describe('Unit | Scope', () => {
user: { id: '1', email: '[email protected]' },
tags: { tag1: 'aa', tag2: 'aa' },
extra: { extra1: 'aa', extra2: 'aa' },
contexts: { os: { name: 'os1' }, culture: { display_name: 'name1' } },
contexts: {
os: { name: 'os1' },
culture: { display_name: 'name1' },
},
fingerprint: ['dd', 'aa'],
breadcrumbs: [breadcrumb4, breadcrumb2, breadcrumb3, breadcrumb1],
sdkProcessingMetadata: {
aa: 'aa',
bb: 'bb',
propagationContext: {
spanId: '1',
traceId: '1',
},
},
});
});
Expand Down
Loading