diff --git a/packages/synthetics-sdk-api/package.json b/packages/synthetics-sdk-api/package.json index 885d8016..273a414b 100644 --- a/packages/synthetics-sdk-api/package.json +++ b/packages/synthetics-sdk-api/package.json @@ -15,6 +15,7 @@ "@types/supertest": "^2.0.12", "chai": "^4.3.7", "express": "^4.18.2", + "node-mocks-http": "^1.13.0", "sinon": "^16.0.0", "supertest": "^6.3.3" }, diff --git a/packages/synthetics-sdk-api/src/handlers.ts b/packages/synthetics-sdk-api/src/handlers.ts index f2a30096..c3221f0e 100644 --- a/packages/synthetics-sdk-api/src/handlers.ts +++ b/packages/synthetics-sdk-api/src/handlers.ts @@ -29,9 +29,14 @@ import { getInstrumentedLogger } from './auto_instrumentation'; instantiateMetadata(); const asyncFilenamePrefix = 'async '; +const syntheticExecutionIdHeader = 'Synthetic-Execution-Id'; const runSynthetic = async ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - syntheticCode: (args: { logger: Logger }) => any + syntheticCode: (args: { + logger: Logger; + executionId: string | undefined; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + }) => any, + executionId: string | undefined ) => { const logger = await getInstrumentedLogger(); const startTime = new Date().toISOString(); @@ -40,7 +45,7 @@ const runSynthetic = async ( const synthetic_generic_result = GenericResultV1.create(); try { - await syntheticCode({ logger }); + await syntheticCode({ logger, executionId }); synthetic_generic_result.ok = true; } catch (err: unknown) { synthetic_generic_result.ok = false; @@ -93,12 +98,18 @@ const runSynthetic = async ( * returns the results via res.send */ export function runSyntheticHandler( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - syntheticCode: (args: { logger: Logger }) => any + syntheticCode: (args: { + logger: Logger; + executionId: string | undefined; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + }) => any ) { // eslint-disable-next-line @typescript-eslint/no-explicit-any - return async (req: Request, res: Response): Promise => - res.send(await runSynthetic(syntheticCode)); + return async (req: Request, res: Response): Promise => { + res.send( + await runSynthetic(syntheticCode, req.get(syntheticExecutionIdHeader)) + ); + }; } export function firstUserErrorStackFrame( diff --git a/packages/synthetics-sdk-api/test/unit/handlers.spec.ts b/packages/synthetics-sdk-api/test/unit/handlers.spec.ts index fe91333a..9b4452df 100644 --- a/packages/synthetics-sdk-api/test/unit/handlers.spec.ts +++ b/packages/synthetics-sdk-api/test/unit/handlers.spec.ts @@ -15,6 +15,7 @@ import { SyntheticResult, runSyntheticHandler } from '../../src/index'; import { AssertionError, expect } from 'chai'; import { Request, Response } from 'express'; +import { createRequest } from 'node-mocks-http'; import { firstUserErrorStackFrame } from '../../src/handlers'; import ErrorStackParser = require('error-stack-parser'); @@ -24,13 +25,15 @@ describe('GCM Synthetics Handler', async () => { const handler = runSyntheticHandler(() => true); const runHandler = new Promise((resolve) => { + const mockRequest = createRequest({}); + let mockResponse = { send: (body: any) => { resolve(body); } } as Response; - handler({} as Request, mockResponse); + handler(mockRequest, mockResponse); }); const syntheticResult = await runHandler as SyntheticResult; @@ -53,13 +56,14 @@ describe('GCM Synthetics Handler', async () => { }); const runHandler = new Promise((resolve) => { + const mockRequest = createRequest({}); let mockResponse = { send: (body: any) => { resolve(body); } } as Response; - handler({} as Request, mockResponse); + handler(mockRequest, mockResponse); }); const syntheticResult = await runHandler as SyntheticResult; @@ -92,13 +96,14 @@ describe('GCM Synthetics Handler', async () => { const handler = runSyntheticHandler(handlerFunction); const runHandler = new Promise((resolve) => { + const mockRequest = createRequest({}); let mockResponse = { send: (body: any) => { resolve(body); } } as Response; - handler({} as Request, mockResponse); + handler(mockRequest, mockResponse); }); const syntheticResult = await runHandler as SyntheticResult; @@ -153,4 +158,29 @@ describe('GCM Synthetics Handler', async () => { ' at async MyClass.Function (/user/my/file.js:6:11)'); }); }); + + it('has execution id available', async () => { + const executionId = 'deadbeefdeadbeefdeadbeefdeadbeef' + const handler = runSyntheticHandler((args: {executionId: string|undefined}) => { + expect(args.executionId).to.equal(executionId); + }); + + const runHandler = new Promise((resolve) => { + const mockRequest = createRequest({ + headers: {"Synthetic-Execution-Id": executionId} + }); + + let mockResponse = { + send: (body: any) => { + resolve(body); + } + } as Response; + + handler(mockRequest, mockResponse); + }); + + const syntheticResult = await runHandler as SyntheticResult; + expect(syntheticResult?.synthetic_generic_result_v1?.ok).to.be.true; + expect(syntheticResult?.synthetic_generic_result_v1?.generic_error).to.be.undefined; + }); });