@promster/express
Version:
Express server integrations of promster
1 lines • 6.04 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","names":["createHttpMetrics","createGcMetrics","createRequestRecorder","createGcObserver","defaultNormalizers","Prometheus","timing"],"sources":["../src/middleware/middleware.ts"],"sourcesContent":["import type { TRequestRecorder } from '@promster/metrics';\nimport {\n createGcMetrics,\n createGcObserver,\n createHttpMetrics,\n createRequestRecorder,\n defaultNormalizers,\n Prometheus,\n skipMetricsInEnvironment,\n timing,\n} from '@promster/metrics';\nimport type {\n TDefaultedPromsterOptions,\n TGcMetrics,\n THttpMetrics,\n TLabelValues,\n TOptionalPromsterOptions,\n} from '@promster/types';\nimport type { Application, NextFunction, Request, Response } from 'express';\nimport merge from 'merge-options';\n\ninterface TApp extends Application {\n locals: Record<string, unknown>;\n}\n\ntype TLocaleTarget = {\n app?: TApp;\n key: string;\n value: typeof Prometheus | TRequestRecorder;\n};\nconst exposeOnLocals = ({ app, key, value }: TLocaleTarget) => {\n if (app?.locals) {\n app.locals[key] = value;\n }\n};\n\nconst extractPath = (req: Request) => req.originalUrl || req.url;\n\nlet recordRequest: TRequestRecorder;\nlet upMetric: TGcMetrics['up'];\n\nconst getRequestRecorder = () => recordRequest;\nconst signalIsUp = () => {\n if (!upMetric) {\n return;\n }\n\n for (const upMetricType of upMetric) {\n upMetricType.set(1);\n }\n};\n\nconst signalIsNotUp = () => {\n if (!upMetric) {\n return;\n }\n\n for (const upMetricType of upMetric) {\n upMetricType.set(0);\n }\n};\n\ntype TSkipFunction = <TRequest = Request, TResponse = Response>(\n _req: TRequest,\n _res: TResponse,\n _labels: TLabelValues,\n) => boolean;\nexport type TPromsterOptions = TOptionalPromsterOptions & {\n skip?: TSkipFunction;\n};\ntype TMiddlewareOptions = {\n app?: TApp;\n options?: TPromsterOptions;\n};\nconst createMiddleware = (\n { app, options }: TMiddlewareOptions = { app: undefined, options: undefined },\n) => {\n const allDefaultedOptions: TDefaultedPromsterOptions & {\n skip?: TSkipFunction;\n } = merge(\n createHttpMetrics.defaultOptions,\n createGcMetrics.defaultOptions,\n createRequestRecorder.defaultOptions,\n // @ts-expect-error\n createGcObserver.defaultOptions,\n defaultNormalizers,\n options,\n );\n\n const shouldSkipMetricsByEnvironment =\n skipMetricsInEnvironment(allDefaultedOptions);\n\n const httpMetrics: THttpMetrics = createHttpMetrics(allDefaultedOptions);\n const gcMetrics: TGcMetrics = createGcMetrics(allDefaultedOptions);\n const observeGc = createGcObserver(gcMetrics, allDefaultedOptions);\n\n recordRequest = createRequestRecorder(httpMetrics, allDefaultedOptions);\n upMetric = gcMetrics?.up;\n\n exposeOnLocals({ app, key: 'Prometheus', value: Prometheus });\n exposeOnLocals({ app, key: 'recordRequest', value: recordRequest });\n\n if (!shouldSkipMetricsByEnvironment) {\n observeGc();\n }\n\n signalIsUp();\n\n return (request: Request, response: Response, next: NextFunction) => {\n const requestTiming = timing.start();\n\n response.on('finish', () => {\n const labels = Object.assign(\n {},\n {\n method: allDefaultedOptions.normalizeMethod(request.method, {\n req: request,\n res: response,\n }),\n status_code: allDefaultedOptions.normalizeStatusCode(\n response.statusCode,\n { req: request, res: response },\n ),\n path: allDefaultedOptions.normalizePath(extractPath(request), {\n req: request,\n res: response,\n }),\n },\n allDefaultedOptions.getLabelValues?.(request, response),\n );\n\n const shouldSkipByRequest = allDefaultedOptions.skip?.(\n request,\n response,\n labels,\n );\n\n const requestContentLength = Number(\n request.headers['content-length'] ?? 0,\n );\n const responseContentLength = Number(\n response.getHeader('content-length') ?? 0,\n );\n\n if (!shouldSkipByRequest && !shouldSkipMetricsByEnvironment) {\n recordRequest(requestTiming, {\n labels,\n requestContentLength,\n responseContentLength,\n });\n }\n });\n\n next();\n };\n};\n\nexport {\n createMiddleware,\n exposeOnLocals,\n extractPath,\n getRequestRecorder,\n signalIsUp,\n signalIsNotUp,\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAM,kBAAkB,EAAE,KAAK,KAAK,YAA2B;CAC7D,IAAI,KAAK,QACP,IAAI,OAAO,OAAO;AAEtB;AAEA,MAAM,eAAe,QAAiB,IAAI,eAAe,IAAI;AAE7D,IAAI;AACJ,IAAI;AAEJ,MAAM,2BAA2B;AACjC,MAAM,mBAAmB;CACvB,IAAI,CAAC,UACH;CAGF,KAAK,MAAM,gBAAgB,UACzB,aAAa,IAAI,CAAC;AAEtB;AAEA,MAAM,sBAAsB;CAC1B,IAAI,CAAC,UACH;CAGF,KAAK,MAAM,gBAAgB,UACzB,aAAa,IAAI,CAAC;AAEtB;AAcA,MAAM,oBACJ,EAAE,KAAK,YAAgC;CAAE,KAAK,KAAA;CAAW,SAAS,KAAA;AAAU,MACzE;CACH,MAAM,uBAAA,GAAA,cAAA,QAAA,CAGJA,kBAAAA,kBAAkB,gBAClBC,kBAAAA,gBAAgB,gBAChBC,kBAAAA,sBAAsB,gBAEtBC,kBAAAA,iBAAiB,gBACjBC,kBAAAA,oBACA,OACF;CAEA,MAAM,kCAAA,GAAA,kBAAA,yBAAA,CACqB,mBAAmB;CAE9C,MAAM,eAAA,GAAA,kBAAA,kBAAA,CAA8C,mBAAmB;CACvE,MAAM,aAAA,GAAA,kBAAA,gBAAA,CAAwC,mBAAmB;CACjE,MAAM,aAAA,GAAA,kBAAA,iBAAA,CAA6B,WAAW,mBAAmB;CAEjE,iBAAA,GAAA,kBAAA,sBAAA,CAAsC,aAAa,mBAAmB;CACtE,WAAW,WAAW;CAEtB,eAAe;EAAE;EAAK,KAAK;EAAc,OAAOC,kBAAAA;CAAW,CAAC;CAC5D,eAAe;EAAE;EAAK,KAAK;EAAiB,OAAO;CAAc,CAAC;CAElE,IAAI,CAAC,gCACH,UAAU;CAGZ,WAAW;CAEX,QAAQ,SAAkB,UAAoB,SAAuB;EACnE,MAAM,gBAAgBC,kBAAAA,OAAO,MAAM;EAEnC,SAAS,GAAG,gBAAgB;GAC1B,MAAM,SAAS,OAAO,OACpB,CAAC,GACD;IACE,QAAQ,oBAAoB,gBAAgB,QAAQ,QAAQ;KAC1D,KAAK;KACL,KAAK;IACP,CAAC;IACD,aAAa,oBAAoB,oBAC/B,SAAS,YACT;KAAE,KAAK;KAAS,KAAK;IAAS,CAChC;IACA,MAAM,oBAAoB,cAAc,YAAY,OAAO,GAAG;KAC5D,KAAK;KACL,KAAK;IACP,CAAC;GACH,GACA,oBAAoB,iBAAiB,SAAS,QAAQ,CACxD;GAEA,MAAM,sBAAsB,oBAAoB,OAC9C,SACA,UACA,MACF;GAEA,MAAM,uBAAuB,OAC3B,QAAQ,QAAQ,qBAAqB,CACvC;GACA,MAAM,wBAAwB,OAC5B,SAAS,UAAU,gBAAgB,KAAK,CAC1C;GAEA,IAAI,CAAC,uBAAuB,CAAC,gCAC3B,cAAc,eAAe;IAC3B;IACA;IACA;GACF,CAAC;EAEL,CAAC;EAED,KAAK;CACP;AACF"}