Skip to content

Commit ac324bb

Browse files
authored
chore(middleware-recursion-detection): read TraceID from Lambda Invoke Store (#7293)
1 parent 9484757 commit ac324bb

File tree

4 files changed

+69
-14
lines changed

4 files changed

+69
-14
lines changed

packages/middleware-recursion-detection/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"license": "Apache-2.0",
2525
"dependencies": {
2626
"@aws-sdk/types": "*",
27+
"@aws/lambda-invoke-store": "^0.0.1",
2728
"@smithy/protocol-http": "^5.1.3",
2829
"@smithy/types": "^4.3.2",
2930
"tslib": "^2.6.2"

packages/middleware-recursion-detection/src/recursionDetectionMiddleware.spec.ts

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { InvokeStore } from "@aws/lambda-invoke-store";
12
import { HttpRequest } from "@smithy/protocol-http";
23
import { afterAll, beforeEach, describe, expect, test as it, vi } from "vitest";
34

@@ -6,31 +7,71 @@ import { recursionDetectionMiddleware } from "./recursionDetectionMiddleware";
67
describe(recursionDetectionMiddleware.name, () => {
78
const mockNextHandler = vi.fn();
89
const originEnv = process.env;
10+
911
const TRACE_ID_HEADER_NAME = "X-Amzn-Trace-Id";
1012

1113
beforeEach(() => {
1214
vi.clearAllMocks();
15+
vi.spyOn(InvokeStore, "getXRayTraceId").mockImplementation(() => undefined);
1316
process.env = {};
1417
});
1518

1619
afterAll(() => {
1720
process.env = originEnv;
1821
});
1922

20-
it(`sets ${TRACE_ID_HEADER_NAME} header when function name and trace id environmental variables are set`, async () => {
21-
process.env = {
22-
AWS_LAMBDA_FUNCTION_NAME: "some-function",
23-
_X_AMZN_TRACE_ID: "some-trace-id",
24-
};
25-
const handler = recursionDetectionMiddleware()(mockNextHandler, {} as any);
26-
await handler({
27-
input: {},
28-
request: new HttpRequest({}),
23+
describe(`sets ${TRACE_ID_HEADER_NAME} header when function name and`, () => {
24+
const mockTraceIdEnv = "trace-id-from-env";
25+
const mockTraceIdInvokeStore = "trace-id-from-invoke-store";
26+
27+
it("trace id environmental variables is set", async () => {
28+
process.env = {
29+
AWS_LAMBDA_FUNCTION_NAME: "some-function",
30+
_X_AMZN_TRACE_ID: mockTraceIdEnv,
31+
};
32+
const handler = recursionDetectionMiddleware()(mockNextHandler, {} as any);
33+
await handler({
34+
input: {},
35+
request: new HttpRequest({}),
36+
});
37+
const { calls } = (mockNextHandler as any).mock;
38+
expect(calls.length).toBe(1);
39+
const { request } = mockNextHandler.mock.calls[0][0];
40+
expect(request.headers[TRACE_ID_HEADER_NAME]).toBe(mockTraceIdEnv);
41+
});
42+
43+
it("trace id value is set in InvokeStore", async () => {
44+
vi.spyOn(InvokeStore, "getXRayTraceId").mockImplementation(() => mockTraceIdInvokeStore);
45+
process.env = {
46+
AWS_LAMBDA_FUNCTION_NAME: "some-function",
47+
};
48+
const handler = recursionDetectionMiddleware()(mockNextHandler, {} as any);
49+
await handler({
50+
input: {},
51+
request: new HttpRequest({}),
52+
});
53+
const { calls } = (mockNextHandler as any).mock;
54+
expect(calls.length).toBe(1);
55+
const { request } = mockNextHandler.mock.calls[0][0];
56+
expect(request.headers[TRACE_ID_HEADER_NAME]).toBe(mockTraceIdInvokeStore);
57+
});
58+
59+
it("favors trace id value from InvokeStore over that from env variable", async () => {
60+
vi.spyOn(InvokeStore, "getXRayTraceId").mockImplementation(() => mockTraceIdInvokeStore);
61+
process.env = {
62+
AWS_LAMBDA_FUNCTION_NAME: "some-function",
63+
_X_AMZN_TRACE_ID: mockTraceIdEnv,
64+
};
65+
const handler = recursionDetectionMiddleware()(mockNextHandler, {} as any);
66+
await handler({
67+
input: {},
68+
request: new HttpRequest({}),
69+
});
70+
const { calls } = (mockNextHandler as any).mock;
71+
expect(calls.length).toBe(1);
72+
const { request } = mockNextHandler.mock.calls[0][0];
73+
expect(request.headers[TRACE_ID_HEADER_NAME]).toBe(mockTraceIdInvokeStore);
2974
});
30-
const { calls } = (mockNextHandler as any).mock;
31-
expect(calls.length).toBe(1);
32-
const { request } = mockNextHandler.mock.calls[0][0];
33-
expect(request.headers[TRACE_ID_HEADER_NAME]).toBe("some-trace-id");
3475
});
3576

3677
it(`should NOT set ${TRACE_ID_HEADER_NAME} header when function name environmental variable is NOT set`, async () => {

packages/middleware-recursion-detection/src/recursionDetectionMiddleware.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { InvokeStore } from "@aws/lambda-invoke-store";
12
import { HttpRequest } from "@smithy/protocol-http";
23
import {
34
BuildHandler,
@@ -31,7 +32,11 @@ export const recursionDetectionMiddleware =
3132
return next(args);
3233
}
3334
const functionName = process.env[ENV_LAMBDA_FUNCTION_NAME];
34-
const traceId = process.env[ENV_TRACE_ID];
35+
36+
const traceIdFromEnv = process.env[ENV_TRACE_ID];
37+
const traceIdFromInvokeStore = InvokeStore.getXRayTraceId();
38+
const traceId = traceIdFromInvokeStore ?? traceIdFromEnv;
39+
3540
const nonEmptyString = (str: unknown): str is string => typeof str === "string" && str.length > 0;
3641
if (nonEmptyString(functionName) && nonEmptyString(traceId)) {
3742
request.headers[TRACE_ID_HEADER_NAME] = traceId;

yarn.lock

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24096,6 +24096,7 @@ __metadata:
2409624096
resolution: "@aws-sdk/middleware-recursion-detection@workspace:packages/middleware-recursion-detection"
2409724097
dependencies:
2409824098
"@aws-sdk/types": "npm:*"
24099+
"@aws/lambda-invoke-store": "npm:^0.0.1"
2409924100
"@smithy/protocol-http": "npm:^5.1.3"
2410024101
"@smithy/types": "npm:^4.3.2"
2410124102
"@tsconfig/recommended": "npm:1.0.1"
@@ -25022,6 +25023,13 @@ __metadata:
2502225023
languageName: node
2502325024
linkType: hard
2502425025

25026+
"@aws/lambda-invoke-store@npm:^0.0.1":
25027+
version: 0.0.1
25028+
resolution: "@aws/lambda-invoke-store@npm:0.0.1"
25029+
checksum: 10c0/0bbf3060014a462177fb743e132e9b106a6743ad9cd905df4bd26e9ca8bfe2cc90473b03a79938fa908934e45e43f366f57af56a697991abda71d9ac92f5018f
25030+
languageName: node
25031+
linkType: hard
25032+
2502525033
"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0, @babel/code-frame@npm:^7.26.2":
2502625034
version: 7.26.2
2502725035
resolution: "@babel/code-frame@npm:7.26.2"

0 commit comments

Comments
 (0)