@autofleet/outbreak 2.3.2 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -3
- package/dist/index.d.ts +39 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var node_module=require('node:module'),c=require('node:http'),node_crypto=require('node:crypto'),w=require('node:async_hooks');var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var c__default=/*#__PURE__*/_interopDefault(c);var w__default=/*#__PURE__*/_interopDefault(w);var f={HTTP_REQUEST:"httpRequest",WEB_SOCKET:"webSocket",RABBIT:"rabbit",BULL_MQ:"bull"};var p=Symbol("outbreak-wrapped"),H=()=>node_crypto.randomUUID().split("-")[0],S=t=>t instanceof Request||Object.prototype.toString.call(t)==="[object Request]",
|
1
|
+
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var node_module=require('node:module'),c=require('node:http'),node_crypto=require('node:crypto'),w=require('node:async_hooks');var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var c__default=/*#__PURE__*/_interopDefault(c);var w__default=/*#__PURE__*/_interopDefault(w);var f={HTTP_REQUEST:"httpRequest",WEB_SOCKET:"webSocket",RABBIT:"rabbit",BULL_MQ:"bull"};var p=Symbol("outbreak-wrapped"),H=()=>node_crypto.randomUUID().split("-")[0],S=t=>t instanceof Request||Object.prototype.toString.call(t)==="[object Request]",I=t=>t instanceof Headers||Object.prototype.toString.call(t)==="[object Headers]";function L(t,e,r,n){let s=r.headers[t.correlationIdHeader]??H();e.getCurrentTrace().context.set(t.correlationIdHeader,s),n.setHeader(t.correlationIdHeader,s);}function k(t,e,r,n){t.setAndPropagateCorrelationId&&L(t,e,r,n),Object.entries(r.headers).forEach(([s,o])=>{(t.headersToCollect.has(s)||s.startsWith(t.headersPrefix))&&typeof o<"u"&&e.getCurrentTrace().context.set(s,o);});}function M(t,e,r){return (n,s,o,a)=>{e.newTrace(f.HTTP_REQUEST),k(t,e,n,s),r(n,s,o,a);}}function O(t,e){if(c__default.default.createServer[p])return;let r=c__default.default.createServer;function n(s,o){return o=o||s,r(M(t,e,o))}n[p]=true,c__default.default.createServer=n;}function m(t,e){let r=t.getCurrentTrace().context;r&&(e.headers||={},[...r.keys()].forEach(n=>{let s=r.get(n);typeof s=="symbol"||typeof s>"u"||(e.headers[n]=s);}));}function y(t,e){if(c__default.default[e][p])return;let r=c__default.default[e];function n(a,i,d){return m(t,i),r(a,i,d)}function s(a,i){return m(t,a),r(a,i)}function o(...a){let i={},d,u;return a.length===3?([d,i,u]=a,n(d,i,u)):([i,u]=a,s(i,u))}o[p]=true,c__default.default[e]=o;}function v(t,e){let r=t.getCurrentTrace()?.context;if(r)for(let n of r.keys()){let s=r.get(n);typeof s=="symbol"||typeof s>"u"||e.set(n,s);}}function P(t){if(globalThis.fetch[p])return;let e=globalThis.fetch;globalThis.fetch=(r,n)=>(S(r)&&r.headers&&!n?.headers?v(t,r.headers):(n??={},n.headers??=new Headers,I(n.headers)||(n.headers=new Headers(n.headers)),v(t,n.headers)),e(r,n)),globalThis.fetch[p]=true;}function g(t,e){O(t,e),y(e,"request"),y(e,"get"),P(e);}var q="x-trace-id",U=t=>{if(!Array.isArray(t))throw new Error("Header list is not an array");let e=/^[\x21-\x7e]+$/i,r=t.filter(n=>typeof n!="string"||!e.test(n));if(r.length>0)throw new Error(`Header list contains invalid headers: ${r}`)},E=(t={})=>{let{setAndPropagateCorrelationId:e=true,headersToPropagate:r=["x-request-id","x-variant-id"],headersPrefix:n="x-af-"}=t;return U(r),{setAndPropagateCorrelationId:e,correlationIdHeader:q,headersToCollect:new Set(r),headersPrefix:n}},R={load:E,correlationIdHeader:q};var T=class{constructor(e){this.type=e;this.id=node_crypto.randomUUID();this.context=new Map;this.nonHeaderContext=new Map;}},l=class{constructor(){this.#t=false;this.#r=new Map;this.#e={currentTrace:null,traces:new Map};this.#n=w__default.default.createHook({init:(e,r,n)=>{this.#e.traces.has(n)&&this.#e.traces.set(e,this.#e.traces.get(n));},before:e=>{this.#e.traces.has(e)&&(this.#r.set(e,this.#e.currentTrace),this.#e.currentTrace=this.#e.traces.get(e));},after:e=>{this.#e.traces.has(e)&&(this.#e.currentTrace=this.#r.get(e));},destroy:e=>{this.#e.traces.delete(e),this.#r.delete(e);}});this.enable=()=>(this.#t||(this.#n.enable(),this.#t=true),this.#n);this.newTrace=e=>{this.#t||this.enable();let r=new T(e);return this.#e.currentTrace=r,this.#e.traces.set(w__default.default.executionAsyncId(),r),r};this.getCurrentTrace=()=>this.#e.currentTrace||{};}#t;#r;#e;#n};var b=node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))),h=new l,F=()=>h.getCurrentTrace(),W=()=>F().context?.get(R.correlationIdHeader),x=t=>({[t]:W()}),_=(t,e)=>e(r=>Object.assign(r,x(t)));function B(t,e){let{format:r}=b("winston");t.format=r.combine(_(e,r)(),t.format);}function K(t){g(R.load(t),h),h.enable();let e=t?.loggerTraceKey||"traceId";t?.winstonLogger&&B(t.winstonLogger,e),t?.contextMiddlewareGetter?.(()=>x(e));try{b("bluebird").config({asyncHooks:!0});}catch{}}var {newTrace:re}=h;exports.default=K;exports.getCurrentContext=F;exports.getCurrentContextTraceId=W;exports.newTrace=re;exports.traceTypes=f;//# sourceMappingURL=index.cjs.map
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/const.ts","../src/http_wrapper.ts","../src/config.ts","../src/tracer.ts","../src/index.ts"],"names":["traceTypes","kOutbreakWrapped","generateShortId","randomUUID","isFetchRequest","headers","isFetchHeaders","setAndCollectCorrelationId","config","tracer","req","res","correlationId","collect","headerName","value","wrappedListener","listener","next","error","wrapHttpCreateServer","http","originalHttpCreateServer","wrappedHttpCreateServer","options","inject","currentTraceContext","header","wrapHttpRequest","originalMethodName","originalMethod","urlFirst","url","cb","optionsFirst","wrappedHttpRequest","args","callback","injectInFetchRequest","wrapFetch","originalFetch","input","init","wrapHttp","correlationIdHeader","validateHeaderList","headerNameRegex","invalidHeaders","h","load","overrides","setAndPropagateCorrelationId","headersToPropagate","headersPrefix","config_default","Trace","type","Tracer","#isTraceEnabled","#prevStates","#tracer","#hook","asyncHooks","asyncId","_type","triggerAsyncId","currentTrace","safeRequire","createRequire","getCurrentContextTraceId","contextMiddleware","loggerTraceKey","addMetadataToLog","format","info","lazilySetupWinstonLogger","winstonLogger","traceKey","outbreakInitialize","getCurrentContext","newTrace"],"mappings":"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","file":"index.cjs","sourcesContent":["export const traceTypes = {\n HTTP_REQUEST: 'httpRequest',\n WEB_SOCKET: 'webSocket',\n RABBIT: 'rabbit',\n BULL_MQ: 'bull',\n} as const;\nexport type TraceType = typeof traceTypes[keyof typeof traceTypes];\n","import http from 'node:http';\nimport { randomUUID } from 'node:crypto';\nimport type { URL } from 'node:url';\nimport { traceTypes } from './const';\nimport type { Tracer } from './tracer';\nimport type { LoadedConfig } from './config';\n\nexport const kOutbreakWrapped = Symbol('outbreak-wrapped');\nconst generateShortId = () => randomUUID().split('-')[0];\nconst isFetchRequest = (headers: unknown): headers is Request => headers instanceof Request || Object.prototype.toString.call(headers) === '[object Request]';\nconst isFetchHeaders = (headers: unknown): headers is Headers => headers instanceof Headers || Object.prototype.toString.call(headers) === '[object Headers]';\n\nfunction setAndCollectCorrelationId(config: LoadedConfig, tracer: Tracer, req: http.IncomingMessage, res: http.ServerResponse<http.IncomingMessage>): void {\n const correlationId = req.headers[config.correlationIdHeader] ?? generateShortId();\n tracer.getCurrentTrace().context.set(config.correlationIdHeader, correlationId as string);\n res.setHeader(config.correlationIdHeader, correlationId);\n}\n\nfunction collect(config: LoadedConfig, tracer: Tracer, req: http.IncomingMessage, res: http.ServerResponse<http.IncomingMessage>): void {\n if (config.setAndPropagateCorrelationId) {\n setAndCollectCorrelationId(config, tracer, req, res);\n }\n\n Object.entries(req.headers).forEach(([headerName, value]) => {\n const shouldCollect = config.headersToCollect.has(headerName) || headerName.startsWith(config.headersPrefix);\n if (shouldCollect && typeof value !== 'undefined') {\n tracer.getCurrentTrace().context.set(headerName, value as string);\n }\n });\n}\n\nfunction wrappedListener<\n Request extends typeof http.IncomingMessage = typeof http.IncomingMessage,\n Response extends typeof http.ServerResponse = typeof http.ServerResponse,\n>(\n config: LoadedConfig,\n tracer: Tracer,\n listener: http.RequestListener<Request, Response>,\n): http.RequestListener<Request, Response> {\n // @ts-expect-error we add next and error which don't exist on the original type\n return (req: http.IncomingMessage, res: http.ServerResponse, next: unknown, error: unknown): void => {\n tracer.newTrace(traceTypes.HTTP_REQUEST);\n\n collect(config, tracer, req, res);\n\n // @ts-expect-error we add next and error which don't exist on the original type\n listener(req, res, next, error);\n };\n}\n\nfunction wrapHttpCreateServer<\n Request extends typeof http.IncomingMessage = typeof http.IncomingMessage,\n Response extends typeof http.ServerResponse = typeof http.ServerResponse,\n>(config: LoadedConfig, tracer: Tracer): void {\n if (http.createServer[kOutbreakWrapped]) {\n return;\n }\n const originalHttpCreateServer = http.createServer;\n // args of http.createServer are ([options<Object>], [listener<Fn>]) Express only sends listener\n function wrappedHttpCreateServer(options: http.ServerOptions<Request, Response>, listener?: http.RequestListener<Request, Response>): http.Server<Request, Response>;\n function wrappedHttpCreateServer(listener?: http.RequestListener<Request, Response>): http.Server<Request, Response>;\n function wrappedHttpCreateServer(\n options: http.ServerOptions<Request, Response> | http.RequestListener<Request, Response>,\n listener?: http.RequestListener<Request, Response>,\n ): http.Server<Request, Response> {\n listener = listener || options as http.RequestListener<Request, Response>;\n return originalHttpCreateServer<Request, Response>(wrappedListener(config, tracer, listener));\n }\n wrappedHttpCreateServer[kOutbreakWrapped] = true;\n http.createServer = wrappedHttpCreateServer;\n}\n\nfunction inject(tracer: Tracer, options: http.RequestOptions): void {\n const currentTraceContext = tracer.getCurrentTrace().context;\n if (currentTraceContext) {\n options.headers ||= {};\n [...(currentTraceContext.keys())].forEach((header) => {\n options.headers[header] = currentTraceContext.get(header);\n });\n }\n}\nfunction wrapHttpRequest(tracer: Tracer, originalMethodName: 'request' | 'get'): void {\n if (http[originalMethodName][kOutbreakWrapped]) {\n return;\n }\n const originalMethod = http[originalMethodName];\n function urlFirst(url: string | URL, options: http.RequestOptions, cb: (res: http.IncomingMessage) => void): http.ClientRequest {\n inject(tracer, options);\n\n return originalMethod(url, options, cb);\n }\n\n function optionsFirst(options: http.RequestOptions, cb: (res: http.IncomingMessage) => void): http.ClientRequest {\n inject(tracer, options);\n\n return originalMethod(options, cb);\n }\n\n function wrappedHttpRequest(options: string | http.RequestOptions | URL, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;\n function wrappedHttpRequest(url: string | URL, options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;\n function wrappedHttpRequest(...args): http.ClientRequest {\n let options = {};\n let url: string | URL;\n let callback: (res: http.IncomingMessage) => void;\n\n if (args.length === 3) {\n [url, options, callback] = args;\n return urlFirst(url, options, callback);\n }\n [options, callback] = args;\n return optionsFirst(options, callback);\n }\n wrappedHttpRequest[kOutbreakWrapped] = true;\n http[originalMethodName] = wrappedHttpRequest;\n}\n\nfunction injectInFetchRequest(tracer: Tracer, headers: Headers): void {\n const currentTraceContext = tracer.getCurrentTrace()?.context;\n /* c8 ignore next 3 */\n if (!currentTraceContext) {\n return;\n }\n // eslint-disable-next-line no-restricted-syntax\n for (const header of currentTraceContext.keys()) {\n headers.set(header, currentTraceContext.get(header));\n }\n}\n\nfunction wrapFetch(tracer: Tracer): void {\n if (globalThis.fetch[kOutbreakWrapped]) {\n return;\n }\n const originalFetch = globalThis.fetch;\n globalThis.fetch = (input: string | URL | Request, init?: RequestInit): Promise<Response> => {\n if (isFetchRequest(input) && input.headers && !init?.headers) {\n injectInFetchRequest(tracer, input.headers);\n } else {\n init ??= {};\n init.headers ??= new Headers();\n if (!isFetchHeaders(init.headers)) {\n init.headers = new Headers(init.headers);\n }\n injectInFetchRequest(tracer, init.headers);\n }\n return originalFetch(input, init);\n };\n globalThis.fetch[kOutbreakWrapped] = true;\n}\n\nexport default function wrapHttp(config: LoadedConfig, tracer: Tracer): void {\n wrapHttpCreateServer(config, tracer);\n wrapHttpRequest(tracer, 'request');\n wrapHttpRequest(tracer, 'get');\n wrapFetch(tracer);\n}\n","const correlationIdHeader = 'x-trace-id';\n\nconst validateHeaderList = (headers: string[]): void => {\n if (!Array.isArray(headers)) {\n throw new Error('Header list is not an array');\n }\n\n // could be tighter - ASCII code between 33 and 126 at the moment\n const headerNameRegex = /^[\\x21-\\x7e]+$/i;\n\n const invalidHeaders = headers.filter((h) => typeof h !== 'string' || !headerNameRegex.test(h));\n\n if (invalidHeaders.length > 0) {\n throw new Error(`Header list contains invalid headers: ${invalidHeaders}`);\n }\n};\n\nexport interface Overrides {\n setAndPropagateCorrelationId?: boolean;\n headersToPropagate?: string[];\n headersPrefix?: string;\n}\n\nexport interface LoadedConfig extends Required<Pick<Overrides, 'setAndPropagateCorrelationId' | 'headersPrefix'>> {\n correlationIdHeader: string;\n headersToCollect: Set<string>;\n}\n\nconst load = (overrides: Overrides = {}): LoadedConfig => {\n const {\n setAndPropagateCorrelationId = true,\n headersToPropagate = [\n 'x-request-id',\n 'x-variant-id',\n ],\n headersPrefix = 'x-af-',\n } = overrides;\n\n validateHeaderList(headersToPropagate);\n\n return {\n setAndPropagateCorrelationId,\n correlationIdHeader,\n headersToCollect: new Set(headersToPropagate),\n headersPrefix,\n };\n};\n\nexport default {\n load,\n correlationIdHeader,\n};\n","import asyncHooks from 'node:async_hooks';\nimport { randomUUID } from 'node:crypto';\nimport type { TraceType } from './const';\n\ninterface TraceHolder {\n currentTrace: Trace | null;\n traces: Record<number, Trace>;\n}\n\nexport class Trace {\n public readonly id = randomUUID();\n\n public readonly context = new Map<string, unknown>();\n\n constructor(public type: TraceType) {}\n}\n\nexport class Tracer {\n #isTraceEnabled = false;\n\n #prevStates = new Map<number, Trace>();\n\n #tracer: TraceHolder = {\n currentTrace: null,\n traces: {},\n };\n\n #hook = asyncHooks.createHook({\n init: (asyncId, _type, triggerAsyncId) => {\n if (!this.#tracer.traces[triggerAsyncId]) {\n return;\n }\n this.#tracer.traces[asyncId] = this.#tracer.traces[triggerAsyncId];\n },\n before: (asyncId) => {\n if (!this.#tracer.traces[asyncId]) {\n return;\n }\n this.#prevStates.set(asyncId, this.#tracer.currentTrace);\n this.#tracer.currentTrace = this.#tracer.traces[asyncId];\n },\n after: (asyncId) => {\n if (!this.#tracer.traces[asyncId]) {\n return;\n }\n this.#tracer.currentTrace = this.#prevStates.get(asyncId);\n },\n destroy: (asyncId) => {\n if (this.#tracer.traces[asyncId]) {\n delete this.#tracer.traces[asyncId];\n this.#prevStates.delete(asyncId);\n }\n },\n });\n\n public enable = (): asyncHooks.AsyncHook => {\n if (!this.#isTraceEnabled) {\n this.#hook.enable();\n this.#isTraceEnabled = true;\n }\n return this.#hook;\n };\n\n public newTrace = (type: TraceType): Trace => {\n if (!this.#isTraceEnabled) {\n this.enable();\n }\n const currentTrace = new Trace(type);\n this.#tracer.currentTrace = currentTrace;\n this.#tracer.traces[asyncHooks.executionAsyncId()] = currentTrace;\n return currentTrace;\n };\n\n public getCurrentTrace = (): Trace | Record<string, never> => this.#tracer.currentTrace || {};\n}\n","import { createRequire } from 'node:module';\nimport type winston from 'winston';\nimport httpWrapper from './http_wrapper';\nimport config, { type Overrides } from './config';\nimport { type Trace, Tracer } from './tracer';\n\nexport { traceTypes } from './const';\n\nconst safeRequire = createRequire(import.meta.url);\n\nconst tracer = new Tracer();\n\ninterface Options extends Overrides {\n winstonLogger?: winston.Logger;\n contextMiddlewareGetter?: (middleware: () => Record<string, unknown>) => void;\n loggerTraceKey? : string;\n}\n\nexport const getCurrentContextTraceId = (): string | undefined => tracer.getCurrentTrace().context?.get(config.correlationIdHeader) as string | undefined;\nconst contextMiddleware = (loggerTraceKey: string) => ({ [loggerTraceKey]: getCurrentContextTraceId() });\nconst addMetadataToLog = (loggerTraceKey: string, format: typeof winston.format) => format((info) => Object.assign(info, contextMiddleware(loggerTraceKey)));\n\nfunction lazilySetupWinstonLogger(winstonLogger: winston.Logger, traceKey: string): void {\n const { format } = safeRequire('winston');\n winstonLogger.format = format.combine(\n addMetadataToLog(traceKey, format)(),\n winstonLogger.format,\n );\n}\n\nexport default function outbreakInitialize(options: Options): void {\n httpWrapper(config.load(options), tracer);\n tracer.enable();\n\n const traceKey = options.loggerTraceKey || 'traceId';\n if (options.winstonLogger) {\n lazilySetupWinstonLogger(options.winstonLogger, traceKey);\n }\n options.contextMiddlewareGetter?.(() => contextMiddleware(traceKey));\n\n // Make an attempt to enable async hooks for bluebird, if available\n try {\n const bluebird = safeRequire('bluebird');\n bluebird.config({ asyncHooks: true });\n /* c8 ignore next */\n } catch (e) { /* ignore */ }\n}\n\nexport const getCurrentContext = (): Trace | Record<string, never> => tracer.getCurrentTrace();\n\nexport const { newTrace } = tracer;\n"]}
|
1
|
+
{"version":3,"sources":["../src/const.ts","../src/http_wrapper.ts","../src/config.ts","../src/tracer.ts","../src/index.ts"],"names":["traceTypes","kOutbreakWrapped","generateShortId","randomUUID","isFetchRequest","headers","isFetchHeaders","setAndCollectCorrelationId","config","tracer","req","res","correlationId","collect","headerName","value","wrappedListener","listener","next","error","wrapHttpCreateServer","http","originalHttpCreateServer","wrappedHttpCreateServer","options","inject","currentTraceContext","header","wrapHttpRequest","originalMethodName","originalMethod","urlFirst","url","cb","optionsFirst","wrappedHttpRequest","args","callback","injectInFetchRequest","wrapFetch","originalFetch","input","init","wrapHttp","correlationIdHeader","validateHeaderList","headerNameRegex","invalidHeaders","h","load","overrides","setAndPropagateCorrelationId","headersToPropagate","headersPrefix","config_default","Trace","type","Tracer","#isTraceEnabled","#prevStates","#tracer","#hook","asyncHooks","asyncId","_type","triggerAsyncId","currentTrace","safeRequire","createRequire","getCurrentContext","getCurrentContextTraceId","contextMiddleware","loggerTraceKey","addMetadataToLog","format","info","lazilySetupWinstonLogger","winstonLogger","traceKey","outbreakInitialize","newTrace"],"mappings":"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","file":"index.cjs","sourcesContent":["/** The supported trace types. Each type represents a different way that can trigger an action. */\nexport const traceTypes = {\n HTTP_REQUEST: 'httpRequest',\n WEB_SOCKET: 'webSocket',\n RABBIT: 'rabbit',\n BULL_MQ: 'bull',\n} as const;\nexport type TraceType = typeof traceTypes[keyof typeof traceTypes];\n","import http from 'node:http';\nimport { randomUUID } from 'node:crypto';\nimport type { URL } from 'node:url';\nimport { traceTypes } from './const';\nimport type { Tracer } from './tracer';\nimport type { LoadedConfig } from './config';\n\nexport const kOutbreakWrapped = Symbol('outbreak-wrapped');\nconst generateShortId = () => randomUUID().split('-')[0];\nconst isFetchRequest = (headers: unknown): headers is Request => headers instanceof Request || Object.prototype.toString.call(headers) === '[object Request]';\nconst isFetchHeaders = (headers: unknown): headers is Headers => headers instanceof Headers || Object.prototype.toString.call(headers) === '[object Headers]';\n\nfunction setAndCollectCorrelationId(config: LoadedConfig, tracer: Tracer, req: http.IncomingMessage, res: http.ServerResponse<http.IncomingMessage>): void {\n const correlationId = req.headers[config.correlationIdHeader] ?? generateShortId();\n tracer.getCurrentTrace().context.set(config.correlationIdHeader, correlationId as string);\n res.setHeader(config.correlationIdHeader, correlationId);\n}\n\nfunction collect(config: LoadedConfig, tracer: Tracer, req: http.IncomingMessage, res: http.ServerResponse<http.IncomingMessage>): void {\n if (config.setAndPropagateCorrelationId) {\n setAndCollectCorrelationId(config, tracer, req, res);\n }\n\n Object.entries(req.headers).forEach(([headerName, value]) => {\n const shouldCollect = config.headersToCollect.has(headerName) || headerName.startsWith(config.headersPrefix);\n if (shouldCollect && typeof value !== 'undefined') {\n tracer.getCurrentTrace().context.set(headerName, value);\n }\n });\n}\n\nfunction wrappedListener<\n Request extends typeof http.IncomingMessage = typeof http.IncomingMessage,\n Response extends typeof http.ServerResponse = typeof http.ServerResponse,\n>(\n config: LoadedConfig,\n tracer: Tracer,\n listener: http.RequestListener<Request, Response>,\n): http.RequestListener<Request, Response> {\n // @ts-expect-error we add next and error which don't exist on the original type\n return (req: http.IncomingMessage, res: http.ServerResponse, next: unknown, error: unknown): void => {\n tracer.newTrace(traceTypes.HTTP_REQUEST);\n\n collect(config, tracer, req, res);\n\n // @ts-expect-error we add next and error which don't exist on the original type\n listener(req, res, next, error);\n };\n}\n\nfunction wrapHttpCreateServer<\n Request extends typeof http.IncomingMessage = typeof http.IncomingMessage,\n Response extends typeof http.ServerResponse = typeof http.ServerResponse,\n>(config: LoadedConfig, tracer: Tracer): void {\n if (http.createServer[kOutbreakWrapped]) {\n return;\n }\n const originalHttpCreateServer = http.createServer;\n // args of http.createServer are ([options<Object>], [listener<Fn>]) Express only sends listener\n function wrappedHttpCreateServer(options: http.ServerOptions<Request, Response>, listener?: http.RequestListener<Request, Response>): http.Server<Request, Response>;\n function wrappedHttpCreateServer(listener?: http.RequestListener<Request, Response>): http.Server<Request, Response>;\n function wrappedHttpCreateServer(\n options: http.ServerOptions<Request, Response> | http.RequestListener<Request, Response>,\n listener?: http.RequestListener<Request, Response>,\n ): http.Server<Request, Response> {\n listener = listener || options as http.RequestListener<Request, Response>;\n return originalHttpCreateServer<Request, Response>(wrappedListener(config, tracer, listener));\n }\n wrappedHttpCreateServer[kOutbreakWrapped] = true;\n http.createServer = wrappedHttpCreateServer;\n}\n\nfunction inject(tracer: Tracer, options: http.RequestOptions): void {\n const currentTraceContext = tracer.getCurrentTrace().context;\n if (currentTraceContext) {\n options.headers ||= {};\n [...(currentTraceContext.keys())].forEach((header) => {\n const value = currentTraceContext.get(header);\n if (typeof value === 'symbol' || typeof value === 'undefined') {\n return;\n }\n options.headers[header] = value as string;\n });\n }\n}\nfunction wrapHttpRequest(tracer: Tracer, originalMethodName: 'request' | 'get'): void {\n if (http[originalMethodName][kOutbreakWrapped]) {\n return;\n }\n const originalMethod = http[originalMethodName];\n function urlFirst(url: string | URL, options: http.RequestOptions, cb: (res: http.IncomingMessage) => void): http.ClientRequest {\n inject(tracer, options);\n\n return originalMethod(url, options, cb);\n }\n\n function optionsFirst(options: http.RequestOptions, cb: (res: http.IncomingMessage) => void): http.ClientRequest {\n inject(tracer, options);\n\n return originalMethod(options, cb);\n }\n\n function wrappedHttpRequest(options: string | http.RequestOptions | URL, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;\n function wrappedHttpRequest(url: string | URL, options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;\n function wrappedHttpRequest(...args): http.ClientRequest {\n let options = {};\n let url: string | URL;\n let callback: (res: http.IncomingMessage) => void;\n\n if (args.length === 3) {\n [url, options, callback] = args;\n return urlFirst(url, options, callback);\n }\n [options, callback] = args;\n return optionsFirst(options, callback);\n }\n wrappedHttpRequest[kOutbreakWrapped] = true;\n http[originalMethodName] = wrappedHttpRequest;\n}\n\nfunction injectInFetchRequest(tracer: Tracer, headers: Headers): void {\n const currentTraceContext = tracer.getCurrentTrace()?.context;\n /* c8 ignore next 3 */\n if (!currentTraceContext) {\n return;\n }\n // eslint-disable-next-line no-restricted-syntax\n for (const header of currentTraceContext.keys()) {\n const value = currentTraceContext.get(header);\n if (typeof value === 'symbol' || typeof value === 'undefined') {\n // eslint-disable-next-line no-continue\n continue;\n }\n headers.set(header, value as string);\n }\n}\n\nfunction wrapFetch(tracer: Tracer): void {\n if (globalThis.fetch[kOutbreakWrapped]) {\n return;\n }\n const originalFetch = globalThis.fetch;\n globalThis.fetch = (input: string | URL | Request, init?: RequestInit): Promise<Response> => {\n if (isFetchRequest(input) && input.headers && !init?.headers) {\n injectInFetchRequest(tracer, input.headers);\n } else {\n init ??= {};\n init.headers ??= new Headers();\n if (!isFetchHeaders(init.headers)) {\n init.headers = new Headers(init.headers);\n }\n injectInFetchRequest(tracer, init.headers);\n }\n return originalFetch(input, init);\n };\n globalThis.fetch[kOutbreakWrapped] = true;\n}\n\nexport default function wrapHttp(config: LoadedConfig, tracer: Tracer): void {\n wrapHttpCreateServer(config, tracer);\n wrapHttpRequest(tracer, 'request');\n wrapHttpRequest(tracer, 'get');\n wrapFetch(tracer);\n}\n","const correlationIdHeader = 'x-trace-id';\n\nconst validateHeaderList = (headers: string[]): void => {\n if (!Array.isArray(headers)) {\n throw new Error('Header list is not an array');\n }\n\n // could be tighter - ASCII code between 33 and 126 at the moment\n // TODO: we can simply use the regex node uses? https://github.com/nodejs/node/blob/b07ff551db152ccb507e71160ce077e235206b16/lib/_http_common.js#L214\n const headerNameRegex = /^[\\x21-\\x7e]+$/i;\n\n const invalidHeaders = headers.filter((h) => typeof h !== 'string' || !headerNameRegex.test(h));\n\n if (invalidHeaders.length > 0) {\n throw new Error(`Header list contains invalid headers: ${invalidHeaders}`);\n }\n};\n\nexport interface Overrides {\n /**\n * Whether to set and propagate the correlation ID.\n * When set to `true`, each request will either use the correlation ID from the incoming request or generate a new one.\n * The correlation ID will be propagated to any outgoing HTTP requests, as well as to the response of the current request.\n * @default true\n */\n setAndPropagateCorrelationId?: boolean;\n /**\n * The list of exact headers to propagate from incoming requests to outgoing requests.\n * @default ['x-request-id', 'x-variant-id']\n */\n headersToPropagate?: string[];\n /** The prefix defining which headers will be collected from incoming requests and passed on to any outgoing request. @default 'x-af-' */\n headersPrefix?: string;\n}\n\nexport interface LoadedConfig extends Required<Pick<Overrides, 'setAndPropagateCorrelationId' | 'headersPrefix'>> {\n correlationIdHeader: string;\n headersToCollect: Set<string>;\n}\n\nconst load = (overrides: Overrides = {}): LoadedConfig => {\n const {\n setAndPropagateCorrelationId = true,\n headersToPropagate = [\n 'x-request-id',\n 'x-variant-id',\n ],\n headersPrefix = 'x-af-',\n } = overrides;\n\n validateHeaderList(headersToPropagate);\n\n return {\n setAndPropagateCorrelationId,\n correlationIdHeader,\n headersToCollect: new Set(headersToPropagate),\n headersPrefix,\n };\n};\n\nexport default {\n load,\n correlationIdHeader,\n};\n","import asyncHooks from 'node:async_hooks';\nimport { randomUUID } from 'node:crypto';\nimport type { TraceType } from './const';\n\ninterface TraceHolder {\n currentTrace: Trace | null;\n traces: Map<number, Trace>;\n}\n\nexport class Trace {\n /** The unique identifier of the trace. */\n public readonly id = randomUUID();\n\n /** The context of the trace. Any item set to this map will be injected into the HTTP headers of any outgoing HTTP request. */\n public readonly context = new Map<string, unknown>();\n\n /** The non-header context of the trace. This is not injected into the HTTP headers outgoing HTTP request. */\n public readonly nonHeaderContext = new Map<string, unknown>();\n\n constructor(\n /** The type of action which has started the action creating this trace. */\n public type: TraceType,\n ) {}\n}\n\nexport class Tracer {\n #isTraceEnabled = false;\n\n #prevStates = new Map<number, Trace>();\n\n #tracer: TraceHolder = {\n currentTrace: null,\n traces: new Map(),\n };\n\n #hook = asyncHooks.createHook({\n init: (asyncId, _type, triggerAsyncId) => {\n if (!this.#tracer.traces.has(triggerAsyncId)) {\n return;\n }\n this.#tracer.traces.set(asyncId, this.#tracer.traces.get(triggerAsyncId));\n },\n before: (asyncId) => {\n if (!this.#tracer.traces.has(asyncId)) {\n return;\n }\n this.#prevStates.set(asyncId, this.#tracer.currentTrace);\n this.#tracer.currentTrace = this.#tracer.traces.get(asyncId);\n },\n after: (asyncId) => {\n if (!this.#tracer.traces.has(asyncId)) {\n return;\n }\n this.#tracer.currentTrace = this.#prevStates.get(asyncId);\n },\n destroy: (asyncId) => {\n this.#tracer.traces.delete(asyncId);\n this.#prevStates.delete(asyncId);\n },\n });\n\n public enable = (): asyncHooks.AsyncHook => {\n if (!this.#isTraceEnabled) {\n this.#hook.enable();\n this.#isTraceEnabled = true;\n }\n return this.#hook;\n };\n\n public newTrace = (type: TraceType): Trace => {\n if (!this.#isTraceEnabled) {\n this.enable();\n }\n const currentTrace = new Trace(type);\n this.#tracer.currentTrace = currentTrace;\n this.#tracer.traces.set(asyncHooks.executionAsyncId(), currentTrace);\n return currentTrace;\n };\n\n public getCurrentTrace = (): Trace | Record<string, never> => this.#tracer.currentTrace || {};\n}\n","import { createRequire } from 'node:module';\nimport type winston from 'winston';\nimport httpWrapper from './http_wrapper';\nimport config, { type Overrides } from './config';\nimport { type Trace, Tracer } from './tracer';\n\nexport { traceTypes } from './const';\n\nconst safeRequire = createRequire(import.meta.url);\n\nconst tracer = new Tracer();\n\ninterface Options extends Overrides {\n /**\n * The winston logger used for logging.\n *\n * If provided, the logger's `format` will combine an additional format which injects the `traceId` into the log, using the {@link loggerTraceKey} as the trace's key.\n */\n winstonLogger?: winston.Logger;\n /**\n * A function which will be called with the middleware used to inject the trace ID into the logger.\n *\n * The trace ID will be injected using the {@link loggerTraceKey} as the trace's key.\n */\n contextMiddlewareGetter?: (middleware: () => Record<string, unknown>) => void;\n /** The key used to inject the trace ID into the logger. @default 'traceId' */\n loggerTraceKey? : string;\n}\n\n/** Get the current trace from the context. */\nexport const getCurrentContext = (): Trace | Record<string, never> => tracer.getCurrentTrace();\n/** Get the trace ID from the current context. */\nexport const getCurrentContextTraceId = (): string | undefined => getCurrentContext().context?.get(config.correlationIdHeader) as string | undefined;\nconst contextMiddleware = (loggerTraceKey: string) => ({ [loggerTraceKey]: getCurrentContextTraceId() });\nconst addMetadataToLog = (loggerTraceKey: string, format: typeof winston.format) => format((info) => Object.assign(info, contextMiddleware(loggerTraceKey)));\n\nfunction lazilySetupWinstonLogger(winstonLogger: winston.Logger, traceKey: string): void {\n const { format } = safeRequire('winston');\n winstonLogger.format = format.combine(\n addMetadataToLog(traceKey, format)(),\n winstonLogger.format,\n );\n}\n\nexport default function outbreakInitialize(options?: Options): void {\n httpWrapper(config.load(options), tracer);\n tracer.enable();\n\n const traceKey = options?.loggerTraceKey || 'traceId';\n if (options?.winstonLogger) {\n lazilySetupWinstonLogger(options.winstonLogger, traceKey);\n }\n options?.contextMiddlewareGetter?.(() => contextMiddleware(traceKey));\n\n // Make an attempt to enable async hooks for bluebird, if available\n try {\n const bluebird = safeRequire('bluebird');\n bluebird.config({ asyncHooks: true });\n /* c8 ignore next */\n } catch (e) { /* ignore */ }\n}\n\n/**\n * Create a new trace, representing a new action starting.\n * @param type The type of action which is starting the trace.\n */\nexport const { newTrace } = tracer;\n"]}
|
package/dist/index.d.cts
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import winston from 'winston';
|
2
2
|
|
3
|
+
/** The supported trace types. Each type represents a different way that can trigger an action. */
|
3
4
|
declare const traceTypes: {
|
4
5
|
readonly HTTP_REQUEST: "httpRequest";
|
5
6
|
readonly WEB_SOCKET: "webSocket";
|
@@ -9,26 +10,61 @@ declare const traceTypes: {
|
|
9
10
|
type TraceType = typeof traceTypes[keyof typeof traceTypes];
|
10
11
|
|
11
12
|
interface Overrides {
|
13
|
+
/**
|
14
|
+
* Whether to set and propagate the correlation ID.
|
15
|
+
* When set to `true`, each request will either use the correlation ID from the incoming request or generate a new one.
|
16
|
+
* The correlation ID will be propagated to any outgoing HTTP requests, as well as to the response of the current request.
|
17
|
+
* @default true
|
18
|
+
*/
|
12
19
|
setAndPropagateCorrelationId?: boolean;
|
20
|
+
/**
|
21
|
+
* The list of exact headers to propagate from incoming requests to outgoing requests.
|
22
|
+
* @default ['x-request-id', 'x-variant-id']
|
23
|
+
*/
|
13
24
|
headersToPropagate?: string[];
|
25
|
+
/** The prefix defining which headers will be collected from incoming requests and passed on to any outgoing request. @default 'x-af-' */
|
14
26
|
headersPrefix?: string;
|
15
27
|
}
|
16
28
|
|
17
29
|
declare class Trace {
|
30
|
+
/** The type of action which has started the action creating this trace. */
|
18
31
|
type: TraceType;
|
32
|
+
/** The unique identifier of the trace. */
|
19
33
|
readonly id: `${string}-${string}-${string}-${string}-${string}`;
|
34
|
+
/** The context of the trace. Any item set to this map will be injected into the HTTP headers of any outgoing HTTP request. */
|
20
35
|
readonly context: Map<string, unknown>;
|
21
|
-
|
36
|
+
/** The non-header context of the trace. This is not injected into the HTTP headers outgoing HTTP request. */
|
37
|
+
readonly nonHeaderContext: Map<string, unknown>;
|
38
|
+
constructor(
|
39
|
+
/** The type of action which has started the action creating this trace. */
|
40
|
+
type: TraceType);
|
22
41
|
}
|
23
42
|
|
24
43
|
interface Options extends Overrides {
|
44
|
+
/**
|
45
|
+
* The winston logger used for logging.
|
46
|
+
*
|
47
|
+
* If provided, the logger's `format` will combine an additional format which injects the `traceId` into the log, using the {@link loggerTraceKey} as the trace's key.
|
48
|
+
*/
|
25
49
|
winstonLogger?: winston.Logger;
|
50
|
+
/**
|
51
|
+
* A function which will be called with the middleware used to inject the trace ID into the logger.
|
52
|
+
*
|
53
|
+
* The trace ID will be injected using the {@link loggerTraceKey} as the trace's key.
|
54
|
+
*/
|
26
55
|
contextMiddlewareGetter?: (middleware: () => Record<string, unknown>) => void;
|
56
|
+
/** The key used to inject the trace ID into the logger. @default 'traceId' */
|
27
57
|
loggerTraceKey?: string;
|
28
58
|
}
|
29
|
-
|
30
|
-
declare function outbreakInitialize(options: Options): void;
|
59
|
+
/** Get the current trace from the context. */
|
31
60
|
declare const getCurrentContext: () => Trace | Record<string, never>;
|
61
|
+
/** Get the trace ID from the current context. */
|
62
|
+
declare const getCurrentContextTraceId: () => string | undefined;
|
63
|
+
declare function outbreakInitialize(options?: Options): void;
|
64
|
+
/**
|
65
|
+
* Create a new trace, representing a new action starting.
|
66
|
+
* @param type The type of action which is starting the trace.
|
67
|
+
*/
|
32
68
|
declare const newTrace: (type: TraceType) => Trace;
|
33
69
|
|
34
70
|
export { outbreakInitialize as default, getCurrentContext, getCurrentContextTraceId, newTrace, traceTypes };
|
package/dist/index.d.ts
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import winston from 'winston';
|
2
2
|
|
3
|
+
/** The supported trace types. Each type represents a different way that can trigger an action. */
|
3
4
|
declare const traceTypes: {
|
4
5
|
readonly HTTP_REQUEST: "httpRequest";
|
5
6
|
readonly WEB_SOCKET: "webSocket";
|
@@ -9,26 +10,61 @@ declare const traceTypes: {
|
|
9
10
|
type TraceType = typeof traceTypes[keyof typeof traceTypes];
|
10
11
|
|
11
12
|
interface Overrides {
|
13
|
+
/**
|
14
|
+
* Whether to set and propagate the correlation ID.
|
15
|
+
* When set to `true`, each request will either use the correlation ID from the incoming request or generate a new one.
|
16
|
+
* The correlation ID will be propagated to any outgoing HTTP requests, as well as to the response of the current request.
|
17
|
+
* @default true
|
18
|
+
*/
|
12
19
|
setAndPropagateCorrelationId?: boolean;
|
20
|
+
/**
|
21
|
+
* The list of exact headers to propagate from incoming requests to outgoing requests.
|
22
|
+
* @default ['x-request-id', 'x-variant-id']
|
23
|
+
*/
|
13
24
|
headersToPropagate?: string[];
|
25
|
+
/** The prefix defining which headers will be collected from incoming requests and passed on to any outgoing request. @default 'x-af-' */
|
14
26
|
headersPrefix?: string;
|
15
27
|
}
|
16
28
|
|
17
29
|
declare class Trace {
|
30
|
+
/** The type of action which has started the action creating this trace. */
|
18
31
|
type: TraceType;
|
32
|
+
/** The unique identifier of the trace. */
|
19
33
|
readonly id: `${string}-${string}-${string}-${string}-${string}`;
|
34
|
+
/** The context of the trace. Any item set to this map will be injected into the HTTP headers of any outgoing HTTP request. */
|
20
35
|
readonly context: Map<string, unknown>;
|
21
|
-
|
36
|
+
/** The non-header context of the trace. This is not injected into the HTTP headers outgoing HTTP request. */
|
37
|
+
readonly nonHeaderContext: Map<string, unknown>;
|
38
|
+
constructor(
|
39
|
+
/** The type of action which has started the action creating this trace. */
|
40
|
+
type: TraceType);
|
22
41
|
}
|
23
42
|
|
24
43
|
interface Options extends Overrides {
|
44
|
+
/**
|
45
|
+
* The winston logger used for logging.
|
46
|
+
*
|
47
|
+
* If provided, the logger's `format` will combine an additional format which injects the `traceId` into the log, using the {@link loggerTraceKey} as the trace's key.
|
48
|
+
*/
|
25
49
|
winstonLogger?: winston.Logger;
|
50
|
+
/**
|
51
|
+
* A function which will be called with the middleware used to inject the trace ID into the logger.
|
52
|
+
*
|
53
|
+
* The trace ID will be injected using the {@link loggerTraceKey} as the trace's key.
|
54
|
+
*/
|
26
55
|
contextMiddlewareGetter?: (middleware: () => Record<string, unknown>) => void;
|
56
|
+
/** The key used to inject the trace ID into the logger. @default 'traceId' */
|
27
57
|
loggerTraceKey?: string;
|
28
58
|
}
|
29
|
-
|
30
|
-
declare function outbreakInitialize(options: Options): void;
|
59
|
+
/** Get the current trace from the context. */
|
31
60
|
declare const getCurrentContext: () => Trace | Record<string, never>;
|
61
|
+
/** Get the trace ID from the current context. */
|
62
|
+
declare const getCurrentContextTraceId: () => string | undefined;
|
63
|
+
declare function outbreakInitialize(options?: Options): void;
|
64
|
+
/**
|
65
|
+
* Create a new trace, representing a new action starting.
|
66
|
+
* @param type The type of action which is starting the trace.
|
67
|
+
*/
|
32
68
|
declare const newTrace: (type: TraceType) => Trace;
|
33
69
|
|
34
70
|
export { outbreakInitialize as default, getCurrentContext, getCurrentContextTraceId, newTrace, traceTypes };
|
package/dist/index.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
import {createRequire}from'node:module';import c from'node:http';import {randomUUID}from'node:crypto';import w from'node:async_hooks';var f={HTTP_REQUEST:"httpRequest",WEB_SOCKET:"webSocket",RABBIT:"rabbit",BULL_MQ:"bull"};var p=Symbol("outbreak-wrapped"),H=()=>randomUUID().split("-")[0],S=t=>t instanceof Request||Object.prototype.toString.call(t)==="[object Request]",
|
1
|
+
import {createRequire}from'node:module';import c from'node:http';import {randomUUID}from'node:crypto';import w from'node:async_hooks';var f={HTTP_REQUEST:"httpRequest",WEB_SOCKET:"webSocket",RABBIT:"rabbit",BULL_MQ:"bull"};var p=Symbol("outbreak-wrapped"),H=()=>randomUUID().split("-")[0],S=t=>t instanceof Request||Object.prototype.toString.call(t)==="[object Request]",I=t=>t instanceof Headers||Object.prototype.toString.call(t)==="[object Headers]";function L(t,e,r,n){let s=r.headers[t.correlationIdHeader]??H();e.getCurrentTrace().context.set(t.correlationIdHeader,s),n.setHeader(t.correlationIdHeader,s);}function k(t,e,r,n){t.setAndPropagateCorrelationId&&L(t,e,r,n),Object.entries(r.headers).forEach(([s,o])=>{(t.headersToCollect.has(s)||s.startsWith(t.headersPrefix))&&typeof o<"u"&&e.getCurrentTrace().context.set(s,o);});}function M(t,e,r){return (n,s,o,a)=>{e.newTrace(f.HTTP_REQUEST),k(t,e,n,s),r(n,s,o,a);}}function O(t,e){if(c.createServer[p])return;let r=c.createServer;function n(s,o){return o=o||s,r(M(t,e,o))}n[p]=true,c.createServer=n;}function m(t,e){let r=t.getCurrentTrace().context;r&&(e.headers||={},[...r.keys()].forEach(n=>{let s=r.get(n);typeof s=="symbol"||typeof s>"u"||(e.headers[n]=s);}));}function y(t,e){if(c[e][p])return;let r=c[e];function n(a,i,d){return m(t,i),r(a,i,d)}function s(a,i){return m(t,a),r(a,i)}function o(...a){let i={},d,u;return a.length===3?([d,i,u]=a,n(d,i,u)):([i,u]=a,s(i,u))}o[p]=true,c[e]=o;}function v(t,e){let r=t.getCurrentTrace()?.context;if(r)for(let n of r.keys()){let s=r.get(n);typeof s=="symbol"||typeof s>"u"||e.set(n,s);}}function P(t){if(globalThis.fetch[p])return;let e=globalThis.fetch;globalThis.fetch=(r,n)=>(S(r)&&r.headers&&!n?.headers?v(t,r.headers):(n??={},n.headers??=new Headers,I(n.headers)||(n.headers=new Headers(n.headers)),v(t,n.headers)),e(r,n)),globalThis.fetch[p]=true;}function g(t,e){O(t,e),y(e,"request"),y(e,"get"),P(e);}var q="x-trace-id",U=t=>{if(!Array.isArray(t))throw new Error("Header list is not an array");let e=/^[\x21-\x7e]+$/i,r=t.filter(n=>typeof n!="string"||!e.test(n));if(r.length>0)throw new Error(`Header list contains invalid headers: ${r}`)},E=(t={})=>{let{setAndPropagateCorrelationId:e=true,headersToPropagate:r=["x-request-id","x-variant-id"],headersPrefix:n="x-af-"}=t;return U(r),{setAndPropagateCorrelationId:e,correlationIdHeader:q,headersToCollect:new Set(r),headersPrefix:n}},R={load:E,correlationIdHeader:q};var T=class{constructor(e){this.type=e;this.id=randomUUID();this.context=new Map;this.nonHeaderContext=new Map;}},l=class{constructor(){this.#t=false;this.#r=new Map;this.#e={currentTrace:null,traces:new Map};this.#n=w.createHook({init:(e,r,n)=>{this.#e.traces.has(n)&&this.#e.traces.set(e,this.#e.traces.get(n));},before:e=>{this.#e.traces.has(e)&&(this.#r.set(e,this.#e.currentTrace),this.#e.currentTrace=this.#e.traces.get(e));},after:e=>{this.#e.traces.has(e)&&(this.#e.currentTrace=this.#r.get(e));},destroy:e=>{this.#e.traces.delete(e),this.#r.delete(e);}});this.enable=()=>(this.#t||(this.#n.enable(),this.#t=true),this.#n);this.newTrace=e=>{this.#t||this.enable();let r=new T(e);return this.#e.currentTrace=r,this.#e.traces.set(w.executionAsyncId(),r),r};this.getCurrentTrace=()=>this.#e.currentTrace||{};}#t;#r;#e;#n};var b=createRequire(import.meta.url),h=new l,F=()=>h.getCurrentTrace(),W=()=>F().context?.get(R.correlationIdHeader),x=t=>({[t]:W()}),_=(t,e)=>e(r=>Object.assign(r,x(t)));function B(t,e){let{format:r}=b("winston");t.format=r.combine(_(e,r)(),t.format);}function K(t){g(R.load(t),h),h.enable();let e=t?.loggerTraceKey||"traceId";t?.winstonLogger&&B(t.winstonLogger,e),t?.contextMiddlewareGetter?.(()=>x(e));try{b("bluebird").config({asyncHooks:!0});}catch{}}var {newTrace:re}=h;export{K as default,F as getCurrentContext,W as getCurrentContextTraceId,re as newTrace,f as traceTypes};//# sourceMappingURL=index.js.map
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/const.ts","../src/http_wrapper.ts","../src/config.ts","../src/tracer.ts","../src/index.ts"],"names":["traceTypes","kOutbreakWrapped","generateShortId","randomUUID","isFetchRequest","headers","isFetchHeaders","setAndCollectCorrelationId","config","tracer","req","res","correlationId","collect","headerName","value","wrappedListener","listener","next","error","wrapHttpCreateServer","http","originalHttpCreateServer","wrappedHttpCreateServer","options","inject","currentTraceContext","header","wrapHttpRequest","originalMethodName","originalMethod","urlFirst","url","cb","optionsFirst","wrappedHttpRequest","args","callback","injectInFetchRequest","wrapFetch","originalFetch","input","init","wrapHttp","correlationIdHeader","validateHeaderList","headerNameRegex","invalidHeaders","h","load","overrides","setAndPropagateCorrelationId","headersToPropagate","headersPrefix","config_default","Trace","type","Tracer","#isTraceEnabled","#prevStates","#tracer","#hook","asyncHooks","asyncId","_type","triggerAsyncId","currentTrace","safeRequire","createRequire","getCurrentContextTraceId","contextMiddleware","loggerTraceKey","addMetadataToLog","format","info","lazilySetupWinstonLogger","winstonLogger","traceKey","outbreakInitialize","getCurrentContext","newTrace"],"mappings":"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","file":"index.js","sourcesContent":["export const traceTypes = {\n HTTP_REQUEST: 'httpRequest',\n WEB_SOCKET: 'webSocket',\n RABBIT: 'rabbit',\n BULL_MQ: 'bull',\n} as const;\nexport type TraceType = typeof traceTypes[keyof typeof traceTypes];\n","import http from 'node:http';\nimport { randomUUID } from 'node:crypto';\nimport type { URL } from 'node:url';\nimport { traceTypes } from './const';\nimport type { Tracer } from './tracer';\nimport type { LoadedConfig } from './config';\n\nexport const kOutbreakWrapped = Symbol('outbreak-wrapped');\nconst generateShortId = () => randomUUID().split('-')[0];\nconst isFetchRequest = (headers: unknown): headers is Request => headers instanceof Request || Object.prototype.toString.call(headers) === '[object Request]';\nconst isFetchHeaders = (headers: unknown): headers is Headers => headers instanceof Headers || Object.prototype.toString.call(headers) === '[object Headers]';\n\nfunction setAndCollectCorrelationId(config: LoadedConfig, tracer: Tracer, req: http.IncomingMessage, res: http.ServerResponse<http.IncomingMessage>): void {\n const correlationId = req.headers[config.correlationIdHeader] ?? generateShortId();\n tracer.getCurrentTrace().context.set(config.correlationIdHeader, correlationId as string);\n res.setHeader(config.correlationIdHeader, correlationId);\n}\n\nfunction collect(config: LoadedConfig, tracer: Tracer, req: http.IncomingMessage, res: http.ServerResponse<http.IncomingMessage>): void {\n if (config.setAndPropagateCorrelationId) {\n setAndCollectCorrelationId(config, tracer, req, res);\n }\n\n Object.entries(req.headers).forEach(([headerName, value]) => {\n const shouldCollect = config.headersToCollect.has(headerName) || headerName.startsWith(config.headersPrefix);\n if (shouldCollect && typeof value !== 'undefined') {\n tracer.getCurrentTrace().context.set(headerName, value as string);\n }\n });\n}\n\nfunction wrappedListener<\n Request extends typeof http.IncomingMessage = typeof http.IncomingMessage,\n Response extends typeof http.ServerResponse = typeof http.ServerResponse,\n>(\n config: LoadedConfig,\n tracer: Tracer,\n listener: http.RequestListener<Request, Response>,\n): http.RequestListener<Request, Response> {\n // @ts-expect-error we add next and error which don't exist on the original type\n return (req: http.IncomingMessage, res: http.ServerResponse, next: unknown, error: unknown): void => {\n tracer.newTrace(traceTypes.HTTP_REQUEST);\n\n collect(config, tracer, req, res);\n\n // @ts-expect-error we add next and error which don't exist on the original type\n listener(req, res, next, error);\n };\n}\n\nfunction wrapHttpCreateServer<\n Request extends typeof http.IncomingMessage = typeof http.IncomingMessage,\n Response extends typeof http.ServerResponse = typeof http.ServerResponse,\n>(config: LoadedConfig, tracer: Tracer): void {\n if (http.createServer[kOutbreakWrapped]) {\n return;\n }\n const originalHttpCreateServer = http.createServer;\n // args of http.createServer are ([options<Object>], [listener<Fn>]) Express only sends listener\n function wrappedHttpCreateServer(options: http.ServerOptions<Request, Response>, listener?: http.RequestListener<Request, Response>): http.Server<Request, Response>;\n function wrappedHttpCreateServer(listener?: http.RequestListener<Request, Response>): http.Server<Request, Response>;\n function wrappedHttpCreateServer(\n options: http.ServerOptions<Request, Response> | http.RequestListener<Request, Response>,\n listener?: http.RequestListener<Request, Response>,\n ): http.Server<Request, Response> {\n listener = listener || options as http.RequestListener<Request, Response>;\n return originalHttpCreateServer<Request, Response>(wrappedListener(config, tracer, listener));\n }\n wrappedHttpCreateServer[kOutbreakWrapped] = true;\n http.createServer = wrappedHttpCreateServer;\n}\n\nfunction inject(tracer: Tracer, options: http.RequestOptions): void {\n const currentTraceContext = tracer.getCurrentTrace().context;\n if (currentTraceContext) {\n options.headers ||= {};\n [...(currentTraceContext.keys())].forEach((header) => {\n options.headers[header] = currentTraceContext.get(header);\n });\n }\n}\nfunction wrapHttpRequest(tracer: Tracer, originalMethodName: 'request' | 'get'): void {\n if (http[originalMethodName][kOutbreakWrapped]) {\n return;\n }\n const originalMethod = http[originalMethodName];\n function urlFirst(url: string | URL, options: http.RequestOptions, cb: (res: http.IncomingMessage) => void): http.ClientRequest {\n inject(tracer, options);\n\n return originalMethod(url, options, cb);\n }\n\n function optionsFirst(options: http.RequestOptions, cb: (res: http.IncomingMessage) => void): http.ClientRequest {\n inject(tracer, options);\n\n return originalMethod(options, cb);\n }\n\n function wrappedHttpRequest(options: string | http.RequestOptions | URL, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;\n function wrappedHttpRequest(url: string | URL, options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;\n function wrappedHttpRequest(...args): http.ClientRequest {\n let options = {};\n let url: string | URL;\n let callback: (res: http.IncomingMessage) => void;\n\n if (args.length === 3) {\n [url, options, callback] = args;\n return urlFirst(url, options, callback);\n }\n [options, callback] = args;\n return optionsFirst(options, callback);\n }\n wrappedHttpRequest[kOutbreakWrapped] = true;\n http[originalMethodName] = wrappedHttpRequest;\n}\n\nfunction injectInFetchRequest(tracer: Tracer, headers: Headers): void {\n const currentTraceContext = tracer.getCurrentTrace()?.context;\n /* c8 ignore next 3 */\n if (!currentTraceContext) {\n return;\n }\n // eslint-disable-next-line no-restricted-syntax\n for (const header of currentTraceContext.keys()) {\n headers.set(header, currentTraceContext.get(header));\n }\n}\n\nfunction wrapFetch(tracer: Tracer): void {\n if (globalThis.fetch[kOutbreakWrapped]) {\n return;\n }\n const originalFetch = globalThis.fetch;\n globalThis.fetch = (input: string | URL | Request, init?: RequestInit): Promise<Response> => {\n if (isFetchRequest(input) && input.headers && !init?.headers) {\n injectInFetchRequest(tracer, input.headers);\n } else {\n init ??= {};\n init.headers ??= new Headers();\n if (!isFetchHeaders(init.headers)) {\n init.headers = new Headers(init.headers);\n }\n injectInFetchRequest(tracer, init.headers);\n }\n return originalFetch(input, init);\n };\n globalThis.fetch[kOutbreakWrapped] = true;\n}\n\nexport default function wrapHttp(config: LoadedConfig, tracer: Tracer): void {\n wrapHttpCreateServer(config, tracer);\n wrapHttpRequest(tracer, 'request');\n wrapHttpRequest(tracer, 'get');\n wrapFetch(tracer);\n}\n","const correlationIdHeader = 'x-trace-id';\n\nconst validateHeaderList = (headers: string[]): void => {\n if (!Array.isArray(headers)) {\n throw new Error('Header list is not an array');\n }\n\n // could be tighter - ASCII code between 33 and 126 at the moment\n const headerNameRegex = /^[\\x21-\\x7e]+$/i;\n\n const invalidHeaders = headers.filter((h) => typeof h !== 'string' || !headerNameRegex.test(h));\n\n if (invalidHeaders.length > 0) {\n throw new Error(`Header list contains invalid headers: ${invalidHeaders}`);\n }\n};\n\nexport interface Overrides {\n setAndPropagateCorrelationId?: boolean;\n headersToPropagate?: string[];\n headersPrefix?: string;\n}\n\nexport interface LoadedConfig extends Required<Pick<Overrides, 'setAndPropagateCorrelationId' | 'headersPrefix'>> {\n correlationIdHeader: string;\n headersToCollect: Set<string>;\n}\n\nconst load = (overrides: Overrides = {}): LoadedConfig => {\n const {\n setAndPropagateCorrelationId = true,\n headersToPropagate = [\n 'x-request-id',\n 'x-variant-id',\n ],\n headersPrefix = 'x-af-',\n } = overrides;\n\n validateHeaderList(headersToPropagate);\n\n return {\n setAndPropagateCorrelationId,\n correlationIdHeader,\n headersToCollect: new Set(headersToPropagate),\n headersPrefix,\n };\n};\n\nexport default {\n load,\n correlationIdHeader,\n};\n","import asyncHooks from 'node:async_hooks';\nimport { randomUUID } from 'node:crypto';\nimport type { TraceType } from './const';\n\ninterface TraceHolder {\n currentTrace: Trace | null;\n traces: Record<number, Trace>;\n}\n\nexport class Trace {\n public readonly id = randomUUID();\n\n public readonly context = new Map<string, unknown>();\n\n constructor(public type: TraceType) {}\n}\n\nexport class Tracer {\n #isTraceEnabled = false;\n\n #prevStates = new Map<number, Trace>();\n\n #tracer: TraceHolder = {\n currentTrace: null,\n traces: {},\n };\n\n #hook = asyncHooks.createHook({\n init: (asyncId, _type, triggerAsyncId) => {\n if (!this.#tracer.traces[triggerAsyncId]) {\n return;\n }\n this.#tracer.traces[asyncId] = this.#tracer.traces[triggerAsyncId];\n },\n before: (asyncId) => {\n if (!this.#tracer.traces[asyncId]) {\n return;\n }\n this.#prevStates.set(asyncId, this.#tracer.currentTrace);\n this.#tracer.currentTrace = this.#tracer.traces[asyncId];\n },\n after: (asyncId) => {\n if (!this.#tracer.traces[asyncId]) {\n return;\n }\n this.#tracer.currentTrace = this.#prevStates.get(asyncId);\n },\n destroy: (asyncId) => {\n if (this.#tracer.traces[asyncId]) {\n delete this.#tracer.traces[asyncId];\n this.#prevStates.delete(asyncId);\n }\n },\n });\n\n public enable = (): asyncHooks.AsyncHook => {\n if (!this.#isTraceEnabled) {\n this.#hook.enable();\n this.#isTraceEnabled = true;\n }\n return this.#hook;\n };\n\n public newTrace = (type: TraceType): Trace => {\n if (!this.#isTraceEnabled) {\n this.enable();\n }\n const currentTrace = new Trace(type);\n this.#tracer.currentTrace = currentTrace;\n this.#tracer.traces[asyncHooks.executionAsyncId()] = currentTrace;\n return currentTrace;\n };\n\n public getCurrentTrace = (): Trace | Record<string, never> => this.#tracer.currentTrace || {};\n}\n","import { createRequire } from 'node:module';\nimport type winston from 'winston';\nimport httpWrapper from './http_wrapper';\nimport config, { type Overrides } from './config';\nimport { type Trace, Tracer } from './tracer';\n\nexport { traceTypes } from './const';\n\nconst safeRequire = createRequire(import.meta.url);\n\nconst tracer = new Tracer();\n\ninterface Options extends Overrides {\n winstonLogger?: winston.Logger;\n contextMiddlewareGetter?: (middleware: () => Record<string, unknown>) => void;\n loggerTraceKey? : string;\n}\n\nexport const getCurrentContextTraceId = (): string | undefined => tracer.getCurrentTrace().context?.get(config.correlationIdHeader) as string | undefined;\nconst contextMiddleware = (loggerTraceKey: string) => ({ [loggerTraceKey]: getCurrentContextTraceId() });\nconst addMetadataToLog = (loggerTraceKey: string, format: typeof winston.format) => format((info) => Object.assign(info, contextMiddleware(loggerTraceKey)));\n\nfunction lazilySetupWinstonLogger(winstonLogger: winston.Logger, traceKey: string): void {\n const { format } = safeRequire('winston');\n winstonLogger.format = format.combine(\n addMetadataToLog(traceKey, format)(),\n winstonLogger.format,\n );\n}\n\nexport default function outbreakInitialize(options: Options): void {\n httpWrapper(config.load(options), tracer);\n tracer.enable();\n\n const traceKey = options.loggerTraceKey || 'traceId';\n if (options.winstonLogger) {\n lazilySetupWinstonLogger(options.winstonLogger, traceKey);\n }\n options.contextMiddlewareGetter?.(() => contextMiddleware(traceKey));\n\n // Make an attempt to enable async hooks for bluebird, if available\n try {\n const bluebird = safeRequire('bluebird');\n bluebird.config({ asyncHooks: true });\n /* c8 ignore next */\n } catch (e) { /* ignore */ }\n}\n\nexport const getCurrentContext = (): Trace | Record<string, never> => tracer.getCurrentTrace();\n\nexport const { newTrace } = tracer;\n"]}
|
1
|
+
{"version":3,"sources":["../src/const.ts","../src/http_wrapper.ts","../src/config.ts","../src/tracer.ts","../src/index.ts"],"names":["traceTypes","kOutbreakWrapped","generateShortId","randomUUID","isFetchRequest","headers","isFetchHeaders","setAndCollectCorrelationId","config","tracer","req","res","correlationId","collect","headerName","value","wrappedListener","listener","next","error","wrapHttpCreateServer","http","originalHttpCreateServer","wrappedHttpCreateServer","options","inject","currentTraceContext","header","wrapHttpRequest","originalMethodName","originalMethod","urlFirst","url","cb","optionsFirst","wrappedHttpRequest","args","callback","injectInFetchRequest","wrapFetch","originalFetch","input","init","wrapHttp","correlationIdHeader","validateHeaderList","headerNameRegex","invalidHeaders","h","load","overrides","setAndPropagateCorrelationId","headersToPropagate","headersPrefix","config_default","Trace","type","Tracer","#isTraceEnabled","#prevStates","#tracer","#hook","asyncHooks","asyncId","_type","triggerAsyncId","currentTrace","safeRequire","createRequire","getCurrentContext","getCurrentContextTraceId","contextMiddleware","loggerTraceKey","addMetadataToLog","format","info","lazilySetupWinstonLogger","winstonLogger","traceKey","outbreakInitialize","newTrace"],"mappings":"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","file":"index.js","sourcesContent":["/** The supported trace types. Each type represents a different way that can trigger an action. */\nexport const traceTypes = {\n HTTP_REQUEST: 'httpRequest',\n WEB_SOCKET: 'webSocket',\n RABBIT: 'rabbit',\n BULL_MQ: 'bull',\n} as const;\nexport type TraceType = typeof traceTypes[keyof typeof traceTypes];\n","import http from 'node:http';\nimport { randomUUID } from 'node:crypto';\nimport type { URL } from 'node:url';\nimport { traceTypes } from './const';\nimport type { Tracer } from './tracer';\nimport type { LoadedConfig } from './config';\n\nexport const kOutbreakWrapped = Symbol('outbreak-wrapped');\nconst generateShortId = () => randomUUID().split('-')[0];\nconst isFetchRequest = (headers: unknown): headers is Request => headers instanceof Request || Object.prototype.toString.call(headers) === '[object Request]';\nconst isFetchHeaders = (headers: unknown): headers is Headers => headers instanceof Headers || Object.prototype.toString.call(headers) === '[object Headers]';\n\nfunction setAndCollectCorrelationId(config: LoadedConfig, tracer: Tracer, req: http.IncomingMessage, res: http.ServerResponse<http.IncomingMessage>): void {\n const correlationId = req.headers[config.correlationIdHeader] ?? generateShortId();\n tracer.getCurrentTrace().context.set(config.correlationIdHeader, correlationId as string);\n res.setHeader(config.correlationIdHeader, correlationId);\n}\n\nfunction collect(config: LoadedConfig, tracer: Tracer, req: http.IncomingMessage, res: http.ServerResponse<http.IncomingMessage>): void {\n if (config.setAndPropagateCorrelationId) {\n setAndCollectCorrelationId(config, tracer, req, res);\n }\n\n Object.entries(req.headers).forEach(([headerName, value]) => {\n const shouldCollect = config.headersToCollect.has(headerName) || headerName.startsWith(config.headersPrefix);\n if (shouldCollect && typeof value !== 'undefined') {\n tracer.getCurrentTrace().context.set(headerName, value);\n }\n });\n}\n\nfunction wrappedListener<\n Request extends typeof http.IncomingMessage = typeof http.IncomingMessage,\n Response extends typeof http.ServerResponse = typeof http.ServerResponse,\n>(\n config: LoadedConfig,\n tracer: Tracer,\n listener: http.RequestListener<Request, Response>,\n): http.RequestListener<Request, Response> {\n // @ts-expect-error we add next and error which don't exist on the original type\n return (req: http.IncomingMessage, res: http.ServerResponse, next: unknown, error: unknown): void => {\n tracer.newTrace(traceTypes.HTTP_REQUEST);\n\n collect(config, tracer, req, res);\n\n // @ts-expect-error we add next and error which don't exist on the original type\n listener(req, res, next, error);\n };\n}\n\nfunction wrapHttpCreateServer<\n Request extends typeof http.IncomingMessage = typeof http.IncomingMessage,\n Response extends typeof http.ServerResponse = typeof http.ServerResponse,\n>(config: LoadedConfig, tracer: Tracer): void {\n if (http.createServer[kOutbreakWrapped]) {\n return;\n }\n const originalHttpCreateServer = http.createServer;\n // args of http.createServer are ([options<Object>], [listener<Fn>]) Express only sends listener\n function wrappedHttpCreateServer(options: http.ServerOptions<Request, Response>, listener?: http.RequestListener<Request, Response>): http.Server<Request, Response>;\n function wrappedHttpCreateServer(listener?: http.RequestListener<Request, Response>): http.Server<Request, Response>;\n function wrappedHttpCreateServer(\n options: http.ServerOptions<Request, Response> | http.RequestListener<Request, Response>,\n listener?: http.RequestListener<Request, Response>,\n ): http.Server<Request, Response> {\n listener = listener || options as http.RequestListener<Request, Response>;\n return originalHttpCreateServer<Request, Response>(wrappedListener(config, tracer, listener));\n }\n wrappedHttpCreateServer[kOutbreakWrapped] = true;\n http.createServer = wrappedHttpCreateServer;\n}\n\nfunction inject(tracer: Tracer, options: http.RequestOptions): void {\n const currentTraceContext = tracer.getCurrentTrace().context;\n if (currentTraceContext) {\n options.headers ||= {};\n [...(currentTraceContext.keys())].forEach((header) => {\n const value = currentTraceContext.get(header);\n if (typeof value === 'symbol' || typeof value === 'undefined') {\n return;\n }\n options.headers[header] = value as string;\n });\n }\n}\nfunction wrapHttpRequest(tracer: Tracer, originalMethodName: 'request' | 'get'): void {\n if (http[originalMethodName][kOutbreakWrapped]) {\n return;\n }\n const originalMethod = http[originalMethodName];\n function urlFirst(url: string | URL, options: http.RequestOptions, cb: (res: http.IncomingMessage) => void): http.ClientRequest {\n inject(tracer, options);\n\n return originalMethod(url, options, cb);\n }\n\n function optionsFirst(options: http.RequestOptions, cb: (res: http.IncomingMessage) => void): http.ClientRequest {\n inject(tracer, options);\n\n return originalMethod(options, cb);\n }\n\n function wrappedHttpRequest(options: string | http.RequestOptions | URL, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;\n function wrappedHttpRequest(url: string | URL, options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;\n function wrappedHttpRequest(...args): http.ClientRequest {\n let options = {};\n let url: string | URL;\n let callback: (res: http.IncomingMessage) => void;\n\n if (args.length === 3) {\n [url, options, callback] = args;\n return urlFirst(url, options, callback);\n }\n [options, callback] = args;\n return optionsFirst(options, callback);\n }\n wrappedHttpRequest[kOutbreakWrapped] = true;\n http[originalMethodName] = wrappedHttpRequest;\n}\n\nfunction injectInFetchRequest(tracer: Tracer, headers: Headers): void {\n const currentTraceContext = tracer.getCurrentTrace()?.context;\n /* c8 ignore next 3 */\n if (!currentTraceContext) {\n return;\n }\n // eslint-disable-next-line no-restricted-syntax\n for (const header of currentTraceContext.keys()) {\n const value = currentTraceContext.get(header);\n if (typeof value === 'symbol' || typeof value === 'undefined') {\n // eslint-disable-next-line no-continue\n continue;\n }\n headers.set(header, value as string);\n }\n}\n\nfunction wrapFetch(tracer: Tracer): void {\n if (globalThis.fetch[kOutbreakWrapped]) {\n return;\n }\n const originalFetch = globalThis.fetch;\n globalThis.fetch = (input: string | URL | Request, init?: RequestInit): Promise<Response> => {\n if (isFetchRequest(input) && input.headers && !init?.headers) {\n injectInFetchRequest(tracer, input.headers);\n } else {\n init ??= {};\n init.headers ??= new Headers();\n if (!isFetchHeaders(init.headers)) {\n init.headers = new Headers(init.headers);\n }\n injectInFetchRequest(tracer, init.headers);\n }\n return originalFetch(input, init);\n };\n globalThis.fetch[kOutbreakWrapped] = true;\n}\n\nexport default function wrapHttp(config: LoadedConfig, tracer: Tracer): void {\n wrapHttpCreateServer(config, tracer);\n wrapHttpRequest(tracer, 'request');\n wrapHttpRequest(tracer, 'get');\n wrapFetch(tracer);\n}\n","const correlationIdHeader = 'x-trace-id';\n\nconst validateHeaderList = (headers: string[]): void => {\n if (!Array.isArray(headers)) {\n throw new Error('Header list is not an array');\n }\n\n // could be tighter - ASCII code between 33 and 126 at the moment\n // TODO: we can simply use the regex node uses? https://github.com/nodejs/node/blob/b07ff551db152ccb507e71160ce077e235206b16/lib/_http_common.js#L214\n const headerNameRegex = /^[\\x21-\\x7e]+$/i;\n\n const invalidHeaders = headers.filter((h) => typeof h !== 'string' || !headerNameRegex.test(h));\n\n if (invalidHeaders.length > 0) {\n throw new Error(`Header list contains invalid headers: ${invalidHeaders}`);\n }\n};\n\nexport interface Overrides {\n /**\n * Whether to set and propagate the correlation ID.\n * When set to `true`, each request will either use the correlation ID from the incoming request or generate a new one.\n * The correlation ID will be propagated to any outgoing HTTP requests, as well as to the response of the current request.\n * @default true\n */\n setAndPropagateCorrelationId?: boolean;\n /**\n * The list of exact headers to propagate from incoming requests to outgoing requests.\n * @default ['x-request-id', 'x-variant-id']\n */\n headersToPropagate?: string[];\n /** The prefix defining which headers will be collected from incoming requests and passed on to any outgoing request. @default 'x-af-' */\n headersPrefix?: string;\n}\n\nexport interface LoadedConfig extends Required<Pick<Overrides, 'setAndPropagateCorrelationId' | 'headersPrefix'>> {\n correlationIdHeader: string;\n headersToCollect: Set<string>;\n}\n\nconst load = (overrides: Overrides = {}): LoadedConfig => {\n const {\n setAndPropagateCorrelationId = true,\n headersToPropagate = [\n 'x-request-id',\n 'x-variant-id',\n ],\n headersPrefix = 'x-af-',\n } = overrides;\n\n validateHeaderList(headersToPropagate);\n\n return {\n setAndPropagateCorrelationId,\n correlationIdHeader,\n headersToCollect: new Set(headersToPropagate),\n headersPrefix,\n };\n};\n\nexport default {\n load,\n correlationIdHeader,\n};\n","import asyncHooks from 'node:async_hooks';\nimport { randomUUID } from 'node:crypto';\nimport type { TraceType } from './const';\n\ninterface TraceHolder {\n currentTrace: Trace | null;\n traces: Map<number, Trace>;\n}\n\nexport class Trace {\n /** The unique identifier of the trace. */\n public readonly id = randomUUID();\n\n /** The context of the trace. Any item set to this map will be injected into the HTTP headers of any outgoing HTTP request. */\n public readonly context = new Map<string, unknown>();\n\n /** The non-header context of the trace. This is not injected into the HTTP headers outgoing HTTP request. */\n public readonly nonHeaderContext = new Map<string, unknown>();\n\n constructor(\n /** The type of action which has started the action creating this trace. */\n public type: TraceType,\n ) {}\n}\n\nexport class Tracer {\n #isTraceEnabled = false;\n\n #prevStates = new Map<number, Trace>();\n\n #tracer: TraceHolder = {\n currentTrace: null,\n traces: new Map(),\n };\n\n #hook = asyncHooks.createHook({\n init: (asyncId, _type, triggerAsyncId) => {\n if (!this.#tracer.traces.has(triggerAsyncId)) {\n return;\n }\n this.#tracer.traces.set(asyncId, this.#tracer.traces.get(triggerAsyncId));\n },\n before: (asyncId) => {\n if (!this.#tracer.traces.has(asyncId)) {\n return;\n }\n this.#prevStates.set(asyncId, this.#tracer.currentTrace);\n this.#tracer.currentTrace = this.#tracer.traces.get(asyncId);\n },\n after: (asyncId) => {\n if (!this.#tracer.traces.has(asyncId)) {\n return;\n }\n this.#tracer.currentTrace = this.#prevStates.get(asyncId);\n },\n destroy: (asyncId) => {\n this.#tracer.traces.delete(asyncId);\n this.#prevStates.delete(asyncId);\n },\n });\n\n public enable = (): asyncHooks.AsyncHook => {\n if (!this.#isTraceEnabled) {\n this.#hook.enable();\n this.#isTraceEnabled = true;\n }\n return this.#hook;\n };\n\n public newTrace = (type: TraceType): Trace => {\n if (!this.#isTraceEnabled) {\n this.enable();\n }\n const currentTrace = new Trace(type);\n this.#tracer.currentTrace = currentTrace;\n this.#tracer.traces.set(asyncHooks.executionAsyncId(), currentTrace);\n return currentTrace;\n };\n\n public getCurrentTrace = (): Trace | Record<string, never> => this.#tracer.currentTrace || {};\n}\n","import { createRequire } from 'node:module';\nimport type winston from 'winston';\nimport httpWrapper from './http_wrapper';\nimport config, { type Overrides } from './config';\nimport { type Trace, Tracer } from './tracer';\n\nexport { traceTypes } from './const';\n\nconst safeRequire = createRequire(import.meta.url);\n\nconst tracer = new Tracer();\n\ninterface Options extends Overrides {\n /**\n * The winston logger used for logging.\n *\n * If provided, the logger's `format` will combine an additional format which injects the `traceId` into the log, using the {@link loggerTraceKey} as the trace's key.\n */\n winstonLogger?: winston.Logger;\n /**\n * A function which will be called with the middleware used to inject the trace ID into the logger.\n *\n * The trace ID will be injected using the {@link loggerTraceKey} as the trace's key.\n */\n contextMiddlewareGetter?: (middleware: () => Record<string, unknown>) => void;\n /** The key used to inject the trace ID into the logger. @default 'traceId' */\n loggerTraceKey? : string;\n}\n\n/** Get the current trace from the context. */\nexport const getCurrentContext = (): Trace | Record<string, never> => tracer.getCurrentTrace();\n/** Get the trace ID from the current context. */\nexport const getCurrentContextTraceId = (): string | undefined => getCurrentContext().context?.get(config.correlationIdHeader) as string | undefined;\nconst contextMiddleware = (loggerTraceKey: string) => ({ [loggerTraceKey]: getCurrentContextTraceId() });\nconst addMetadataToLog = (loggerTraceKey: string, format: typeof winston.format) => format((info) => Object.assign(info, contextMiddleware(loggerTraceKey)));\n\nfunction lazilySetupWinstonLogger(winstonLogger: winston.Logger, traceKey: string): void {\n const { format } = safeRequire('winston');\n winstonLogger.format = format.combine(\n addMetadataToLog(traceKey, format)(),\n winstonLogger.format,\n );\n}\n\nexport default function outbreakInitialize(options?: Options): void {\n httpWrapper(config.load(options), tracer);\n tracer.enable();\n\n const traceKey = options?.loggerTraceKey || 'traceId';\n if (options?.winstonLogger) {\n lazilySetupWinstonLogger(options.winstonLogger, traceKey);\n }\n options?.contextMiddlewareGetter?.(() => contextMiddleware(traceKey));\n\n // Make an attempt to enable async hooks for bluebird, if available\n try {\n const bluebird = safeRequire('bluebird');\n bluebird.config({ asyncHooks: true });\n /* c8 ignore next */\n } catch (e) { /* ignore */ }\n}\n\n/**\n * Create a new trace, representing a new action starting.\n * @param type The type of action which is starting the trace.\n */\nexport const { newTrace } = tracer;\n"]}
|