Skip to content

Commit 3cec51d

Browse files
committed
feat(core): Pass name & attributes to tracesSampler
1 parent 4097c4a commit 3cec51d

File tree

7 files changed

+82
-13
lines changed

7 files changed

+82
-13
lines changed

MIGRATION.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ npx @sentry/migr8@latest
1010
This will let you select which updates to run, and automatically update your code. Make sure to still review all code
1111
changes!
1212

13+
## Deprecated `transactionContext` passed to `tracesSampler`
14+
15+
Instead of an `transactionContext` being passed to the `tracesSampler` callback, the callback will directly receive
16+
`name` and `attributes` going forward. You can use these to make your sampling decisions, while `transactionContext`
17+
will be removed in v8. Note that the `attributes` are only the attributes at transaction creation time, and some
18+
attributes may only be set later (and thus not be available during sampling).
19+
1320
## Deprecate using `getClient()` to check if the SDK was initialized
1421

1522
In v8, `getClient()` will stop returning `undefined` if `Sentry.init()` was not called. For cases where this may be used

packages/core/src/tracing/hubextensions.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,14 @@ The transaction will not be sampled. Please use the ${configInstrumenter} instru
6565
// eslint-disable-next-line deprecation/deprecation
6666
let transaction = new Transaction(transactionContext, this);
6767
transaction = sampleTransaction(transaction, options, {
68+
name: transactionContext.name,
6869
parentSampled: transactionContext.parentSampled,
6970
transactionContext,
71+
attributes: {
72+
// eslint-disable-next-line deprecation/deprecation
73+
...transactionContext.data,
74+
...transactionContext.attributes,
75+
},
7076
...customSamplingContext,
7177
});
7278
if (transaction.isRecording()) {
@@ -106,8 +112,14 @@ export function startIdleTransaction(
106112
delayAutoFinishUntilSignal,
107113
);
108114
transaction = sampleTransaction(transaction, options, {
115+
name: transactionContext.name,
109116
parentSampled: transactionContext.parentSampled,
110117
transactionContext,
118+
attributes: {
119+
// eslint-disable-next-line deprecation/deprecation
120+
...transactionContext.data,
121+
...transactionContext.attributes,
122+
},
111123
...customSamplingContext,
112124
});
113125
if (transaction.isRecording()) {

packages/core/test/lib/tracing/trace.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
addTracingExtensions,
55
getCurrentScope,
66
makeMain,
7+
setCurrentClient,
78
spanToJSON,
89
withScope,
910
} from '../../../src';
@@ -357,6 +358,35 @@ describe('startSpan', () => {
357358
expect(span).toBeDefined();
358359
});
359360
});
361+
362+
it('samples with a tracesSampler', () => {
363+
const tracesSampler = jest.fn(() => {
364+
return true;
365+
});
366+
367+
const options = getDefaultTestClientOptions({ tracesSampler });
368+
client = new TestClient(options);
369+
setCurrentClient(client);
370+
371+
startSpan(
372+
{ name: 'outer', attributes: { test1: 'aa', test2: 'aa' }, data: { test1: 'bb', test3: 'bb' } },
373+
outerSpan => {
374+
expect(outerSpan).toBeDefined();
375+
},
376+
);
377+
378+
expect(tracesSampler).toBeCalledTimes(1);
379+
expect(tracesSampler).toHaveBeenLastCalledWith({
380+
parentSampled: undefined,
381+
name: 'outer',
382+
attributes: {
383+
test1: 'aa',
384+
test2: 'aa',
385+
test3: 'bb',
386+
},
387+
transactionContext: expect.objectContaining({ name: 'outer', parentSampled: undefined }),
388+
});
389+
});
360390
});
361391

