Skip to content

Commit 3e0e3a8

Browse files
authored
Merge branch 'develop' into baggage-sent-twice
2 parents 385a954 + c3fa288 commit 3e0e3a8

10 files changed

Lines changed: 124 additions & 34 deletions

File tree

dev-packages/cloudflare-integration-tests/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"@langchain/langgraph": "^1.0.1",
1717
"@sentry/cloudflare": "10.42.0",
1818
"@sentry/hono": "10.42.0",
19-
"hono": "^4.11.10"
19+
"hono": "^4.12.5"
2020
},
2121
"devDependencies": {
2222
"@cloudflare/workers-types": "^4.20250922.0",

dev-packages/e2e-tests/test-applications/cloudflare-hono/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
},
1313
"dependencies": {
1414
"@sentry/cloudflare": "latest || *",
15-
"hono": "4.11.10"
15+
"hono": "4.12.5"
1616
},
1717
"devDependencies": {
1818
"@cloudflare/vitest-pool-workers": "^0.8.31",

dev-packages/e2e-tests/test-applications/nestjs-microservices/src/app.controller.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,21 @@ export class AppController {
2828
return firstValueFrom(this.client.send({ cmd: 'manual-capture' }, {}));
2929
}
3030

31+
@Get('test-microservice-guard')
32+
async testMicroserviceGuard() {
33+
return firstValueFrom(this.client.send({ cmd: 'test-guard' }, {}));
34+
}
35+
36+
@Get('test-microservice-interceptor')
37+
async testMicroserviceInterceptor() {
38+
return firstValueFrom(this.client.send({ cmd: 'test-interceptor' }, {}));
39+
}
40+
41+
@Get('test-microservice-pipe')
42+
async testMicroservicePipe() {
43+
return firstValueFrom(this.client.send({ cmd: 'test-pipe' }, { value: 123 }));
44+
}
45+
3146
@Get('flush')
3247
async flush() {
3348
await flush();
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
2+
3+
@Injectable()
4+
export class ExampleGuard implements CanActivate {
5+
canActivate(context: ExecutionContext): boolean {
6+
return true;
7+
}
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
2+
3+
@Injectable()
4+
export class ExampleInterceptor implements NestInterceptor {
5+
intercept(context: ExecutionContext, next: CallHandler) {
6+
return next.handle();
7+
}
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Injectable, PipeTransform } from '@nestjs/common';
2+
3+
@Injectable()
4+
export class ExamplePipe implements PipeTransform {
5+
transform(value: any) {
6+
return value;
7+
}
8+
}

dev-packages/e2e-tests/test-applications/nestjs-microservices/src/microservice.controller.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
import { Controller } from '@nestjs/common';
1+
import { Controller, UseGuards, UseInterceptors, UsePipes } from '@nestjs/common';
22
import { MessagePattern } from '@nestjs/microservices';
33
import * as Sentry from '@sentry/nestjs';
4+
import { ExampleGuard } from './example.guard';
5+
import { ExampleInterceptor } from './example.interceptor';
6+
import { ExamplePipe } from './example.pipe';
47

58
@Controller()
69
export class MicroserviceController {
@@ -25,4 +28,22 @@ export class MicroserviceController {
2528
}
2629
return { success: true };
2730
}
31+
32+
@UseGuards(ExampleGuard)
33+
@MessagePattern({ cmd: 'test-guard' })
34+
testGuard(): { result: string } {
35+
return { result: 'guard-handled' };
36+
}
37+
38+
@UseInterceptors(ExampleInterceptor)
39+
@MessagePattern({ cmd: 'test-interceptor' })
40+
testInterceptor(): { result: string } {
41+
return { result: 'interceptor-handled' };
42+
}
43+
44+
@UsePipes(ExamplePipe)
45+
@MessagePattern({ cmd: 'test-pipe' })
46+
testPipe(data: { value: number }): { result: number } {
47+
return { result: data.value };
48+
}
2849
}

dev-packages/e2e-tests/test-applications/nestjs-microservices/tests/transactions.test.ts

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ test('Sends an HTTP transaction', async ({ baseURL }) => {
2222
);
2323
});
2424

25-
// Trace context does not propagate over NestJS TCP transport.
26-
// The manual span created inside the microservice handler is orphaned, not a child of the HTTP transaction.
27-
// This test documents this gap — if trace propagation is ever fixed, test.fail() will alert us.
28-
test.fail('Microservice spans are captured as children of the HTTP transaction', async ({ baseURL }) => {
29-
const transactionEventPromise = waitForTransaction('nestjs-microservices', transactionEvent => {
25+
// Trace context does not propagate over NestJS TCP transport, so RPC spans are disconnected from
26+
// the HTTP transaction. Instead of appearing as child spans of the HTTP transaction, auto-instrumented
27+
// NestJS guard/interceptor/pipe spans become separate standalone transactions.
28+
// This documents the current (broken) behavior — ideally these should be connected to the HTTP trace.
29+
30+
test('Microservice spans are not connected to the HTTP transaction', async ({ baseURL }) => {
31+
const httpTransactionPromise = waitForTransaction('nestjs-microservices', transactionEvent => {
3032
return (
3133
transactionEvent?.contexts?.trace?.op === 'http.server' &&
3234
transactionEvent?.transaction === 'GET /test-microservice-sum'
@@ -36,19 +38,48 @@ test.fail('Microservice spans are captured as children of the HTTP transaction',
3638
const response = await fetch(`${baseURL}/test-microservice-sum`);
3739
expect(response.status).toBe(200);
3840

39-
const body = await response.json();
40-
expect(body.result).toBe(6);
41+
const httpTransaction = await httpTransactionPromise;
4142

42-
const transactionEvent = await transactionEventPromise;
43+
// The microservice span should be part of this transaction but isn't due to missing trace propagation
44+
const microserviceSpan = httpTransaction.spans?.find(span => span.description === 'microservice-sum-operation');
45+
expect(microserviceSpan).toBeUndefined();
46+
});
4347

44-
expect(transactionEvent.contexts?.trace).toEqual(
45-
expect.objectContaining({
46-
op: 'http.server',
47-
status: 'ok',
48-
}),
49-
);
48+
test('Microservice guard is emitted as a standalone transaction instead of being part of the HTTP trace', async ({
49+
baseURL,
50+
}) => {
51+
const guardTransactionPromise = waitForTransaction('nestjs-microservices', transactionEvent => {
52+
return transactionEvent?.transaction === 'ExampleGuard';
53+
});
54+
55+
await fetch(`${baseURL}/test-microservice-guard`);
56+
57+
const guardTransaction = await guardTransactionPromise;
58+
expect(guardTransaction).toBeDefined();
59+
});
60+
61+
test('Microservice interceptor is emitted as a standalone transaction instead of being part of the HTTP trace', async ({
62+
baseURL,
63+
}) => {
64+
const interceptorTransactionPromise = waitForTransaction('nestjs-microservices', transactionEvent => {
65+
return transactionEvent?.transaction === 'ExampleInterceptor';
66+
});
67+
68+
await fetch(`${baseURL}/test-microservice-interceptor`);
69+
70+
const interceptorTransaction = await interceptorTransactionPromise;
71+
expect(interceptorTransaction).toBeDefined();
72+
});
73+
74+
test('Microservice pipe is emitted as a standalone transaction instead of being part of the HTTP trace', async ({
75+
baseURL,
76+
}) => {
77+
const pipeTransactionPromise = waitForTransaction('nestjs-microservices', transactionEvent => {
78+
return transactionEvent?.transaction === 'ExamplePipe';
79+
});
80+
81+
await fetch(`${baseURL}/test-microservice-pipe`);
5082

51-
const microserviceSpan = transactionEvent.spans?.find(span => span.description === 'microservice-sum-operation');
52-
expect(microserviceSpan).toBeDefined();
53-
expect(microserviceSpan.trace_id).toBe(transactionEvent.contexts?.trace?.trace_id);
83+
const pipeTransaction = await pipeTransactionPromise;
84+
expect(pipeTransaction).toBeDefined();
5485
});

dev-packages/node-integration-tests/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"generic-pool": "^3.9.0",
5757
"graphql": "^16.11.0",
5858
"graphql-tag": "^2.12.6",
59-
"hono": "^4.11.10",
59+
"hono": "^4.12.5",
6060
"http-terminator": "^3.2.0",
6161
"ioredis": "^5.4.1",
6262
"kafkajs": "2.2.4",

yarn.lock

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18604,10 +18604,10 @@ homedir-polyfill@^1.0.1:
1860418604
dependencies:
1860518605
parse-passwd "^1.0.0"
1860618606

18607-
hono@^4.11.10:
18608-
version "4.11.10"
18609-
resolved "https://registry.yarnpkg.com/hono/-/hono-4.11.10.tgz#0cb40d3d8e2ff764c761b4267b99e3c7a6edf6a0"
18610-
integrity sha512-kyWP5PAiMooEvGrA9jcD3IXF7ATu8+o7B3KCbPXid5se52NPqnOpM/r9qeW2heMnOekF4kqR1fXJqCYeCLKrZg==
18607+
hono@^4.12.5:
18608+
version "4.12.5"
18609+
resolved "https://registry.yarnpkg.com/hono/-/hono-4.12.5.tgz#8c16209b35040025d3f110d18f3b821de6cab00f"
18610+
integrity sha512-3qq+FUBtlTHhtYxbxheZgY8NIFnkkC/MR8u5TTsr7YZ3wixryQ3cCwn3iZbg8p8B88iDBBAYSfZDS75t8MN7Vg==
1861118611

1861218612
hookable@^5.5.3:
1861318613
version "5.5.3"
@@ -26629,10 +26629,10 @@ sass@^1.49.9:
2662926629
immutable "^4.0.0"
2663026630
source-map-js ">=0.6.2 <2.0.0"
2663126631

26632-
sax@^1.2.4, sax@^1.4.1:
26633-
version "1.4.4"
26634-
resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.4.tgz#f29c2bba80ce5b86f4343b4c2be9f2b96627cf8b"
26635-
integrity sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==
26632+
sax@^1.2.4, sax@^1.5.0:
26633+
version "1.5.0"
26634+
resolved "https://registry.yarnpkg.com/sax/-/sax-1.5.0.tgz#b5549b671069b7aa392df55ec7574cf411179eb8"
26635+
integrity sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==
2663626636

2663726637
sax@~1.2.4:
2663826638
version "1.2.4"
@@ -28096,7 +28096,6 @@ stylus@0.59.0, stylus@^0.59.0:
2809628096

2809728097
sucrase@^3.27.0, sucrase@^3.35.0, sucrase@getsentry/sucrase#es2020-polyfills:
2809828098
version "3.36.0"
28099-
uid fd682f6129e507c00bb4e6319cc5d6b767e36061
2810028099
resolved "https://codeload.github.com/getsentry/sucrase/tar.gz/fd682f6129e507c00bb4e6319cc5d6b767e36061"
2810128100
dependencies:
2810228101
"@jridgewell/gen-mapping" "^0.3.2"
@@ -28192,17 +28191,17 @@ svelte@^4.2.8:
2819228191
periscopic "^3.1.0"
2819328192

2819428193
svgo@^4.0.0:
28195-
version "4.0.0"
28196-
resolved "https://registry.yarnpkg.com/svgo/-/svgo-4.0.0.tgz#17e0fa2eaccf429e0ec0d2179169abde9ba8ad3d"
28197-
integrity sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==
28194+
version "4.0.1"
28195+
resolved "https://registry.yarnpkg.com/svgo/-/svgo-4.0.1.tgz"
28196+
integrity sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==
2819828197
dependencies:
2819928198
commander "^11.1.0"
2820028199
css-select "^5.1.0"
2820128200
css-tree "^3.0.1"
2820228201
css-what "^6.1.0"
2820328202
csso "^5.0.5"
2820428203
picocolors "^1.1.1"
28205-
sax "^1.4.1"
28204+
sax "^1.5.0"
2820628205

2820728206
swr@^2.2.5:
2820828207
version "2.2.5"

0 commit comments

Comments
 (0)