Skip to content

Commit

Permalink
feat(interactions): Add interactions sample rate to browser tracing i…
Browse files Browse the repository at this point in the history
…ntegrations (#11382)

Adds a `interactionsSampleRate` option to browser tracing integrations
to allow users to apply an additional sample rate filter on interaction
spans.

`interactionsSampleRate` is applied on top of the global
`tracesSampleRate`.
Therefore if `interactionsSampleRate` is `0.5` and `tracesSampleRate` is
`0.1`, then the actual sample rate for interactions is `0.05`
  • Loading branch information
edwardgou-sentry authored Apr 3, 2024
1 parent 264d9b1 commit 7dae9f6
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ export interface BrowserTracingOptions extends RequestInstrumentationOptions {
*/
enableInp: boolean;

/**
* Sample rate to determine interaction span sampling.
* interactionsSampleRate is applied on top of the global tracesSampleRate.
* ie a tracesSampleRate of 0.1 and interactionsSampleRate of 0.5 will result in a 0.05 sample rate for interactions.
*
* Default: 1
*/
interactionsSampleRate: number;

/**
* _metricOptions allows the user to send options to change how metrics are collected.
*
Expand Down Expand Up @@ -154,6 +163,7 @@ const DEFAULT_BROWSER_TRACING_OPTIONS: BrowserTracingOptions = {
markBackgroundSpan: true,
enableLongTask: true,
enableInp: false,
interactionsSampleRate: 1,
_experiments: {},
...defaultRequestInstrumentationOptions,
};
Expand Down Expand Up @@ -196,7 +206,7 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
/** Stores a mapping of interactionIds from PerformanceEventTimings to the origin interaction path */
const interactionIdToRouteNameMapping: InteractionRouteNameMapping = {};
if (options.enableInp) {
startTrackingINP(interactionIdToRouteNameMapping);
startTrackingINP(interactionIdToRouteNameMapping, options.interactionsSampleRate);
}

if (options.enableLongTask) {
Expand Down
12 changes: 11 additions & 1 deletion packages/tracing-internal/src/browser/browsertracing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,15 @@ export interface BrowserTracingOptions extends RequestInstrumentationOptions {
*/
enableInp: boolean;

/**
* Sample rate to determine interaction span sampling.
* interactionsSampleRate is applied on top of the global tracesSampleRate.
* ie a tracesSampleRate of 0.1 and interactionsSampleRate of 0.5 will result in a 0.05 sample rate for interactions.
*
* Default: 1
*/
interactionsSampleRate: number;

/**
* _metricOptions allows the user to send options to change how metrics are collected.
*
Expand Down Expand Up @@ -158,6 +167,7 @@ const DEFAULT_BROWSER_TRACING_OPTIONS: BrowserTracingOptions = {
startTransactionOnPageLoad: true,
enableLongTask: true,
enableInp: false,
interactionsSampleRate: 1,
_experiments: {},
...defaultRequestInstrumentationOptions,
};
Expand Down Expand Up @@ -238,7 +248,7 @@ export class BrowserTracing implements Integration {
this._interactionIdToRouteNameMapping = {};

if (this.options.enableInp) {
startTrackingINP(this._interactionIdToRouteNameMapping);
startTrackingINP(this._interactionIdToRouteNameMapping, this.options.interactionsSampleRate);
}
if (this.options.enableLongTask) {
startTrackingLongTasks();
Expand Down
30 changes: 23 additions & 7 deletions packages/tracing-internal/src/browser/metrics/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,13 @@ export function startTrackingInteractions(): void {
/**
* Start tracking INP webvital events.
*/
export function startTrackingINP(interactionIdtoRouteNameMapping: InteractionRouteNameMapping): () => void {
export function startTrackingINP(
interactionIdtoRouteNameMapping: InteractionRouteNameMapping,
interactionsSampleRate: number,
): () => void {
const performance = getBrowserPerformanceAPI();
if (performance && browserPerformanceTimeOrigin) {
const inpCallback = _trackINP(interactionIdtoRouteNameMapping);
const inpCallback = _trackINP(interactionIdtoRouteNameMapping, interactionsSampleRate);

return (): void => {
inpCallback();
Expand Down Expand Up @@ -247,7 +250,10 @@ const INP_ENTRY_MAP: Record<string, 'click' | 'hover' | 'drag' | 'press'> = {
};

/** Starts tracking the Interaction to Next Paint on the current page. */
function _trackINP(interactionIdToRouteNameMapping: InteractionRouteNameMapping): () => void {
function _trackINP(
interactionIdToRouteNameMapping: InteractionRouteNameMapping,
interactionsSampleRate: number,
): () => void {
return addInpInstrumentationHandler(({ metric }) => {
if (metric.value === undefined) {
return;
Expand Down Expand Up @@ -293,7 +299,8 @@ function _trackINP(interactionIdToRouteNameMapping: InteractionRouteNameMapping)
});

/** Check to see if the span should be sampled */
const sampleRate = getSampleRate(parentContext, options);
const sampleRate = getSampleRate(parentContext, options, interactionsSampleRate);

if (!sampleRate) {
return;
}
Expand Down Expand Up @@ -690,7 +697,11 @@ function _addTtfbRequestTimeToMeasurements(_measurements: Measurements): void {
}

/** Taken from @sentry/core sampling.ts */
function getSampleRate(transactionContext: TransactionContext | undefined, options: ClientOptions): number | boolean {
function getSampleRate(
transactionContext: TransactionContext | undefined,
options: ClientOptions,
interactionsSampleRate: number,
): number | boolean {
if (!hasTracingEnabled(options)) {
return false;
}
Expand All @@ -715,8 +726,13 @@ function getSampleRate(transactionContext: TransactionContext | undefined, optio
sampleRate = 1;
}
if (!isValidSampleRate(sampleRate)) {
DEBUG_BUILD && logger.warn('[Tracing] Discarding transaction because of invalid sample rate.');
DEBUG_BUILD && logger.warn('[Tracing] Discarding interaction span because of invalid sample rate.');
return false;
}
return sampleRate;
if (sampleRate === true) {
return interactionsSampleRate;
} else if (sampleRate === false) {
return 0;
}
return sampleRate * interactionsSampleRate;
}
3 changes: 3 additions & 0 deletions packages/tracing-internal/test/browser/browsertracing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ conditionalTest({ min: 10 })('BrowserTracing', () => {

expect(browserTracing.options).toEqual({
enableInp: false,
interactionsSampleRate: 1,
enableLongTask: true,
_experiments: {},
...TRACING_DEFAULTS,
Expand All @@ -112,6 +113,7 @@ conditionalTest({ min: 10 })('BrowserTracing', () => {

expect(browserTracing.options).toEqual({
enableInp: false,
interactionsSampleRate: 1,
enableLongTask: false,
...TRACING_DEFAULTS,
markBackgroundTransactions: true,
Expand All @@ -132,6 +134,7 @@ conditionalTest({ min: 10 })('BrowserTracing', () => {

expect(browserTracing.options).toEqual({
enableInp: false,
interactionsSampleRate: 1,
enableLongTask: false,
_experiments: {},
...TRACING_DEFAULTS,
Expand Down

0 comments on commit 7dae9f6

Please sign in to comment.