Skip to content
Open
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,5 @@ packages/react-native-babel-plugin/svg-map.json

# Session Replay assets
packages/react-native-session-replay/assets/*

.planning
18 changes: 17 additions & 1 deletion packages/core/src/DdSdkReactNative.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,12 @@ export class DdSdkReactNative {
const resourceTraceSampleRate =
configuration.rumConfiguration?.resourceTraceSampleRate ||
RUM_DEFAULTS.resourceTraceSampleRate;
const trackResourceHeaders =
configuration.rumConfiguration?.trackResourceHeaders ||
RUM_DEFAULTS.trackResourceHeaders;
const headerCaptureRules =
configuration.rumConfiguration?.headerCaptureRules ||
RUM_DEFAULTS.headerCaptureRules;
const logEventMapper = configuration.logsConfiguration?.logEventMapper;
const errorEventMapper =
configuration.rumConfiguration?.errorEventMapper;
Expand Down Expand Up @@ -550,10 +556,20 @@ export class DdSdkReactNative {
});
}

if (trackResourceHeaders && !trackResources) {
InternalLog.log(
'trackResourceHeaders is set but trackResources is false. Header capture will be disabled.',
SdkVerbosity.WARN
);
}

if (trackResources) {
DdRumResourceTracking.startTracking({
resourceTraceSampleRate,
firstPartyHosts
firstPartyHosts,
headerCaptureRules: trackResourceHeaders
? headerCaptureRules
: undefined
});
}

Expand Down
128 changes: 127 additions & 1 deletion packages/core/src/__tests__/DdSdkReactNative.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { version as reactNativeVersion } from 'react-native/package.json';
import { NativeModules } from 'react-native';

import { DdSdkReactNative } from '../DdSdkReactNative';
import { InternalLog } from '../InternalLog';
import type { DdSdkNativeConfiguration } from '../config/features/CoreConfigurationNative';
import { CoreConfiguration } from '../config/features/CoreConfiguration';
import { LogsConfiguration } from '../config/features/LogsConfiguration';
Expand Down Expand Up @@ -676,10 +677,135 @@ describe('DdSdkReactNative', () => {
match: 'something.fr',
propagatorTypes: ['datadog']
}
]
],
headerCaptureRules: undefined
Comment thread
marco-saia-datadog marked this conversation as resolved.
});
});

it('enables header capture with the default headerCaptureRules when trackResourceHeaders is true', async () => {
// GIVEN
const fakeAppId = '1';
const fakeClientToken = '2';
const fakeEnvName = 'env';
const configuration = new CoreConfiguration(
fakeClientToken,
fakeEnvName
);
configuration.rumConfiguration = new RumConfiguration(
fakeAppId,
false,
true
);
configuration.rumConfiguration.trackResourceHeaders = true;

NativeModules.DdSdk.initialize.mockResolvedValue(null);

// WHEN
await DdSdkReactNative.initialize(configuration);

// THEN
expect(DdRumResourceTracking.startTracking).toHaveBeenCalledWith(
expect.objectContaining({
headerCaptureRules: 'defaults'
})
);
});

it('uses the custom headerCaptureRules when trackResourceHeaders is true', async () => {
// GIVEN
const fakeAppId = '1';
const fakeClientToken = '2';
const fakeEnvName = 'env';
const configuration = new CoreConfiguration(
fakeClientToken,
fakeEnvName
);
configuration.rumConfiguration = new RumConfiguration(
fakeAppId,
false,
true
);
configuration.rumConfiguration.trackResourceHeaders = true;
configuration.rumConfiguration.headerCaptureRules = [
{ type: 'matchHeaders', headers: ['x-request-id'] }
];

NativeModules.DdSdk.initialize.mockResolvedValue(null);

// WHEN
await DdSdkReactNative.initialize(configuration);

// THEN
expect(DdRumResourceTracking.startTracking).toHaveBeenCalledWith(
expect.objectContaining({
headerCaptureRules: [
{ type: 'matchHeaders', headers: ['x-request-id'] }
]
})
);
});

it('ignores headerCaptureRules when trackResourceHeaders is false', async () => {
// GIVEN
const fakeAppId = '1';
const fakeClientToken = '2';
const fakeEnvName = 'env';
const configuration = new CoreConfiguration(
fakeClientToken,
fakeEnvName
);
configuration.rumConfiguration = new RumConfiguration(
fakeAppId,
false,
true
);
configuration.rumConfiguration.trackResourceHeaders = false;
configuration.rumConfiguration.headerCaptureRules = [
{ type: 'matchHeaders', headers: ['x-request-id'] }
];

NativeModules.DdSdk.initialize.mockResolvedValue(null);

// WHEN
await DdSdkReactNative.initialize(configuration);

// THEN
expect(DdRumResourceTracking.startTracking).toHaveBeenCalledWith(
expect.objectContaining({
headerCaptureRules: undefined
})
);
});

it('logs a warning and disables header capture when trackResourceHeaders is true but trackResources is false', async () => {
// GIVEN
const fakeAppId = '1';
const fakeClientToken = '2';
const fakeEnvName = 'env';
const configuration = new CoreConfiguration(
fakeClientToken,
fakeEnvName
);
configuration.rumConfiguration = new RumConfiguration(
fakeAppId,
false,
false
);
configuration.rumConfiguration.trackResourceHeaders = true;

NativeModules.DdSdk.initialize.mockResolvedValue(null);

// WHEN
await DdSdkReactNative.initialize(configuration);

// THEN
expect(DdRumResourceTracking.startTracking).not.toHaveBeenCalled();
expect(InternalLog.log).toHaveBeenCalledWith(
'trackResourceHeaders is set but trackResources is false. Header capture will be disabled.',
SdkVerbosity.WARN
);
});

it('enables error tracking feature when initialize { error tracking config enabled }', async () => {
// GIVEN
const fakeAppId = '1';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ describe('DdSdkReactNativeConfiguration', () => {
"customEndpoint": undefined,
"errorEventMapper": null,
"firstPartyHosts": [],
"headerCaptureRules": "defaults",
"initialResourceThreshold": undefined,
"longTaskThresholdMs": 0,
"nativeCrashReportEnabled": false,
Expand All @@ -77,6 +78,7 @@ describe('DdSdkReactNativeConfiguration', () => {
"trackInteractions": false,
"trackMemoryWarnings": true,
"trackNonFatalAnrs": undefined,
"trackResourceHeaders": false,
"trackResources": false,
"trackWatchdogTerminations": false,
"useAccessibilityLabel": true,
Expand Down Expand Up @@ -205,6 +207,7 @@ describe('DdSdkReactNativeConfiguration', () => {
],
},
],
"headerCaptureRules": "defaults",
"initialResourceThreshold": 0.123,
"longTaskThresholdMs": 567,
"nativeCrashReportEnabled": true,
Expand All @@ -221,6 +224,7 @@ describe('DdSdkReactNativeConfiguration', () => {
"trackInteractions": true,
"trackMemoryWarnings": true,
"trackNonFatalAnrs": true,
"trackResourceHeaders": false,
"trackResources": true,
"trackWatchdogTerminations": false,
"useAccessibilityLabel": true,
Expand Down Expand Up @@ -308,6 +312,7 @@ describe('DdSdkReactNativeConfiguration', () => {
"customEndpoint": undefined,
"errorEventMapper": null,
"firstPartyHosts": [],
"headerCaptureRules": "defaults",
"initialResourceThreshold": 0,
"longTaskThresholdMs": false,
"nativeCrashReportEnabled": false,
Expand All @@ -324,6 +329,7 @@ describe('DdSdkReactNativeConfiguration', () => {
"trackInteractions": false,
"trackMemoryWarnings": false,
"trackNonFatalAnrs": false,
"trackResourceHeaders": false,
"trackResources": false,
"trackWatchdogTerminations": false,
"useAccessibilityLabel": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ describe('FileBasedConfiguration', () => {
],
},
],
"headerCaptureRules": "defaults",
"initialResourceThreshold": 456,
"longTaskThresholdMs": 44,
"nativeCrashReportEnabled": true,
Expand All @@ -71,6 +72,7 @@ describe('FileBasedConfiguration', () => {
"trackInteractions": true,
"trackMemoryWarnings": false,
"trackNonFatalAnrs": true,
"trackResourceHeaders": false,
"trackResources": true,
"trackWatchdogTerminations": true,
"useAccessibilityLabel": false,
Expand Down Expand Up @@ -167,6 +169,7 @@ describe('FileBasedConfiguration', () => {
],
},
],
"headerCaptureRules": "defaults",
"initialResourceThreshold": undefined,
"longTaskThresholdMs": 44,
"nativeCrashReportEnabled": false,
Expand All @@ -183,6 +186,7 @@ describe('FileBasedConfiguration', () => {
"trackInteractions": true,
"trackMemoryWarnings": true,
"trackNonFatalAnrs": undefined,
"trackResourceHeaders": false,
"trackResources": true,
"trackWatchdogTerminations": false,
"useAccessibilityLabel": false,
Expand Down Expand Up @@ -231,6 +235,7 @@ describe('FileBasedConfiguration', () => {
"customEndpoint": undefined,
"errorEventMapper": null,
"firstPartyHosts": [],
"headerCaptureRules": "defaults",
"initialResourceThreshold": undefined,
"longTaskThresholdMs": 0,
"nativeCrashReportEnabled": false,
Expand All @@ -247,6 +252,7 @@ describe('FileBasedConfiguration', () => {
"trackInteractions": false,
"trackMemoryWarnings": true,
"trackNonFatalAnrs": undefined,
"trackResourceHeaders": false,
"trackResources": false,
"trackWatchdogTerminations": false,
"useAccessibilityLabel": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type { ResourceEventMapper } from '../../rum/eventMappers/resourceEventMa
import type { FirstPartyHost } from '../../rum/types';
import type { LogEventMapper } from '../../types';
import { LOGS_DEFAULTS } from '../features/LogsConfiguration';
import type { HeaderCaptureRule } from '../features/RumConfiguration.type';
import { RUM_DEFAULTS } from '../features/RumConfiguration';
import type { TraceConfiguration } from '../features/TraceConfiguration';

Expand All @@ -24,6 +25,8 @@ export type AutoInstrumentationConfiguration = {
readonly useAccessibilityLabel?: boolean;
readonly actionNameAttribute?: string;
readonly resourceTraceSampleRate?: number;
readonly headerCaptureRules?: 'defaults' | HeaderCaptureRule[];
readonly trackResourceHeaders?: boolean;
readonly nativeCrashReportEnabled?: boolean;
readonly nativeLongTaskThresholdMs?: number;
readonly nativeViewTracking?: boolean;
Expand Down Expand Up @@ -55,6 +58,8 @@ export type AutoInstrumentationParameters = {
readonly errorEventMapper: ErrorEventMapper | null;
readonly resourceEventMapper: ResourceEventMapper | null;
readonly firstPartyHosts: FirstPartyHost[];
readonly headerCaptureRules?: 'defaults' | HeaderCaptureRule[];
readonly trackResourceHeaders: boolean;
};
readonly logsConfiguration?: {
readonly logEventMapper: LogEventMapper | null;
Expand Down Expand Up @@ -114,7 +119,11 @@ export const addDefaultValuesToAutoInstrumentationConfiguration = (
RUM_DEFAULTS.nativeViewTracking,
firstPartyHosts:
features.rumConfiguration.firstPartyHosts ||
RUM_DEFAULTS.getFirstPartyHosts()
RUM_DEFAULTS.getFirstPartyHosts(),
headerCaptureRules: features.rumConfiguration.headerCaptureRules,
trackResourceHeaders:
features.rumConfiguration.trackResourceHeaders ??
RUM_DEFAULTS.trackResourceHeaders
},
logsConfiguration: {
logEventMapper:
Expand Down
13 changes: 13 additions & 0 deletions packages/core/src/config/features/RumConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { FirstPartyHost } from '../../rum/types';
import { VitalsUpdateFrequency } from '../types';

import type {
HeaderCaptureRule,
RumConfigurationOptions,
RumConfigurationType
} from './RumConfiguration.type';
Expand Down Expand Up @@ -37,6 +38,11 @@ const DEFAULTS = {
trackInteractions: false,
trackMemoryWarnings: true,
trackNonFatalAnrs: undefined,
headerCaptureRules: 'defaults' as
| 'defaults'
| HeaderCaptureRule[]
| undefined,
trackResourceHeaders: false,
trackResources: false,
trackWatchdogTerminations: false,
useAccessibilityLabel: true,
Expand Down Expand Up @@ -112,6 +118,13 @@ export class RumConfiguration implements RumConfigurationType {
// Track non-fatal ANRs enabled
public trackNonFatalAnrs?: boolean = DEFAULTS.trackNonFatalAnrs;

// Header Capture Rules
public headerCaptureRules: 'defaults' | HeaderCaptureRule[] | undefined =
DEFAULTS.headerCaptureRules;

// Track Resource Headers enabled
public trackResourceHeaders: boolean = DEFAULTS.trackResourceHeaders;

// Track Watchdog Terminations enabled
public trackWatchdogTerminations: boolean =
DEFAULTS.trackWatchdogTerminations;
Expand Down
Loading