Skip to content

Commit 11e5f85

Browse files
committed
fixup! feat(cloudflare): Capture request body via httpServerIntegration
1 parent ace755b commit 11e5f85

4 files changed

Lines changed: 103 additions & 48 deletions

File tree

  • dev-packages/cloudflare-integration-tests/suites/tracing/propagation

dev-packages/cloudflare-integration-tests/suites/tracing/propagation/worker-do-rpc-disabled/index.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
import * as Sentry from '@sentry/cloudflare';
22
import { DurableObject } from 'cloudflare:workers';
3-
import type { RpcTarget } from 'cloudflare:workers';
43

54
interface Env {
65
SENTRY_DSN: string;
76
MY_DURABLE_OBJECT: DurableObjectNamespace<MyDurableObjectBase>;
87
}
98

10-
class MyDurableObjectBase extends DurableObject<Env> implements RpcTarget {
11-
async sayHello(name: string): Promise<string> {
12-
return `Hello, ${name}!`;
9+
class MyDurableObjectBase extends DurableObject<Env> {
10+
async fetch(request: Request): Promise<Response> {
11+
const url = new URL(request.url);
12+
if (url.pathname === '/hello') {
13+
return new Response('Hello, World!');
14+
}
15+
return new Response('Not found', { status: 404 });
1316
}
1417
}
1518

16-
// enableRpcTracePropagation is NOT enabled, so RPC methods won't be instrumented
1719
export const MyDurableObject = Sentry.instrumentDurableObjectWithSentry(
1820
(env: Env) => ({
1921
dsn: env.SENTRY_DSN,
2022
tracesSampleRate: 1.0,
21-
// enableRpcTracePropagation: false (default)
2223
}),
2324
MyDurableObjectBase,
2425
);
@@ -34,9 +35,11 @@ export default Sentry.withSentry(
3435
const id = env.MY_DURABLE_OBJECT.idFromName('test');
3536
const stub = env.MY_DURABLE_OBJECT.get(id);
3637

37-
if (url.pathname === '/rpc/hello') {
38-
const result = await stub.sayHello('World');
39-
return new Response(result);
38+
if (url.pathname === '/do/hello') {
39+
// Call DO via fetch instead of RPC
40+
const doResponse = await stub.fetch(new Request('http://do/hello'));
41+
const text = await doResponse.text();
42+
return new Response(text);
4043
}
4144

4245
return new Response('Not found', { status: 404 });

dev-packages/cloudflare-integration-tests/suites/tracing/propagation/worker-do-rpc-disabled/test.ts

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,65 @@ import { expect, it } from 'vitest';
22
import type { Event } from '@sentry/core';
33
import { createRunner } from '../../../../runner';
44

5-
it('does not create RPC transaction when enableRpcTracePropagation is disabled', async ({ signal }) => {
6-
let receivedTransactions: string[] = [];
5+
it('does not propagate trace when enableRpcTracePropagation is disabled', async ({ signal }) => {
6+
let workerTraceId: string | undefined;
7+
let doTraceId: string | undefined;
78

89
const runner = createRunner(__dirname)
910
.expect(envelope => {
1011
const transactionEvent = envelope[1]?.[0]?.[1] as Event;
1112

12-
// Should only receive the worker HTTP transaction, not the DO RPC transaction
1313
expect(transactionEvent).toEqual(
1414
expect.objectContaining({
1515
contexts: expect.objectContaining({
1616
trace: expect.objectContaining({
1717
op: 'http.server',
18-
data: expect.objectContaining({
19-
'sentry.origin': 'auto.http.cloudflare',
20-
}),
21-
origin: 'auto.http.cloudflare',
2218
}),
2319
}),
24-
transaction: 'GET /rpc/hello',
2520
}),
2621
);
27-
receivedTransactions.push(transactionEvent.transaction as string);
22+
23+
const txName = transactionEvent.transaction as string;
24+
const traceId = transactionEvent.contexts?.trace?.trace_id as string;
25+
26+
if (txName === 'GET /do/hello') {
27+
workerTraceId = traceId;
28+
} else if (txName === 'GET /hello') {
29+
doTraceId = traceId;
30+
}
31+
})
32+
.expect(envelope => {
33+
const transactionEvent = envelope[1]?.[0]?.[1] as Event;
34+
35+
expect(transactionEvent).toEqual(
36+
expect.objectContaining({
37+
contexts: expect.objectContaining({
38+
trace: expect.objectContaining({
39+
op: 'http.server',
40+
}),
41+
}),
42+
}),
43+
);
44+
45+
const txName = transactionEvent.transaction as string;
46+
const traceId = transactionEvent.contexts?.trace?.trace_id as string;
47+
48+
if (txName === 'GET /do/hello') {
49+
workerTraceId = traceId;
50+
} else if (txName === 'GET /hello') {
51+
doTraceId = traceId;
52+
}
2853
})
54+
.unordered()
2955
.start(signal);
3056

31-
// The RPC call should still work, just not be instrumented
32-
const response = await runner.makeRequest<string>('get', '/rpc/hello');
57+
const response = await runner.makeRequest<string>('get', '/do/hello');
3358
expect(response).toBe('Hello, World!');
3459

3560
await runner.completed();
3661

37-
// Verify we only got the worker transaction, no RPC transaction
38-
expect(receivedTransactions).toEqual(['GET /rpc/hello']);
39-
expect(receivedTransactions).not.toContain('sayHello');
62+
// Both transactions should exist but have different trace IDs (no propagation)
63+
expect(workerTraceId).toBeDefined();
64+
expect(doTraceId).toBeDefined();
65+
expect(workerTraceId).not.toBe(doTraceId);
4066
});

dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-do-rpc-disabled/index.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
import * as Sentry from '@sentry/cloudflare';
22
import { DurableObject, WorkerEntrypoint } from 'cloudflare:workers';
3-
import type { RpcTarget } from 'cloudflare:workers';
43

54
interface Env {
65
SENTRY_DSN: string;
76
MY_DURABLE_OBJECT: DurableObjectNamespace<MyDurableObjectBase>;
87
}
98

10-
class MyDurableObjectBase extends DurableObject<Env> implements RpcTarget {
11-
async sayHello(name: string): Promise<string> {
12-
return `Hello, ${name}!`;
9+
class MyDurableObjectBase extends DurableObject<Env> {
10+
async fetch(request: Request): Promise<Response> {
11+
const url = new URL(request.url);
12+
if (url.pathname === '/hello') {
13+
return new Response('Hello, World!');
14+
}
15+
return new Response('Not found', { status: 404 });
1316
}
1417
}
1518

16-
// enableRpcTracePropagation is NOT enabled, so RPC methods won't be instrumented
1719
export const MyDurableObject = Sentry.instrumentDurableObjectWithSentry(
1820
(env: Env) => ({
1921
dsn: env.SENTRY_DSN,
2022
tracesSampleRate: 1.0,
21-
// enableRpcTracePropagation: false (default)
2223
}),
2324
MyDurableObjectBase,
2425
);
@@ -29,9 +30,10 @@ class MyWorkerEntrypointBase extends WorkerEntrypoint<Env> {
2930
const id = this.env.MY_DURABLE_OBJECT.idFromName('test');
3031
const stub = this.env.MY_DURABLE_OBJECT.get(id);
3132

32-
if (url.pathname === '/rpc/hello') {
33-
const result = await stub.sayHello('World');
34-
return new Response(result);
33+
if (url.pathname === '/do/hello') {
34+
const doResponse = await stub.fetch(new Request('http://do/hello'));
35+
const text = await doResponse.text();
36+
return new Response(text);
3537
}
3638

3739
return new Response('Not found', { status: 404 });

dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-do-rpc-disabled/test.ts

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,65 @@ import { expect, it } from 'vitest';
22
import type { Event } from '@sentry/core';
33
import { createRunner } from '../../../../runner';
44

5-
it('does not create RPC transaction when enableRpcTracePropagation is disabled (WorkerEntrypoint)', async ({
6-
signal,
7-
}) => {
8-
let receivedTransactions: string[] = [];
5+
it('does not propagate trace when enableRpcTracePropagation is disabled (WorkerEntrypoint)', async ({ signal }) => {
6+
let workerTraceId: string | undefined;
7+
let doTraceId: string | undefined;
98

109
const runner = createRunner(__dirname)
1110
.expect(envelope => {
1211
const transactionEvent = envelope[1]?.[0]?.[1] as Event;
1312

14-
// Should only receive the worker HTTP transaction, not the DO RPC transaction
1513
expect(transactionEvent).toEqual(
1614
expect.objectContaining({
1715
contexts: expect.objectContaining({
1816
trace: expect.objectContaining({
1917
op: 'http.server',
20-
data: expect.objectContaining({
21-
'sentry.origin': 'auto.http.cloudflare',
22-
}),
23-
origin: 'auto.http.cloudflare',
2418
}),
2519
}),
26-
transaction: 'GET /rpc/hello',
2720
}),
2821
);
29-
receivedTransactions.push(transactionEvent.transaction as string);
22+
23+
const txName = transactionEvent.transaction as string;
24+
const traceId = transactionEvent.contexts?.trace?.trace_id as string;
25+
26+
if (txName === 'GET /do/hello') {
27+
workerTraceId = traceId;
28+
} else if (txName === 'GET /hello') {
29+
doTraceId = traceId;
30+
}
31+
})
32+
.expect(envelope => {
33+
const transactionEvent = envelope[1]?.[0]?.[1] as Event;
34+
35+
expect(transactionEvent).toEqual(
36+
expect.objectContaining({
37+
contexts: expect.objectContaining({
38+
trace: expect.objectContaining({
39+
op: 'http.server',
40+
}),
41+
}),
42+
}),
43+
);
44+
45+
const txName = transactionEvent.transaction as string;
46+
const traceId = transactionEvent.contexts?.trace?.trace_id as string;
47+
48+
if (txName === 'GET /do/hello') {
49+
workerTraceId = traceId;
50+
} else if (txName === 'GET /hello') {
51+
doTraceId = traceId;
52+
}
3053
})
54+
.unordered()
3155
.start(signal);
3256

33-
// The RPC call should still work, just not be instrumented
34-
const response = await runner.makeRequest<string>('get', '/rpc/hello');
57+
const response = await runner.makeRequest<string>('get', '/do/hello');
3558
expect(response).toBe('Hello, World!');
3659

3760
await runner.completed();
3861

39-
// Verify we only got the worker transaction, no RPC transaction
40-
expect(receivedTransactions).toEqual(['GET /rpc/hello']);
41-
expect(receivedTransactions).not.toContain('sayHello');
62+
// Both transactions should exist but have different trace IDs (no propagation)
63+
expect(workerTraceId).toBeDefined();
64+
expect(doTraceId).toBeDefined();
65+
expect(workerTraceId).not.toBe(doTraceId);
4266
});

0 commit comments

Comments
 (0)