362392
describe('startSpanManual', () => {

packages/opentelemetry-node/src/spanprocessor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export class SentrySpanProcessor implements OtelSpanProcessor {
7979
const transaction = getCurrentHub().startTransaction({
8080
name: otelSpan.name,
8181
...traceCtx,
82+
attributes: otelSpan.attributes,
8283
instrumenter: 'otel',
8384
startTimestamp: convertOtelTimeToSeconds(otelSpan.startTime),
8485
spanId: otelSpanId,

packages/opentelemetry/src/sampler.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Attributes, Context, SpanContext } from '@opentelemetry/api';
33
import { TraceFlags, isSpanContextValid, trace } from '@opentelemetry/api';
44
import type { Sampler, SamplingResult } from '@opentelemetry/sdk-trace-base';
55
import { SamplingDecision } from '@opentelemetry/sdk-trace-base';
6-
import { hasTracingEnabled } from '@sentry/core';
6+
import { SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, hasTracingEnabled } from '@sentry/core';
77
import type { Client, ClientOptions, SamplingContext } from '@sentry/types';
88
import { isNaN, logger } from '@sentry/utils';
99

@@ -27,7 +27,7 @@ export class SentrySampler implements Sampler {
2727
traceId: string,
2828
spanName: string,
2929
_spanKind: unknown,
30-
_attributes: unknown,
30+
spanAttributes: unknown,
3131
_links: unknown,
3232
): SamplingResult {
3333
const options = this._client.getOptions();
@@ -54,6 +54,8 @@ export class SentrySampler implements Sampler {
5454
}
5555

5656
const sampleRate = getSampleRate(options, {
57+
name: spanName,
58+
attributes: spanAttributes,
5759
transactionContext: {
5860
name: spanName,
5961
parentSampled,
@@ -62,7 +64,7 @@ export class SentrySampler implements Sampler {
6264
});
6365

6466
const attributes: Attributes = {
65-
[InternalSentrySemanticAttributes.SAMPLE_RATE]: Number(sampleRate),
67+
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: Number(sampleRate),
6668
};
6769

6870
if (typeof parentSampled === 'boolean') {

packages/opentelemetry/src/spanExporter.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { ExportResult } from '@opentelemetry/core';
33
import { ExportResultCode } from '@opentelemetry/core';
44
import type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
55
import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
6-
import { flush, getCurrentScope } from '@sentry/core';
6+
import { SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, flush, getCurrentScope } from '@sentry/core';
77
import type { Scope, Span as SentrySpan, SpanOrigin, TransactionSource } from '@sentry/types';
88
import { logger } from '@sentry/utils';
99

@@ -176,7 +176,7 @@ function createTransactionForOtelSpan(span: ReadableSpan): OpenTelemetryTransact
176176
metadata: {
177177
dynamicSamplingContext,
178178
source,
179-
sampleRate: span.attributes[InternalSentrySemanticAttributes.SAMPLE_RATE] as number | undefined,
179+
sampleRate: span.attributes[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE] as number | undefined,
180180
...metadata,
181181
},
182182
data: removeSentryAttributes(data),
@@ -267,7 +267,7 @@ function removeSentryAttributes(data: Record<string, unknown>): Record<string, u
267267
delete cleanedData[InternalSentrySemanticAttributes.ORIGIN];
268268
delete cleanedData[InternalSentrySemanticAttributes.OP];
269269
delete cleanedData[InternalSentrySemanticAttributes.SOURCE];
270-
delete cleanedData[InternalSentrySemanticAttributes.SAMPLE_RATE];
270+
delete cleanedData[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE];
271271
/* eslint-enable @typescript-eslint/no-dynamic-delete */
272272

273273
return cleanedData;

packages/opentelemetry/test/trace.test.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { SpanKind } from '@opentelemetry/api';
33
import { TraceFlags, context, trace } from '@opentelemetry/api';
44
import type { ReadableSpan } from '@opentelemetry/sdk-trace-base';
55
import { Span as SpanClass } from '@opentelemetry/sdk-trace-base';
6+
import { SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE } from '@sentry/core';
67
import type { PropagationContext } from '@sentry/types';
78

89
import { getClient } from '../src/custom/hub';
@@ -206,7 +207,7 @@ describe('trace', () => {
206207
span => {
207208
expect(span).toBeDefined();
208209
expect(getSpanAttributes(span)).toEqual({
209-
[InternalSentrySemanticAttributes.SAMPLE_RATE]: 1,
210+
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
210211
});
211212

212213
expect(getSpanMetadata(span)).toEqual(undefined);
@@ -227,7 +228,7 @@ describe('trace', () => {
227228
[InternalSentrySemanticAttributes.SOURCE]: 'task',
228229
[InternalSentrySemanticAttributes.ORIGIN]: 'auto.test.origin',
229230
[InternalSentrySemanticAttributes.OP]: 'my-op',
230-
[InternalSentrySemanticAttributes.SAMPLE_RATE]: 1,
231+
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
231232
});
232233

233234
expect(getSpanMetadata(span)).toEqual({ requestPath: 'test-path' });
@@ -253,7 +254,7 @@ describe('trace', () => {
253254
expect(span).toBeDefined();
254255
expect(getSpanName(span)).toEqual('outer');
255256
expect(getSpanAttributes(span)).toEqual({
256-
[InternalSentrySemanticAttributes.SAMPLE_RATE]: 1,
257+
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
257258
test1: 'test 1',
258259
test2: 2,
259260
});
@@ -326,7 +327,7 @@ describe('trace', () => {
326327

327328
expect(span).toBeDefined();
328329
expect(getSpanAttributes(span)).toEqual({
329-
[InternalSentrySemanticAttributes.SAMPLE_RATE]: 1,
330+
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
330331
});
331332

332333
expect(getSpanMetadata(span)).toEqual(undefined);
@@ -341,7 +342,7 @@ describe('trace', () => {
341342

342343
expect(span2).toBeDefined();
343344
expect(getSpanAttributes(span2)).toEqual({
344-
[InternalSentrySemanticAttributes.SAMPLE_RATE]: 1,
345+
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
345346
[InternalSentrySemanticAttributes.SOURCE]: 'task',
346347
[InternalSentrySemanticAttributes.ORIGIN]: 'auto.test.origin',
347348
[InternalSentrySemanticAttributes.OP]: 'my-op',
@@ -366,7 +367,7 @@ describe('trace', () => {
366367
expect(span).toBeDefined();
367368
expect(getSpanName(span)).toEqual('outer');
368369
expect(getSpanAttributes(span)).toEqual({
369-
[InternalSentrySemanticAttributes.SAMPLE_RATE]: 1,
370+
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
370371
test1: 'test 1',
371372
test2: 2,
372373
});
@@ -451,7 +452,7 @@ describe('trace', () => {
451452
expect(span).toBeDefined();
452453
expect(getSpanName(span)).toEqual('outer');
453454
expect(getSpanAttributes(span)).toEqual({
454-
[InternalSentrySemanticAttributes.SAMPLE_RATE]: 1,
455+
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
455456
test1: 'test 1',
456457
test2: 2,
457458
});
@@ -688,6 +689,10 @@ describe('trace (sampling)', () => {
688689
expect(tracesSampler).toBeCalledTimes(1);
689690
expect(tracesSampler).toHaveBeenLastCalledWith({
690691
parentSampled: undefined,
692+
name: 'outer',
693+
attributes: {
694+
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
695+
},
691696
transactionContext: { name: 'outer', parentSampled: undefined },
692697
});
693698

@@ -705,6 +710,8 @@ describe('trace (sampling)', () => {
705710
expect(tracesSampler).toHaveBeenCalledTimes(3);
706711
expect(tracesSampler).toHaveBeenLastCalledWith({
707712
parentSampled: false,
713+
name: 'inner2',
714+
attributes: {},
708715
transactionContext: { name: 'inner2', parentSampled: false },
709716
});
710717
});
@@ -727,6 +734,10 @@ describe('trace (sampling)', () => {
727734
expect(tracesSampler).toBeCalledTimes(1);
728735
expect(tracesSampler).toHaveBeenLastCalledWith({
729736
parentSampled: undefined,
737+
name: 'outer',
738+
attributes: {
739+
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1,
740+
},
730741
transactionContext: { name: 'outer', parentSampled: undefined },
731742
});
732743

@@ -744,6 +755,8 @@ describe('trace (sampling)', () => {
744755
expect(tracesSampler).toHaveBeenCalledTimes(3);
745756
expect(tracesSampler).toHaveBeenLastCalledWith({
746757
parentSampled: false,
758+
name: 'inner2',
759+
attributes: {},
747760
transactionContext: { name: 'inner2', parentSampled: false },
748761
});
749762

@@ -757,6 +770,8 @@ describe('trace (sampling)', () => {
757770
expect(tracesSampler).toHaveBeenCalledTimes(4);
758771
expect(tracesSampler).toHaveBeenLastCalledWith({
759772
parentSampled: undefined,
773+
name: 'outer3',
774+
attributes: {},
760775
transactionContext: { name: 'outer3', parentSampled: undefined },
761776
});
762777
});
@@ -799,6 +814,8 @@ describe('trace (sampling)', () => {
799814
expect(tracesSampler).toBeCalledTimes(1);
800815
expect(tracesSampler).toHaveBeenLastCalledWith({
801816
parentSampled: true,
817+
name: 'outer',
818+
attributes: {},
802819
transactionContext: {
803820
name: 'outer',
804821
parentSampled: true,

0 commit comments

Comments
 (0)