Skip to content

Commit 07ece22

Browse files
Merge branch 'staging-38' into fix-merge-b4ff364e61-into-staging-38
2 parents 1003c72 + 0ed9fb1 commit 07ece22

24 files changed

+380
-209
lines changed

packages/core/src/domain/telemetry/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export type { Telemetry } from './telemetry'
1+
export type { Telemetry, SampleRateByMetric } from './telemetry'
22
export {
33
TelemetryService,
44
addTelemetryDebug,

packages/core/src/domain/telemetry/telemetry.spec.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@ import {
2020
startTelemetryCollection,
2121
addTelemetryMetrics,
2222
addTelemetryDebug,
23+
type SampleRateByMetric,
2324
} from './telemetry'
2425
import type { TelemetryEvent } from './telemetryEvent.types'
2526
import { StatusType, TelemetryType } from './rawTelemetryEvent.types'
2627

2728
const NETWORK_METRICS_KIND = 'Network metrics'
2829
const PERFORMANCE_METRICS_KIND = 'Performance metrics'
2930

30-
function startAndSpyTelemetry(configuration?: Partial<Configuration>) {
31+
function startAndSpyTelemetry(configuration?: Partial<Configuration>, sampleRateByMetric: SampleRateByMetric = {}) {
3132
const observable = new Observable<TelemetryEvent & Context>()
3233

3334
const events: TelemetryEvent[] = []
@@ -42,7 +43,8 @@ function startAndSpyTelemetry(configuration?: Partial<Configuration>) {
4243
...configuration,
4344
} as Configuration,
4445
hooks,
45-
observable
46+
observable,
47+
sampleRateByMetric
4648
)
4749

4850
return {
@@ -157,7 +159,10 @@ describe('telemetry', () => {
157159

158160
describe('addTelemetryMetrics', () => {
159161
it('should collect metrics when sampled', async () => {
160-
const { getTelemetryEvents } = startAndSpyTelemetry({ telemetrySampleRate: 100 })
162+
const { getTelemetryEvents } = startAndSpyTelemetry(
163+
{ telemetrySampleRate: 100 },
164+
{ [PERFORMANCE_METRICS_KIND]: 100 }
165+
)
161166

162167
addTelemetryMetrics(PERFORMANCE_METRICS_KIND, { speed: 1000 })
163168

@@ -172,8 +177,22 @@ describe('telemetry', () => {
172177
])
173178
})
174179

175-
it('should not notify metrics when not sampled', async () => {
176-
const { getTelemetryEvents } = startAndSpyTelemetry({ telemetrySampleRate: 0 })
180+
it('should not notify metrics when telemetry not sampled', async () => {
181+
const { getTelemetryEvents } = startAndSpyTelemetry(
182+
{ telemetrySampleRate: 0 },
183+
{ [PERFORMANCE_METRICS_KIND]: 100 }
184+
)
185+
186+
addTelemetryMetrics(PERFORMANCE_METRICS_KIND, { speed: 1000 })
187+
188+
expect(await getTelemetryEvents()).toEqual([])
189+
})
190+
191+
it('should not notify metrics when metric not sampled', async () => {
192+
const { getTelemetryEvents } = startAndSpyTelemetry(
193+
{ telemetrySampleRate: 100 },
194+
{ [PERFORMANCE_METRICS_KIND]: 0 }
195+
)
177196

178197
addTelemetryMetrics(PERFORMANCE_METRICS_KIND, { speed: 1000 })
179198

packages/core/src/domain/telemetry/telemetry.ts

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ export const enum TelemetryService {
5959
export interface Telemetry {
6060
stop: () => void
6161
enabled: boolean
62+
enabledMetrics: { [metricName: string]: boolean }
63+
}
64+
65+
export interface SampleRateByMetric {
66+
[metricName: string]: number
6267
}
6368

6469
const TELEMETRY_EXCLUDED_SITES: string[] = [INTAKE_SITE_US1_FED]
@@ -78,25 +83,34 @@ export function startTelemetry(
7883
hooks: AbstractHooks,
7984
reportError: (error: RawError) => void,
8085
pageMayExitObservable: Observable<PageMayExitEvent>,
81-
createEncoder: (streamId: DeflateEncoderStreamId) => Encoder
86+
createEncoder: (streamId: DeflateEncoderStreamId) => Encoder,
87+
sampleRateByMetric: SampleRateByMetric = {}
8288
): Telemetry {
8389
const observable = new Observable<TelemetryEvent & Context>()
8490

8591
const { stop } = startTelemetryTransport(configuration, reportError, pageMayExitObservable, createEncoder, observable)
8692

87-
const { enabled } = startTelemetryCollection(telemetryService, configuration, hooks, observable)
93+
const { enabled, enabledMetrics } = startTelemetryCollection(
94+
telemetryService,
95+
configuration,
96+
hooks,
97+
observable,
98+
sampleRateByMetric
99+
)
88100

89101
return {
90102
stop,
91103
enabled,
104+
enabledMetrics,
92105
}
93106
}
94107

95108
export function startTelemetryCollection(
96109
telemetryService: TelemetryService,
97110
configuration: Configuration,
98111
hooks: AbstractHooks,
99-
observable: Observable<TelemetryEvent & Context>
112+
observable: Observable<TelemetryEvent & Context>,
113+
sampleRateByMetric: SampleRateByMetric
100114
) {
101115
const alreadySentEventsByKind: Record<string, Set<string>> = {}
102116

@@ -109,10 +123,18 @@ export function startTelemetryCollection(
109123
[TelemetryType.USAGE]: telemetryEnabled && performDraw(configuration.telemetryUsageSampleRate),
110124
}
111125

126+
const telemetryEnabledPerMetrics: { [metricName: string]: boolean } = {}
127+
Object.keys(sampleRateByMetric).forEach((metricName) => {
128+
telemetryEnabledPerMetrics[metricName] = telemetryEnabled && performDraw(sampleRateByMetric[metricName])
129+
})
130+
112131
const runtimeEnvInfo = getRuntimeEnvInfo()
113132
const telemetryObservable = getTelemetryObservable()
114133
telemetryObservable.subscribe(({ rawEvent, kind }) => {
115-
if (!telemetryEnabledPerType[rawEvent.type!]) {
134+
if (
135+
!telemetryEnabledPerType[rawEvent.type!] ||
136+
(kind in telemetryEnabledPerMetrics && !telemetryEnabledPerMetrics[kind])
137+
) {
116138
return
117139
}
118140

@@ -154,6 +176,7 @@ export function startTelemetryCollection(
154176

155177
return {
156178
enabled: telemetryEnabled,
179+
enabledMetrics: telemetryEnabledPerMetrics,
157180
}
158181

159182
function toTelemetryEvent(

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export type {
4040
TelemetryUsageEvent,
4141
RawTelemetryUsage,
4242
RawTelemetryUsageFeature,
43+
SampleRateByMetric,
4344
} from './domain/telemetry'
4445
export {
4546
startTelemetry,

packages/rum-core/src/boot/rumPublicApi.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {
1313
Account,
1414
RumInternalContext,
1515
Telemetry,
16+
SampleRateByMetric,
1617
} from '@datadog/browser-core'
1718
import {
1819
ContextManagerMethod,
@@ -473,6 +474,7 @@ export interface RecorderApi {
473474
isRecording: () => boolean
474475
getReplayStats: (viewId: string) => ReplayStats | undefined
475476
getSessionReplayLink: () => string | undefined
477+
getTelemetrySampleRateByMetric: (configuration: RumConfiguration) => SampleRateByMetric | undefined
476478
}
477479

478480
export interface ProfilerApi {

packages/rum-core/src/boot/startRum.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ import { startRumEventBridge } from '../transport/startRumEventBridge'
3535
import { startUrlContexts } from '../domain/contexts/urlContexts'
3636
import { createLocationChangeObservable } from '../browser/locationChangeObservable'
3737
import type { RumConfiguration } from '../domain/configuration'
38+
import { REMOTE_CONFIGURATION_METRIC_NAME } from '../domain/configuration'
3839
import type { ViewOptions } from '../domain/view/trackViews'
3940
import { startFeatureFlagContexts } from '../domain/contexts/featureFlagContext'
40-
import { startCustomerDataTelemetry } from '../domain/startCustomerDataTelemetry'
41+
import { startCustomerDataTelemetry, CUSTOMER_DATA_METRIC_NAME } from '../domain/startCustomerDataTelemetry'
4142
import type { PageStateHistory } from '../domain/contexts/pageStateHistory'
4243
import { startPageStateHistory } from '../domain/contexts/pageStateHistory'
4344
import { startDisplayContext } from '../domain/contexts/displayContext'
@@ -94,13 +95,20 @@ export function startRum(
9495
})
9596
cleanupTasks.push(() => pageMayExitSubscription.unsubscribe())
9697

98+
const sampleRateByMetric = {
99+
[CUSTOMER_DATA_METRIC_NAME]: configuration.customerDataTelemetrySampleRate,
100+
[REMOTE_CONFIGURATION_METRIC_NAME]: configuration.remoteConfigurationTelemetrySampleRate,
101+
...recorderApi.getTelemetrySampleRateByMetric(configuration),
102+
}
103+
97104
const telemetry = startTelemetry(
98105
TelemetryService.RUM,
99106
configuration,
100107
hooks,
101108
reportError,
102109
pageMayExitObservable,
103-
createEncoder
110+
createEncoder,
111+
sampleRateByMetric
104112
)
105113
cleanupTasks.push(telemetry.stop)
106114

@@ -118,7 +126,7 @@ export function startRum(
118126
createEncoder
119127
)
120128
cleanupTasks.push(() => batch.stop())
121-
startCustomerDataTelemetry(configuration, telemetry, lifeCycle, batch.flushController.flushObservable)
129+
startCustomerDataTelemetry(telemetry, lifeCycle, batch.flushController.flushObservable)
122130
} else {
123131
startRumEventBridge(lifeCycle)
124132
}

packages/rum-core/src/domain/configuration/configuration.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ export interface RumConfiguration extends Configuration {
271271
customerDataTelemetrySampleRate: number
272272
initialViewMetricsTelemetrySampleRate: number
273273
replayTelemetrySampleRate: number
274+
remoteConfigurationTelemetrySampleRate: number
274275
traceContextInjection: TraceContextInjection
275276
plugins: RumPlugin[]
276277
trackFeatureFlagsForEvents: FeatureFlagsForEvents[]
@@ -348,6 +349,7 @@ export function validateAndBuildRumConfiguration(
348349
customerDataTelemetrySampleRate: 1,
349350
initialViewMetricsTelemetrySampleRate: 1,
350351
replayTelemetrySampleRate: 1,
352+
remoteConfigurationTelemetrySampleRate: 1,
351353
traceContextInjection: objectHasValue(TraceContextInjection, initConfiguration.traceContextInjection)
352354
? initConfiguration.traceContextInjection
353355
: TraceContextInjection.SAMPLED,

0 commit comments

Comments
 (0)