Skip to content
Merged
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
9 changes: 8 additions & 1 deletion .claude/skills/manual-testing/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Run a manual test of the current change end-to-end and output repro

## Step 1: Understand the change

Review the current diff to identify what SDK behavior changed and what events/fields need to be verified.
If you don't have the PR changes in memory, review all commits in the PR to identify what SDK behavior changed and what events/fields need to be verified.

## Step 2: Start the dev server

Expand Down Expand Up @@ -52,6 +52,13 @@ yarn dev-server intake <selector> | jq '<field>'

Use `yarn dev-server intake --help` to find the right selector.

To evaluate JavaScript on the page (e.g. to inspect `window` state set by `beforeSend`), switch focus back to tab 0 first, then use `agent-browser eval`:

```bash
agent-browser tab 0
agent-browser eval 'window.someValue'
```

## Step 5: Verify the output matches expectations, then present the test instructions

Output a self-contained bash snippet with the exact commands run and the expected output. This goes directly into the PR "Test instructions" section.
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/browser/fetchObservable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,8 @@ describe('fetch proxy with ResponseBodyAction', () => {
})
})

it('should not collect response body with WAIT or IGNORE action', (done) => {
setupFetchTracking(() => ResponseBodyAction.WAIT)
it('should not collect response body with IGNORE action', (done) => {
setupFetchTracking(() => ResponseBodyAction.IGNORE)

fetch(FAKE_URL).resolveWith({ status: 200, responseText: 'response body content' })

Expand All @@ -313,7 +313,7 @@ describe('fetch proxy with ResponseBodyAction', () => {
})

it('should use the highest priority action when multiple getters are registered', (done) => {
setupFetchTracking(() => ResponseBodyAction.WAIT)
setupFetchTracking(() => ResponseBodyAction.IGNORE)

initFetchObservable({
responseBodyAction: () => ResponseBodyAction.COLLECT,
Expand Down
13 changes: 4 additions & 9 deletions packages/core/src/browser/fetchObservable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,7 @@ type ResponseBodyActionGetter = (context: FetchResolveContext) => ResponseBodyAc
*/
export const enum ResponseBodyAction {
IGNORE = 0,
// TODO(next-major): Remove the "WAIT" action when `trackEarlyRequests` is removed, as the
// duration of fetch requests will always come from PerformanceResourceTiming
WAIT = 1,
COLLECT = 2,
COLLECT = 1,
}

const FETCH_BUFFER_LIMIT = 500
Expand Down Expand Up @@ -154,14 +151,12 @@ async function afterSend(
ResponseBodyAction.IGNORE
) as ResponseBodyAction

if (responseBodyCondition !== ResponseBodyAction.IGNORE) {
if (responseBodyCondition === ResponseBodyAction.COLLECT) {
const clonedResponse = tryToClone(response)
if (clonedResponse && clonedResponse.body) {
try {
const bytes = await readBytesFromStream(clonedResponse.body, {
collectStreamBody: responseBodyCondition === ResponseBodyAction.COLLECT,
})
context.responseBody = bytes && new TextDecoder().decode(bytes)
const bytes = await readBytesFromStream(clonedResponse.body)
context.responseBody = new TextDecoder().decode(bytes)
} catch {
// Ignore errors when reading the response body (e.g., stream aborted, network errors)
// This is not critical and should not be reported as an SDK error
Expand Down
21 changes: 4 additions & 17 deletions packages/core/src/tools/readBytesFromStream.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,9 @@ describe('readBytesFromStream', () => {
})

it('should read full stream', async () => {
const bytes = await readBytesFromStream(stream, {
collectStreamBody: true,
})
const bytes = await readBytesFromStream(stream)

expect(bytes?.length).toBe(27)
})

it('should read full stream without body', async () => {
const bytes = await readBytesFromStream(stream, {
collectStreamBody: false,
})
expect(bytes).toBeUndefined()
expect(bytes.length).toBe(27)
})

it('should handle rejection error on read', async () => {
Expand All @@ -36,9 +27,7 @@ describe('readBytesFromStream', () => {
})

try {
await readBytesFromStream(stream, {
collectStreamBody: true,
})
await readBytesFromStream(stream)
fail('Should have thrown an error')
} catch (error) {
expect(error).toEqual(jasmine.any(Error))
Expand All @@ -54,9 +43,7 @@ describe('readBytesFromStream', () => {
cancel: () => Promise.reject(new Error('foo')),
})

const bytes = await readBytesFromStream(stream, {
collectStreamBody: true,
})
const bytes = await readBytesFromStream(stream)
expect(bytes).toBeDefined()
})
})
15 changes: 3 additions & 12 deletions packages/core/src/tools/readBytesFromStream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,10 @@ import type { Uint8ArrayBuffer } from './utils/byteUtils'
import { concatBuffers } from './utils/byteUtils'
import { noop } from './utils/functionUtils'

interface Options {
// TODO(next-major): always collect stream body when `trackEarlyRequests` is removed, as we don't
// need to use this function to just wait for the end of the stream without collecting it
collectStreamBody?: boolean
}

/**
* Read bytes from a ReadableStream until the end of the stream.
* Returns the bytes if collectStreamBody is true, otherwise returns undefined.
*/
export async function readBytesFromStream(stream: ReadableStream<Uint8ArrayBuffer>, options: Options) {
export async function readBytesFromStream(stream: ReadableStream<Uint8ArrayBuffer>) {
const reader = stream.getReader()
const chunks: Uint8ArrayBuffer[] = []

Expand All @@ -22,9 +15,7 @@ export async function readBytesFromStream(stream: ReadableStream<Uint8ArrayBuffe
break
}

if (options.collectStreamBody) {
chunks.push(result.value)
}
chunks.push(result.value)
}

reader.cancel().catch(
Expand All @@ -33,5 +24,5 @@ export async function readBytesFromStream(stream: ReadableStream<Uint8ArrayBuffe
noop
)

return options.collectStreamBody ? concatBuffers(chunks) : undefined
return concatBuffers(chunks)
}
2 changes: 1 addition & 1 deletion packages/rum-core/src/boot/startRum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ export function startRumEventCollection(

cleanupTasks.push(stopViewCollection)

const resourceCollection = startResourceCollection(lifeCycle, configuration, pageStateHistory)
const resourceCollection = startResourceCollection(lifeCycle, configuration)
cleanupTasks.push(resourceCollection.stop)

const { stop: stopLongTaskCollection } = startLongTaskCollection(lifeCycle, configuration)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,6 @@ describe('serializeRumConfiguration', () => {
trackViewsManually: true,
trackResources: true,
trackLongTasks: true,
trackEarlyRequests: true,
remoteConfigurationId: '123',
remoteConfigurationProxy: 'config',
plugins: [{ name: 'foo', getConfigurationTelemetry: () => ({ bar: true }) }],
Expand Down Expand Up @@ -750,7 +749,6 @@ describe('serializeRumConfiguration', () => {
enable_privacy_for_action_name: false,
track_resources: true,
track_long_task: true,
track_early_requests: true,
use_worker_url: true,
compress_intake_requests: true,
plugins: [{ name: 'foo', bar: true }],
Expand Down
11 changes: 0 additions & 11 deletions packages/rum-core/src/domain/configuration/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,14 +260,6 @@ export interface RumInitConfiguration extends InitConfiguration {
*/
trackLongTasks?: boolean | undefined

/**
* Enables early request collection before resource timing entries are available.
*
* @category Data Collection
* @defaultValue false
*/
trackEarlyRequests?: boolean | undefined

/**
* List of plugins to enable. The plugins API is unstable and experimental, and may change without
* notice. Please use only plugins provided by Datadog matching the version of the SDK you are
Expand Down Expand Up @@ -336,7 +328,6 @@ export interface RumConfiguration extends Configuration {
trackResources: boolean
trackResourceHeaders: MatchOption[]
trackLongTasks: boolean
trackEarlyRequests: boolean
subdomain?: string
traceContextInjection: TraceContextInjection
plugins: RumPlugin[]
Expand Down Expand Up @@ -408,7 +399,6 @@ export function validateAndBuildRumConfiguration(
trackResources: !!(initConfiguration.trackResources ?? true),
trackResourceHeaders: validateAndBuildTrackResourceHeaders(initConfiguration),
trackLongTasks: !!(initConfiguration.trackLongTasks ?? true),
trackEarlyRequests: !!initConfiguration.trackEarlyRequests,
subdomain: initConfiguration.subdomain,
defaultPrivacyLevel: objectHasValue(DefaultPrivacyLevel, initConfiguration.defaultPrivacyLevel)
? initConfiguration.defaultPrivacyLevel
Expand Down Expand Up @@ -586,7 +576,6 @@ export function serializeRumConfiguration(configuration: RumInitConfiguration) {
track_user_interactions: configuration.trackUserInteractions,
track_resources: configuration.trackResources,
track_long_task: configuration.trackLongTasks,
track_early_requests: configuration.trackEarlyRequests,
plugins: configuration.plugins?.map((plugin) => ({
name: plugin.name,
...plugin.getConfigurationTelemetry?.(),
Expand Down
2 changes: 1 addition & 1 deletion packages/rum-core/src/domain/requestCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export function trackFetch(lifeCycle: LifeCycle, configuration: RumConfiguration
if (findGraphQlConfiguration(context.url, configuration)?.trackResponseErrors) {
return ResponseBodyAction.COLLECT
}
return ResponseBodyAction.WAIT
return ResponseBodyAction.IGNORE
},
}).subscribe((rawContext) => {
const context = rawContext as RumFetchResolveContext | RumFetchStartContext
Expand Down

This file was deleted.

Loading
Loading