diff --git a/packages/core/src/tools/experimentalFeatures.ts b/packages/core/src/tools/experimentalFeatures.ts index 80831c87ce..94748fe737 100644 --- a/packages/core/src/tools/experimentalFeatures.ts +++ b/packages/core/src/tools/experimentalFeatures.ts @@ -17,6 +17,7 @@ export enum ExperimentalFeature { COLLECT_FLUSH_REASON = 'collect_flush_reason', ZERO_LCP_TELEMETRY = 'zero_lcp_telemetry', DISABLE_REPLAY_INLINE_CSS = 'disable_replay_inline_css', + WRITABLE_RESOURCE_GRAPHQL = 'writable_resource_graphql', } const enabledExperimentalFeatures: Set = new Set() diff --git a/packages/core/test/emulate/mockExperimentalFeatures.ts b/packages/core/test/emulate/mockExperimentalFeatures.ts new file mode 100644 index 0000000000..0a1f003028 --- /dev/null +++ b/packages/core/test/emulate/mockExperimentalFeatures.ts @@ -0,0 +1,11 @@ +import { + resetExperimentalFeatures, + type ExperimentalFeature, + addExperimentalFeatures, +} from '../../src/tools/experimentalFeatures' +import { registerCleanupTask } from '../registerCleanupTask' + +export function mockExperimentalFeatures(enabledFeatures: ExperimentalFeature[]) { + addExperimentalFeatures(enabledFeatures) + registerCleanupTask(resetExperimentalFeatures) +} diff --git a/packages/core/test/index.ts b/packages/core/test/index.ts index f359253f6c..6ef51ab445 100644 --- a/packages/core/test/index.ts +++ b/packages/core/test/index.ts @@ -16,3 +16,4 @@ export * from './emulate/eventBridge' export * from './emulate/eventBridge' export * from './emulate/stubStorages' export * from './emulate/mockFlushController' +export * from './emulate/mockExperimentalFeatures' diff --git a/packages/rum-core/src/domain/assembly.spec.ts b/packages/rum-core/src/domain/assembly.spec.ts index ffbc02b6cc..5389d99348 100644 --- a/packages/rum-core/src/domain/assembly.spec.ts +++ b/packages/rum-core/src/domain/assembly.spec.ts @@ -1,10 +1,11 @@ import type { ClocksState, RelativeTime } from '@datadog/browser-core' -import { ErrorSource, ONE_MINUTE, display } from '@datadog/browser-core' +import { ErrorSource, ExperimentalFeature, ONE_MINUTE, display } from '@datadog/browser-core' import { initEventBridgeStub, deleteEventBridgeStub, cleanupSyntheticsWorkerValues, mockSyntheticsWorkerValues, + mockExperimentalFeatures, } from '@datadog/browser-core/test' import type { TestSetupBuilder } from '../../test' import { @@ -17,7 +18,7 @@ import { import type { RumEventDomainContext } from '../domainContext.types' import type { RawRumActionEvent, RawRumErrorEvent, RawRumEvent } from '../rawRumEvent.types' import { RumEventType } from '../rawRumEvent.types' -import type { RumActionEvent, RumErrorEvent, RumEvent } from '../rumEvent.types' +import type { RumActionEvent, RumErrorEvent, RumEvent, RumResourceEvent } from '../rumEvent.types' import { startRumAssembly } from './assembly' import type { LifeCycle, RawRumEventCollectedData } from './lifeCycle' import { LifeCycleEventType } from './lifeCycle' @@ -109,6 +110,38 @@ describe('rum assembly', () => { expect(serverRumEvents[0].view.name).toBe('added') }) + + describe('field resource.graphql on Resource events', () => { + it('by default, it should not be modifiable', () => { + const { lifeCycle } = setupBuilder + .withConfiguration({ + beforeSend: (event) => (event.resource!.graphql = { operationType: 'query' }), + }) + .build() + + notifyRawRumEvent(lifeCycle, { + rawRumEvent: createRawRumEvent(RumEventType.RESOURCE, { resource: { url: '/path?foo=bar' } }), + }) + + expect((serverRumEvents[0] as RumResourceEvent).resource.graphql).toBeUndefined() + }) + + it('with the writable_resource_graphql experimental flag is set, it should be modifiable', () => { + mockExperimentalFeatures([ExperimentalFeature.WRITABLE_RESOURCE_GRAPHQL]) + + const { lifeCycle } = setupBuilder + .withConfiguration({ + beforeSend: (event) => (event.resource!.graphql = { operationType: 'query' }), + }) + .build() + + notifyRawRumEvent(lifeCycle, { + rawRumEvent: createRawRumEvent(RumEventType.RESOURCE, { resource: { url: '/path?foo=bar' } }), + }) + + expect((serverRumEvents[0] as RumResourceEvent).resource.graphql).toEqual({ operationType: 'query' }) + }) + }) }) describe('context field', () => { diff --git a/packages/rum-core/src/domain/assembly.ts b/packages/rum-core/src/domain/assembly.ts index afd0c32983..20e7577d61 100644 --- a/packages/rum-core/src/domain/assembly.ts +++ b/packages/rum-core/src/domain/assembly.ts @@ -9,6 +9,8 @@ import { canUseEventBridge, assign, round, + isExperimentalFeatureEnabled, + ExperimentalFeature, } from '@datadog/browser-core' import type { RumEventDomainContext } from '../domainContext.types' import type { @@ -84,6 +86,9 @@ export function startRumAssembly( { 'resource.url': 'string', }, + isExperimentalFeatureEnabled(ExperimentalFeature.WRITABLE_RESOURCE_GRAPHQL) && { + 'resource.graphql': 'object', + }, USER_CUSTOMIZABLE_FIELD_PATHS, VIEW_MODIFIABLE_FIELD_PATHS ),