@autofleet/logger 4.6.2 → 4.7.0-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 +12 -3
- package/dist/index.d.ts +12 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +11 -0
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,`__esModule`,{value:!0});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`pino`);c=s(c);let l=require(`node:module`),u=require(`node:async_hooks`);const d={trace:`DEBUG`,debug:`DEBUG`,info:`INFO`,warn:`WARNING`,error:`ERROR`,fatal:`CRITICAL`};function f(e,t={}){let{serviceName:n,version:r,tags:i}=t,a={...n&&r&&{serviceContext:{service:n,version:r}},...i};return{base:Object.keys(a).length?a:null,formatters:{level:e=>({severity:d[e]??d.info,...[`error`,`fatal`].includes(e)&&{"@type":`type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent`}}),log(e){let t=e,n=t.err?.stack??t.error?.stack??t.e?.stack;return{...e,...n&&{stack_trace:n}}}},messageKey:`message`,...e}}const p=(0,l.createRequire)(require(`url`).pathToFileURL(__filename).href),m=e=>{try{let t=p(e);return t?.dogstatsd?t:null}catch{return null}},h=m(`dd-trace`)??m(`/opt/datadog/apm/library/js/node_modules/dd-trace`),g=[`debug`,`trace`].includes(process.env.LOG_LEVEL||process.env.PINO_LOG_LEVEL||``),_=process.env.DD_SITE||`datadoghq.eu`,v=h?null:process.env.DD_API_KEY,y=h?`dd-trace`:v?`api`:`none`;process.stdout.write(`[logger] Datadog metrics mode initialized: ${y}\n`);const b=(e,t)=>{let n=process.env.DD_SERVICE||process.env.SERVICE_NAME||`unknown`,r=process.env.DD_ENV||process.env.ENV_NAME||`local`,i=Object.fromEntries(Object.entries(t).filter(([,e])=>typeof e==`string`||typeof e==`number`));if(h){h.dogstatsd.increment(e,1,{service:n,env:r,...i});return}if(!v)return;let a=[`service:${n}`,`env:${r}`,...Object.entries(i).map(([e,t])=>`${e}:${String(t)}`)];fetch(`https://api.${_}/api/v2/series`,{method:`POST`,headers:{"Content-Type":`application/json`,"DD-API-KEY":v},body:JSON.stringify({series:[{metric:e,type:1,points:[{timestamp:Math.floor(Date.now()/1e3),value:1}],tags:a}]})}).then(e=>{!e.ok&&g&&e.text().then(t=>{process.stderr.write(`[logger] DD API error ${e.status}: ${t}\n`)}).catch(()=>void 0)}).catch(e=>{g&&process.stderr.write(`[logger] DD API fetch failed: ${String(e)}\n`)})},x=new u.AsyncLocalStorage;function S(e){let t=x.getStore();if(t)for(let[n,r]of Object.entries(e))typeof r!=`string`&&typeof r!=`number`&&typeof r!=`boolean`||(t[n]=r)}function C(e){return x.run({},e)}function w(e,t,n){x.run({},n)}function T(){return x.getStore()??{}}let E=function(e){return e.trace=`trace`,e.debug=`debug`,e.info=`info`,e.warn=`warn`,e.error=`error`,e.fatal=`fatal`,e}({});const D=e=>e||(process.env.LOG_LEVEL?process.env.LOG_LEVEL:process.env.NODE_ENV&&[`production`,`staging`,`test`].includes(process.env.NODE_ENV)?E.info:(process.env.NODE_ENV,E.debug)),O=(e,t,n)=>{let
|
|
1
|
+
Object.defineProperty(exports,`__esModule`,{value:!0});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`pino`);c=s(c);let l=require(`node:module`),u=require(`node:async_hooks`);const d={trace:`DEBUG`,debug:`DEBUG`,info:`INFO`,warn:`WARNING`,error:`ERROR`,fatal:`CRITICAL`};function f(e,t={}){let{serviceName:n,version:r,tags:i}=t,a={...n&&r&&{serviceContext:{service:n,version:r}},...i};return{base:Object.keys(a).length?a:null,formatters:{level:e=>({severity:d[e]??d.info,...[`error`,`fatal`].includes(e)&&{"@type":`type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent`}}),log(e){let t=e,n=t.err?.stack??t.error?.stack??t.e?.stack;return{...e,...n&&{stack_trace:n}}}},messageKey:`message`,...e}}const p=(0,l.createRequire)(require(`url`).pathToFileURL(__filename).href),m=e=>{try{let t=p(e);return t?.dogstatsd?t:null}catch{return null}},h=m(`dd-trace`)??m(`/opt/datadog/apm/library/js/node_modules/dd-trace`),g=[`debug`,`trace`].includes(process.env.LOG_LEVEL||process.env.PINO_LOG_LEVEL||``),_=process.env.DD_SITE||`datadoghq.eu`,v=h?null:process.env.DD_API_KEY,y=h?`dd-trace`:v?`api`:`none`;process.stdout.write(`[logger] Datadog metrics mode initialized: ${y}\n`);const b=(e,t)=>{let n=process.env.DD_SERVICE||process.env.SERVICE_NAME||`unknown`,r=process.env.DD_ENV||process.env.ENV_NAME||`local`,i=Object.fromEntries(Object.entries(t).filter(([,e])=>typeof e==`string`||typeof e==`number`));if(h){h.dogstatsd.increment(e,1,{service:n,env:r,...i});return}if(!v)return;let a=[`service:${n}`,`env:${r}`,...Object.entries(i).map(([e,t])=>`${e}:${String(t)}`)];fetch(`https://api.${_}/api/v2/series`,{method:`POST`,headers:{"Content-Type":`application/json`,"DD-API-KEY":v},body:JSON.stringify({series:[{metric:e,type:1,points:[{timestamp:Math.floor(Date.now()/1e3),value:1}],tags:a}]})}).then(e=>{!e.ok&&g&&e.text().then(t=>{process.stderr.write(`[logger] DD API error ${e.status}: ${t}\n`)}).catch(()=>void 0)}).catch(e=>{g&&process.stderr.write(`[logger] DD API fetch failed: ${String(e)}\n`)})},x=new u.AsyncLocalStorage;function S(e){let t=x.getStore();if(t)for(let[n,r]of Object.entries(e))typeof r!=`string`&&typeof r!=`number`&&typeof r!=`boolean`||(t[n]=r)}function C(e){return x.run({},e)}function w(e,t,n){x.run({},n)}function T(){return x.getStore()??{}}let E=function(e){return e.trace=`trace`,e.debug=`debug`,e.info=`info`,e.warn=`warn`,e.error=`error`,e.fatal=`fatal`,e}({});const D=e=>e||(process.env.LOG_LEVEL?process.env.LOG_LEVEL:process.env.NODE_ENV&&[`production`,`staging`,`test`].includes(process.env.NODE_ENV)?E.info:(process.env.NODE_ENV,E.debug)),O=(e,t,n,r)=>{let i;return i=process.env.NODE_ENV===`production`||r?.disablePrettier?(0,c.default)(f({level:process.env.PINO_LOG_LEVEL||`info`,...t},n)):(0,c.default)({level:process.env.PINO_LOG_LEVEL||`info`,transport:{target:`pino-pretty`,options:{colorize:!0}},...t}),i.level=e,i};var k=class e{#e=[T];#t;constructor(t,n,r){this.addContextMiddleware=e=>this.#e.push(e),this.addToContext=e=>S(e),this.trace=(e,t)=>this.winstonLikeLoggerCall(E.trace,e,t),this.traceLazy=e=>this.lazyLoggerCall(E.trace,e),this.debug=(e,t)=>this.winstonLikeLoggerCall(E.debug,e,t),this.debugLazy=e=>this.lazyLoggerCall(E.debug,e),this.info=(e,t)=>this.winstonLikeLoggerCall(E.info,e,t),this.infoLazy=e=>this.lazyLoggerCall(E.info,e),this.warn=(e,t)=>this.winstonLikeLoggerCall(E.warn,e,t),this.warnLazy=e=>this.lazyLoggerCall(E.warn,e),this.error=(e,t)=>this.winstonLikeLoggerCall(E.error,e,t),this.errorLazy=e=>this.lazyLoggerCall(E.error,e),this.fatal=(e,t)=>this.winstonLikeLoggerCall(E.fatal,e,t),this.fatalLazy=e=>this.lazyLoggerCall(E.fatal,e),this.silent=(e,t)=>{},this.trackEvent=(e,t={})=>{b(e,t)},this.child=(...t)=>{let n=new e;if(n.#e=[...this.#e],typeof t[0]==`string`){let[e,r]=t;n.#t=this.#t.child(r,{msgPrefix:`[${e}] `})}else if(typeof t[0]==`object`)n.#t=this.#t.child(t[0]);else throw Error(`Invalid arguments to child logger`);return n},this.#t=O(D(t),{mixin:()=>this.addMetadata(),serializers:{...c.stdSerializers,e:c.stdSerializers.errWithCause,err:c.stdSerializers.errWithCause,error:c.stdSerializers.errWithCause,errors(e){return Array.isArray(e)?e.map(c.stdSerializers.errWithCause):c.stdSerializers.errWithCause(e)}}},n,r)}winstonLikeLoggerCall(e,t,n){t&&typeof t==`object`&&typeof n==`string`?this.#t[e](t,n):n?this.#t[e](n,t):this.#t[e](t)}lazyLoggerCall(e,t){if(!this.#t.isLevelEnabled(e))return;let[n,r]=t();this.winstonLikeLoggerCall(e,n,r)}addMetadata(){let e={};return this.#e.forEach(t=>{let n=t();Object.assign(e,n)}),e}get level(){return this.#t.level}},A=(e,t,n)=>new k(e,t,n);exports.LogLevel=E,exports.LoggerInstanceManager=k,exports.addToContext=S,exports.default=A,exports.loggerContextMiddleware=w,exports.runWithLoggerContext=C;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["levelToSeverity: Record<LevelOrString, string>","ddMode: DDMode","AsyncLocalStorage","#contextMiddlewares","context","#logger","stdSerializers","newMetadata: Record<string, unknown>"],"sources":["../src/gcpLogOptions.ts","../src/datadogClient.ts","../src/context.ts","../src/index.ts"],"sourcesContent":["// Based on https://github.com/simenandre/pino-cloud-logging/blob/7816b2e4dec3dd18ef34c0f3f241d88a4cab0b90/src/main.ts\n// The repo is licensed under the Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0\n// Extracted since the repo no longer receives updates\n\nimport type { LevelOrString, LoggerOptions } from 'pino';\n\n// Map Pino levels to Google Cloud Logging severity levels\n// https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity\nconst levelToSeverity: Record<LevelOrString, string> = {\n trace: 'DEBUG',\n debug: 'DEBUG',\n info: 'INFO',\n warn: 'WARNING',\n error: 'ERROR',\n fatal: 'CRITICAL',\n};\n\nexport interface ServiceContext {\n serviceName?: string;\n version?: string;\n tags?: Record<string, string>;\n}\n\nexport function gcpLogOptions(\n options?: LoggerOptions,\n context: ServiceContext = {},\n): LoggerOptions {\n const { serviceName, version, tags } = context;\n\n const baseObj = {\n ...(serviceName && version && { serviceContext: { service: serviceName, version } }),\n ...tags,\n };\n const base = Object.keys(baseObj).length ? baseObj : null;\n\n return {\n // https://cloud.google.com/error-reporting/docs/formatting-error-messages#json_representation\n base,\n formatters: {\n level: (label: string) => ({\n severity: levelToSeverity[label] ?? levelToSeverity.info,\n // `@type` property tells Error Reporting to track even if there is no `stack_trace`\n ...(['error', 'fatal'].includes(label) && { '@type': 'type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent' }),\n }),\n\n log(object) {\n const logObject = object as { err?: Error; error?: Error; e?: Error; };\n const stackTrace = logObject.err?.stack ?? logObject.error?.stack ?? logObject.e?.stack;\n // eslint-disable-next-line camelcase\n return { ...object, ...(stackTrace && { stack_trace: stackTrace }) };\n },\n },\n messageKey: 'message',\n ...options,\n };\n}\n","import { createRequire } from 'node:module';\n\nconst _require = createRequire(import.meta.url);\n\ninterface DDTracer {\n dogstatsd: {\n increment: (metric: string, value: number, tags?: Record<string, string | number>) => void;\n };\n}\n\nconst tryRequire = (path: string): DDTracer | null => {\n try {\n const t = _require(path) as DDTracer;\n return t?.dogstatsd ? t : null;\n } catch {\n return null;\n }\n};\n\nconst tracer = tryRequire('dd-trace') ?? tryRequire('/opt/datadog/apm/library/js/node_modules/dd-trace');\nconst isDebugLevel = ['debug', 'trace'].includes(process.env.LOG_LEVEL || process.env.PINO_LOG_LEVEL || '');\n\nconst ddSite = process.env.DD_SITE || 'datadoghq.eu';\nconst ddApiKey = !tracer ? process.env.DD_API_KEY : null;\n\nexport type DDMode = 'dd-trace' | 'api' | 'none';\nexport const ddMode: DDMode = tracer ? 'dd-trace' : ddApiKey ? 'api' : 'none';\nprocess.stdout.write(`[logger] Datadog metrics mode initialized: ${ddMode}\\n`);\n\nexport const sendDDEvent = (eventName: string, data: Record<string, unknown>): void => {\n const service = process.env.DD_SERVICE || process.env.SERVICE_NAME || 'unknown';\n const env = process.env.DD_ENV || process.env.ENV_NAME || 'local';\n\n const primitiveData = Object.fromEntries(\n Object.entries(data).filter(([, v]) => typeof v === 'string' || typeof v === 'number'),\n ) as Record<string, string | number>;\n\n if (tracer) {\n tracer.dogstatsd.increment(eventName, 1, { service, env, ...primitiveData });\n return;\n }\n\n if (!ddApiKey) return;\n\n const tags = [\n `service:${service}`,\n `env:${env}`,\n ...Object.entries(primitiveData).map(([k, v]) => `${k}:${String(v)}`),\n ];\n\n fetch(`https://api.${ddSite}/api/v2/series`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'DD-API-KEY': ddApiKey },\n body: JSON.stringify({\n series: [{\n metric: eventName,\n type: 1,\n points: [{ timestamp: Math.floor(Date.now() / 1000), value: 1 }],\n tags,\n }],\n }),\n }).then((res) => {\n if (!res.ok && isDebugLevel) {\n res.text().then((body) => {\n process.stderr.write(`[logger] DD API error ${res.status}: ${body}\\n`);\n }).catch(() => undefined);\n }\n }).catch((err) => {\n if (isDebugLevel) {\n process.stderr.write(`[logger] DD API fetch failed: ${String(err)}\\n`);\n }\n });\n};\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\ntype LogContext = Record<string, string | number | boolean>;\n\nconst storage = new AsyncLocalStorage<LogContext>();\n\nexport function addToContext(context: Record<string, string | number | boolean>): void {\n const store = storage.getStore();\n if (!store) return;\n for (const [key, value] of Object.entries(context)) {\n if (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean') continue;\n store[key] = value;\n }\n}\n\nexport function runWithLoggerContext<T>(fn: () => T): T {\n return storage.run({}, fn);\n}\n\nexport function loggerContextMiddleware(_req: unknown, _res: unknown, next: () => void): void {\n storage.run({}, next);\n}\n\nexport function getContext(): LogContext {\n return storage.getStore() ?? {};\n}\n","import Pino, { type LoggerOptions, stdSerializers } from 'pino';\nimport { gcpLogOptions, type ServiceContext } from './gcpLogOptions';\nimport { sendDDEvent } from './datadogClient';\nimport { getContext, addToContext, runWithLoggerContext, loggerContextMiddleware } from './context';\n\nexport { type ServiceContext };\nexport { addToContext, runWithLoggerContext, loggerContextMiddleware };\n\nexport enum LogLevel {\n trace = 'trace',\n debug = 'debug',\n info = 'info',\n warn = 'warn',\n error = 'error',\n fatal = 'fatal',\n}\ntype LazyLogFn = () => [string] | [string, unknown];\n\nconst getLevel = (logLevel?: LogLevel): LogLevel => {\n if (logLevel) return logLevel;\n if (process.env.LOG_LEVEL) return process.env.LOG_LEVEL as LogLevel;\n if (process.env.NODE_ENV && ['production', 'staging', 'test'].includes(process.env.NODE_ENV)) return LogLevel.info;\n if (process.env.NODE_ENV === 'development') return LogLevel.debug;\n return LogLevel.debug;\n};\n\nconst createLoggerInstance = (level: LogLevel, options: Omit<LoggerOptions, 'transport'>, context?: ServiceContext): Pino.Logger => {\n let loggerInstance;\n if (process.env.NODE_ENV === 'production') {\n loggerInstance = Pino(gcpLogOptions({\n level: process.env.PINO_LOG_LEVEL || 'info',\n ...options,\n } as object, context));\n } else {\n loggerInstance = Pino({\n level: process.env.PINO_LOG_LEVEL || 'info',\n transport: {\n target: 'pino-pretty',\n options: {\n colorize: true,\n },\n },\n ...options,\n });\n }\n loggerInstance.level = level;\n return loggerInstance;\n};\n\ntype MiddlewareFunction = () => Record<string, unknown>;\n\nexport class LoggerInstanceManager {\n #contextMiddlewares: MiddlewareFunction[] = [getContext];\n\n #logger: Pino.Logger;\n\n constructor(logLevel?: LogLevel, context?: ServiceContext) {\n this.#logger = createLoggerInstance(getLevel(logLevel), {\n mixin: () => this.addMetadata(),\n serializers: {\n ...stdSerializers,\n e: stdSerializers.errWithCause,\n err: stdSerializers.errWithCause,\n error: stdSerializers.errWithCause,\n errors(val) {\n if (Array.isArray(val)) {\n return val.map(stdSerializers.errWithCause);\n }\n return stdSerializers.errWithCause(val);\n },\n },\n }, context);\n }\n\n // To support winston like logging in pino\n private winstonLikeLoggerCall(logLevel: LogLevel, message: string, meta: unknown): void {\n if (message && typeof message === 'object' && typeof meta === 'string') {\n // Fastify sends the message as the second parameter when logging (which is how pino actually works),\n this.#logger[logLevel](message as object, meta);\n } else if (meta) {\n this.#logger[logLevel](meta, message);\n } else {\n this.#logger[logLevel](message);\n }\n }\n\n private lazyLoggerCall(logLevel: LogLevel, fn: LazyLogFn): void {\n if (!this.#logger.isLevelEnabled(logLevel)) {\n return;\n }\n const [message, meta] = fn();\n this.winstonLikeLoggerCall(logLevel, message, meta);\n }\n\n private addMetadata(): Record<string, unknown> {\n const newMetadata: Record<string, unknown> = {};\n this.#contextMiddlewares.forEach((middleware) => {\n const metadata = middleware();\n Object.assign(newMetadata, metadata);\n });\n return newMetadata;\n }\n\n addContextMiddleware = (middleware: MiddlewareFunction): number => this.#contextMiddlewares.push(middleware);\n\n addToContext = (context: Record<string, string | number | boolean>): void => addToContext(context);\n\n trace = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.trace, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the trace level is enabled */\n traceLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.trace, fn);\n\n debug = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.debug, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the debug level is enabled */\n debugLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.debug, fn);\n\n info = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.info, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the info level is enabled */\n infoLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.info, fn);\n\n warn = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.warn, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the warn level is enabled */\n warnLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.warn, fn);\n\n error = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.error, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the error level is enabled */\n errorLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.error, fn);\n\n fatal = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.fatal, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the fatal level is enabled */\n fatalLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.fatal, fn);\n\n /** No-op logging method for silent level (required for Fastify compatibility) */\n silent = (_message: string, _meta?: unknown): void => {\n // no-op\n };\n\n trackEvent = (eventName: string, data: Record<string, unknown> = {}): void => {\n sendDDEvent(eventName, data);\n };\n\n child: OverloadedChildLoggerMethod = (...args: [metadata: Record<string, unknown>] | [instanceNamePrefix: string, metadata: Record<string, unknown>]) => {\n const childLoggerInstanceManager = new LoggerInstanceManager();\n childLoggerInstanceManager.#contextMiddlewares = [...this.#contextMiddlewares];\n\n if (typeof args[0] === 'string') {\n // Overload: child(instanceNamePrefix: string, metadata: Record<string, unknown>)\n const [instanceNamePrefix, metadata] = args;\n childLoggerInstanceManager.#logger = this.#logger.child(metadata!, { msgPrefix: `[${instanceNamePrefix}] ` });\n } else if (typeof args[0] === 'object') {\n // Overload: child(metadata: Record<string, unknown>)\n childLoggerInstanceManager.#logger = this.#logger.child(args[0]);\n } else {\n throw new Error('Invalid arguments to child logger');\n }\n return childLoggerInstanceManager;\n };\n\n get level(): Pino.LevelWithSilentOrString {\n return this.#logger.level;\n }\n}\n\ninterface OverloadedChildLoggerMethod {\n (metadata: Record<string, unknown>): LoggerInstanceManager;\n (instanceNamePrefix: string, metadata: Record<string, unknown>): LoggerInstanceManager;\n}\n\nexport default (loglevel?: `${LogLevel}`, context?: ServiceContext): LoggerInstanceManager => new LoggerInstanceManager(loglevel as LogLevel, context);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["levelToSeverity: Record<LevelOrString, string>","ddMode: DDMode","AsyncLocalStorage","#contextMiddlewares","context","#logger","stdSerializers","newMetadata: Record<string, unknown>"],"sources":["../src/gcpLogOptions.ts","../src/datadogClient.ts","../src/context.ts","../src/index.ts"],"sourcesContent":["// Based on https://github.com/simenandre/pino-cloud-logging/blob/7816b2e4dec3dd18ef34c0f3f241d88a4cab0b90/src/main.ts\n// The repo is licensed under the Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0\n// Extracted since the repo no longer receives updates\n\nimport type { LevelOrString, LoggerOptions } from 'pino';\n\n// Map Pino levels to Google Cloud Logging severity levels\n// https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity\nconst levelToSeverity: Record<LevelOrString, string> = {\n trace: 'DEBUG',\n debug: 'DEBUG',\n info: 'INFO',\n warn: 'WARNING',\n error: 'ERROR',\n fatal: 'CRITICAL',\n};\n\nexport interface ServiceContext {\n serviceName?: string;\n version?: string;\n tags?: Record<string, string>;\n}\n\nexport function gcpLogOptions(\n options?: LoggerOptions,\n context: ServiceContext = {},\n): LoggerOptions {\n const { serviceName, version, tags } = context;\n\n const baseObj = {\n ...(serviceName && version && { serviceContext: { service: serviceName, version } }),\n ...tags,\n };\n const base = Object.keys(baseObj).length ? baseObj : null;\n\n return {\n // https://cloud.google.com/error-reporting/docs/formatting-error-messages#json_representation\n base,\n formatters: {\n level: (label: string) => ({\n severity: levelToSeverity[label] ?? levelToSeverity.info,\n // `@type` property tells Error Reporting to track even if there is no `stack_trace`\n ...(['error', 'fatal'].includes(label) && { '@type': 'type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent' }),\n }),\n\n log(object) {\n const logObject = object as { err?: Error; error?: Error; e?: Error; };\n const stackTrace = logObject.err?.stack ?? logObject.error?.stack ?? logObject.e?.stack;\n // eslint-disable-next-line camelcase\n return { ...object, ...(stackTrace && { stack_trace: stackTrace }) };\n },\n },\n messageKey: 'message',\n ...options,\n };\n}\n","import { createRequire } from 'node:module';\n\nconst _require = createRequire(import.meta.url);\n\ninterface DDTracer {\n dogstatsd: {\n increment: (metric: string, value: number, tags?: Record<string, string | number>) => void;\n };\n}\n\nconst tryRequire = (path: string): DDTracer | null => {\n try {\n const t = _require(path) as DDTracer;\n return t?.dogstatsd ? t : null;\n } catch {\n return null;\n }\n};\n\nconst tracer = tryRequire('dd-trace') ?? tryRequire('/opt/datadog/apm/library/js/node_modules/dd-trace');\nconst isDebugLevel = ['debug', 'trace'].includes(process.env.LOG_LEVEL || process.env.PINO_LOG_LEVEL || '');\n\nconst ddSite = process.env.DD_SITE || 'datadoghq.eu';\nconst ddApiKey = !tracer ? process.env.DD_API_KEY : null;\n\nexport type DDMode = 'dd-trace' | 'api' | 'none';\nexport const ddMode: DDMode = tracer ? 'dd-trace' : ddApiKey ? 'api' : 'none';\nprocess.stdout.write(`[logger] Datadog metrics mode initialized: ${ddMode}\\n`);\n\nexport const sendDDEvent = (eventName: string, data: Record<string, unknown>): void => {\n const service = process.env.DD_SERVICE || process.env.SERVICE_NAME || 'unknown';\n const env = process.env.DD_ENV || process.env.ENV_NAME || 'local';\n\n const primitiveData = Object.fromEntries(\n Object.entries(data).filter(([, v]) => typeof v === 'string' || typeof v === 'number'),\n ) as Record<string, string | number>;\n\n if (tracer) {\n tracer.dogstatsd.increment(eventName, 1, { service, env, ...primitiveData });\n return;\n }\n\n if (!ddApiKey) return;\n\n const tags = [\n `service:${service}`,\n `env:${env}`,\n ...Object.entries(primitiveData).map(([k, v]) => `${k}:${String(v)}`),\n ];\n\n fetch(`https://api.${ddSite}/api/v2/series`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'DD-API-KEY': ddApiKey },\n body: JSON.stringify({\n series: [{\n metric: eventName,\n type: 1,\n points: [{ timestamp: Math.floor(Date.now() / 1000), value: 1 }],\n tags,\n }],\n }),\n }).then((res) => {\n if (!res.ok && isDebugLevel) {\n res.text().then((body) => {\n process.stderr.write(`[logger] DD API error ${res.status}: ${body}\\n`);\n }).catch(() => undefined);\n }\n }).catch((err) => {\n if (isDebugLevel) {\n process.stderr.write(`[logger] DD API fetch failed: ${String(err)}\\n`);\n }\n });\n};\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\ntype LogContext = Record<string, string | number | boolean>;\n\nconst storage = new AsyncLocalStorage<LogContext>();\n\nexport function addToContext(context: Record<string, string | number | boolean>): void {\n const store = storage.getStore();\n if (!store) return;\n for (const [key, value] of Object.entries(context)) {\n if (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean') continue;\n store[key] = value;\n }\n}\n\nexport function runWithLoggerContext<T>(fn: () => T): T {\n return storage.run({}, fn);\n}\n\nexport function loggerContextMiddleware(_req: unknown, _res: unknown, next: () => void): void {\n storage.run({}, next);\n}\n\nexport function getContext(): LogContext {\n return storage.getStore() ?? {};\n}\n","import Pino, { type LoggerOptions, stdSerializers } from 'pino';\nimport { gcpLogOptions, type ServiceContext } from './gcpLogOptions';\nimport { sendDDEvent } from './datadogClient';\nimport { getContext, addToContext, runWithLoggerContext, loggerContextMiddleware } from './context';\n\nexport { type ServiceContext };\nexport { addToContext, runWithLoggerContext, loggerContextMiddleware };\n\nexport enum LogLevel {\n trace = 'trace',\n debug = 'debug',\n info = 'info',\n warn = 'warn',\n error = 'error',\n fatal = 'fatal',\n}\ntype LazyLogFn = () => [string] | [string, unknown];\n\nexport interface LoggerConfig {\n /**\n * Opt out of the `pino-pretty` transport and always emit structured\n * single-line JSON, regardless of `NODE_ENV`. Useful for non-production\n * deployments (e.g. staging on GCP) where pino-pretty's multi-line output is\n * split into a separate log entry per row.\n */\n disablePrettier?: boolean;\n}\n\nconst getLevel = (logLevel?: LogLevel): LogLevel => {\n if (logLevel) return logLevel;\n if (process.env.LOG_LEVEL) return process.env.LOG_LEVEL as LogLevel;\n if (process.env.NODE_ENV && ['production', 'staging', 'test'].includes(process.env.NODE_ENV)) return LogLevel.info;\n if (process.env.NODE_ENV === 'development') return LogLevel.debug;\n return LogLevel.debug;\n};\n\nconst createLoggerInstance = (level: LogLevel, options: Omit<LoggerOptions, 'transport'>, context?: ServiceContext, config?: LoggerConfig): Pino.Logger => {\n let loggerInstance;\n if (process.env.NODE_ENV === 'production' || config?.disablePrettier) {\n loggerInstance = Pino(gcpLogOptions({\n level: process.env.PINO_LOG_LEVEL || 'info',\n ...options,\n } as object, context));\n } else {\n loggerInstance = Pino({\n level: process.env.PINO_LOG_LEVEL || 'info',\n transport: {\n target: 'pino-pretty',\n options: {\n colorize: true,\n },\n },\n ...options,\n });\n }\n loggerInstance.level = level;\n return loggerInstance;\n};\n\ntype MiddlewareFunction = () => Record<string, unknown>;\n\nexport class LoggerInstanceManager {\n #contextMiddlewares: MiddlewareFunction[] = [getContext];\n\n #logger: Pino.Logger;\n\n constructor(logLevel?: LogLevel, context?: ServiceContext, config?: LoggerConfig) {\n this.#logger = createLoggerInstance(getLevel(logLevel), {\n mixin: () => this.addMetadata(),\n serializers: {\n ...stdSerializers,\n e: stdSerializers.errWithCause,\n err: stdSerializers.errWithCause,\n error: stdSerializers.errWithCause,\n errors(val) {\n if (Array.isArray(val)) {\n return val.map(stdSerializers.errWithCause);\n }\n return stdSerializers.errWithCause(val);\n },\n },\n }, context, config);\n }\n\n // To support winston like logging in pino\n private winstonLikeLoggerCall(logLevel: LogLevel, message: string, meta: unknown): void {\n if (message && typeof message === 'object' && typeof meta === 'string') {\n // Fastify sends the message as the second parameter when logging (which is how pino actually works),\n this.#logger[logLevel](message as object, meta);\n } else if (meta) {\n this.#logger[logLevel](meta, message);\n } else {\n this.#logger[logLevel](message);\n }\n }\n\n private lazyLoggerCall(logLevel: LogLevel, fn: LazyLogFn): void {\n if (!this.#logger.isLevelEnabled(logLevel)) {\n return;\n }\n const [message, meta] = fn();\n this.winstonLikeLoggerCall(logLevel, message, meta);\n }\n\n private addMetadata(): Record<string, unknown> {\n const newMetadata: Record<string, unknown> = {};\n this.#contextMiddlewares.forEach((middleware) => {\n const metadata = middleware();\n Object.assign(newMetadata, metadata);\n });\n return newMetadata;\n }\n\n addContextMiddleware = (middleware: MiddlewareFunction): number => this.#contextMiddlewares.push(middleware);\n\n addToContext = (context: Record<string, string | number | boolean>): void => addToContext(context);\n\n trace = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.trace, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the trace level is enabled */\n traceLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.trace, fn);\n\n debug = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.debug, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the debug level is enabled */\n debugLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.debug, fn);\n\n info = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.info, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the info level is enabled */\n infoLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.info, fn);\n\n warn = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.warn, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the warn level is enabled */\n warnLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.warn, fn);\n\n error = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.error, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the error level is enabled */\n errorLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.error, fn);\n\n fatal = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.fatal, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the fatal level is enabled */\n fatalLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.fatal, fn);\n\n /** No-op logging method for silent level (required for Fastify compatibility) */\n silent = (_message: string, _meta?: unknown): void => {\n // no-op\n };\n\n trackEvent = (eventName: string, data: Record<string, unknown> = {}): void => {\n sendDDEvent(eventName, data);\n };\n\n child: OverloadedChildLoggerMethod = (...args: [metadata: Record<string, unknown>] | [instanceNamePrefix: string, metadata: Record<string, unknown>]) => {\n const childLoggerInstanceManager = new LoggerInstanceManager();\n childLoggerInstanceManager.#contextMiddlewares = [...this.#contextMiddlewares];\n\n if (typeof args[0] === 'string') {\n // Overload: child(instanceNamePrefix: string, metadata: Record<string, unknown>)\n const [instanceNamePrefix, metadata] = args;\n childLoggerInstanceManager.#logger = this.#logger.child(metadata!, { msgPrefix: `[${instanceNamePrefix}] ` });\n } else if (typeof args[0] === 'object') {\n // Overload: child(metadata: Record<string, unknown>)\n childLoggerInstanceManager.#logger = this.#logger.child(args[0]);\n } else {\n throw new Error('Invalid arguments to child logger');\n }\n return childLoggerInstanceManager;\n };\n\n get level(): Pino.LevelWithSilentOrString {\n return this.#logger.level;\n }\n}\n\ninterface OverloadedChildLoggerMethod {\n (metadata: Record<string, unknown>): LoggerInstanceManager;\n (instanceNamePrefix: string, metadata: Record<string, unknown>): LoggerInstanceManager;\n}\n\nexport default (loglevel?: `${LogLevel}`, context?: ServiceContext, config?: LoggerConfig): LoggerInstanceManager => new LoggerInstanceManager(loglevel as LogLevel, context, config);\n"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -22,10 +22,19 @@ declare enum LogLevel {
|
|
|
22
22
|
fatal = "fatal",
|
|
23
23
|
}
|
|
24
24
|
type LazyLogFn = () => [string] | [string, unknown];
|
|
25
|
+
interface LoggerConfig {
|
|
26
|
+
/**
|
|
27
|
+
* Opt out of the `pino-pretty` transport and always emit structured
|
|
28
|
+
* single-line JSON, regardless of `NODE_ENV`. Useful for non-production
|
|
29
|
+
* deployments (e.g. staging on GCP) where pino-pretty's multi-line output is
|
|
30
|
+
* split into a separate log entry per row.
|
|
31
|
+
*/
|
|
32
|
+
disablePrettier?: boolean;
|
|
33
|
+
}
|
|
25
34
|
type MiddlewareFunction = () => Record<string, unknown>;
|
|
26
35
|
declare class LoggerInstanceManager {
|
|
27
36
|
#private;
|
|
28
|
-
constructor(logLevel?: LogLevel, context?: ServiceContext);
|
|
37
|
+
constructor(logLevel?: LogLevel, context?: ServiceContext, config?: LoggerConfig);
|
|
29
38
|
private winstonLikeLoggerCall;
|
|
30
39
|
private lazyLoggerCall;
|
|
31
40
|
private addMetadata;
|
|
@@ -59,7 +68,7 @@ interface OverloadedChildLoggerMethod {
|
|
|
59
68
|
(metadata: Record<string, unknown>): LoggerInstanceManager;
|
|
60
69
|
(instanceNamePrefix: string, metadata: Record<string, unknown>): LoggerInstanceManager;
|
|
61
70
|
}
|
|
62
|
-
declare const _default: (loglevel?: `${LogLevel}`, context?: ServiceContext) => LoggerInstanceManager;
|
|
71
|
+
declare const _default: (loglevel?: `${LogLevel}`, context?: ServiceContext, config?: LoggerConfig) => LoggerInstanceManager;
|
|
63
72
|
//#endregion
|
|
64
|
-
export { LogLevel, LoggerInstanceManager, type ServiceContext, addToContext, _default as default, loggerContextMiddleware, runWithLoggerContext };
|
|
73
|
+
export { LogLevel, LoggerConfig, LoggerInstanceManager, type ServiceContext, addToContext, _default as default, loggerContextMiddleware, runWithLoggerContext };
|
|
65
74
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -22,10 +22,19 @@ declare enum LogLevel {
|
|
|
22
22
|
fatal = "fatal",
|
|
23
23
|
}
|
|
24
24
|
type LazyLogFn = () => [string] | [string, unknown];
|
|
25
|
+
interface LoggerConfig {
|
|
26
|
+
/**
|
|
27
|
+
* Opt out of the `pino-pretty` transport and always emit structured
|
|
28
|
+
* single-line JSON, regardless of `NODE_ENV`. Useful for non-production
|
|
29
|
+
* deployments (e.g. staging on GCP) where pino-pretty's multi-line output is
|
|
30
|
+
* split into a separate log entry per row.
|
|
31
|
+
*/
|
|
32
|
+
disablePrettier?: boolean;
|
|
33
|
+
}
|
|
25
34
|
type MiddlewareFunction = () => Record<string, unknown>;
|
|
26
35
|
declare class LoggerInstanceManager {
|
|
27
36
|
#private;
|
|
28
|
-
constructor(logLevel?: LogLevel, context?: ServiceContext);
|
|
37
|
+
constructor(logLevel?: LogLevel, context?: ServiceContext, config?: LoggerConfig);
|
|
29
38
|
private winstonLikeLoggerCall;
|
|
30
39
|
private lazyLoggerCall;
|
|
31
40
|
private addMetadata;
|
|
@@ -59,7 +68,7 @@ interface OverloadedChildLoggerMethod {
|
|
|
59
68
|
(metadata: Record<string, unknown>): LoggerInstanceManager;
|
|
60
69
|
(instanceNamePrefix: string, metadata: Record<string, unknown>): LoggerInstanceManager;
|
|
61
70
|
}
|
|
62
|
-
declare const _default: (loglevel?: `${LogLevel}`, context?: ServiceContext) => LoggerInstanceManager;
|
|
71
|
+
declare const _default: (loglevel?: `${LogLevel}`, context?: ServiceContext, config?: LoggerConfig) => LoggerInstanceManager;
|
|
63
72
|
//#endregion
|
|
64
|
-
export { LogLevel, LoggerInstanceManager, type ServiceContext, addToContext, _default as default, loggerContextMiddleware, runWithLoggerContext };
|
|
73
|
+
export { LogLevel, LoggerConfig, LoggerInstanceManager, type ServiceContext, addToContext, _default as default, loggerContextMiddleware, runWithLoggerContext };
|
|
65
74
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createRequire as e}from"node:module";import t,{stdSerializers as n}from"pino";import{AsyncLocalStorage as r}from"node:async_hooks";const i={trace:`DEBUG`,debug:`DEBUG`,info:`INFO`,warn:`WARNING`,error:`ERROR`,fatal:`CRITICAL`};function a(e,t={}){let{serviceName:n,version:r,tags:a}=t,o={...n&&r&&{serviceContext:{service:n,version:r}},...a};return{base:Object.keys(o).length?o:null,formatters:{level:e=>({severity:i[e]??i.info,...[`error`,`fatal`].includes(e)&&{"@type":`type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent`}}),log(e){let t=e,n=t.err?.stack??t.error?.stack??t.e?.stack;return{...e,...n&&{stack_trace:n}}}},messageKey:`message`,...e}}const o=e(import.meta.url),s=e=>{try{let t=o(e);return t?.dogstatsd?t:null}catch{return null}},c=s(`dd-trace`)??s(`/opt/datadog/apm/library/js/node_modules/dd-trace`),l=[`debug`,`trace`].includes(process.env.LOG_LEVEL||process.env.PINO_LOG_LEVEL||``),u=process.env.DD_SITE||`datadoghq.eu`,d=c?null:process.env.DD_API_KEY,f=c?`dd-trace`:d?`api`:`none`;process.stdout.write(`[logger] Datadog metrics mode initialized: ${f}\n`);const p=(e,t)=>{let n=process.env.DD_SERVICE||process.env.SERVICE_NAME||`unknown`,r=process.env.DD_ENV||process.env.ENV_NAME||`local`,i=Object.fromEntries(Object.entries(t).filter(([,e])=>typeof e==`string`||typeof e==`number`));if(c){c.dogstatsd.increment(e,1,{service:n,env:r,...i});return}if(!d)return;let a=[`service:${n}`,`env:${r}`,...Object.entries(i).map(([e,t])=>`${e}:${String(t)}`)];fetch(`https://api.${u}/api/v2/series`,{method:`POST`,headers:{"Content-Type":`application/json`,"DD-API-KEY":d},body:JSON.stringify({series:[{metric:e,type:1,points:[{timestamp:Math.floor(Date.now()/1e3),value:1}],tags:a}]})}).then(e=>{!e.ok&&l&&e.text().then(t=>{process.stderr.write(`[logger] DD API error ${e.status}: ${t}\n`)}).catch(()=>void 0)}).catch(e=>{l&&process.stderr.write(`[logger] DD API fetch failed: ${String(e)}\n`)})},m=new r;function h(e){let t=m.getStore();if(t)for(let[n,r]of Object.entries(e))typeof r!=`string`&&typeof r!=`number`&&typeof r!=`boolean`||(t[n]=r)}function g(e){return m.run({},e)}function _(e,t,n){m.run({},n)}function v(){return m.getStore()??{}}let y=function(e){return e.trace=`trace`,e.debug=`debug`,e.info=`info`,e.warn=`warn`,e.error=`error`,e.fatal=`fatal`,e}({});const b=e=>e||(process.env.LOG_LEVEL?process.env.LOG_LEVEL:process.env.NODE_ENV&&[`production`,`staging`,`test`].includes(process.env.NODE_ENV)?y.info:(process.env.NODE_ENV,y.debug)),x=(e,n,r)=>{let
|
|
1
|
+
import{createRequire as e}from"node:module";import t,{stdSerializers as n}from"pino";import{AsyncLocalStorage as r}from"node:async_hooks";const i={trace:`DEBUG`,debug:`DEBUG`,info:`INFO`,warn:`WARNING`,error:`ERROR`,fatal:`CRITICAL`};function a(e,t={}){let{serviceName:n,version:r,tags:a}=t,o={...n&&r&&{serviceContext:{service:n,version:r}},...a};return{base:Object.keys(o).length?o:null,formatters:{level:e=>({severity:i[e]??i.info,...[`error`,`fatal`].includes(e)&&{"@type":`type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent`}}),log(e){let t=e,n=t.err?.stack??t.error?.stack??t.e?.stack;return{...e,...n&&{stack_trace:n}}}},messageKey:`message`,...e}}const o=e(import.meta.url),s=e=>{try{let t=o(e);return t?.dogstatsd?t:null}catch{return null}},c=s(`dd-trace`)??s(`/opt/datadog/apm/library/js/node_modules/dd-trace`),l=[`debug`,`trace`].includes(process.env.LOG_LEVEL||process.env.PINO_LOG_LEVEL||``),u=process.env.DD_SITE||`datadoghq.eu`,d=c?null:process.env.DD_API_KEY,f=c?`dd-trace`:d?`api`:`none`;process.stdout.write(`[logger] Datadog metrics mode initialized: ${f}\n`);const p=(e,t)=>{let n=process.env.DD_SERVICE||process.env.SERVICE_NAME||`unknown`,r=process.env.DD_ENV||process.env.ENV_NAME||`local`,i=Object.fromEntries(Object.entries(t).filter(([,e])=>typeof e==`string`||typeof e==`number`));if(c){c.dogstatsd.increment(e,1,{service:n,env:r,...i});return}if(!d)return;let a=[`service:${n}`,`env:${r}`,...Object.entries(i).map(([e,t])=>`${e}:${String(t)}`)];fetch(`https://api.${u}/api/v2/series`,{method:`POST`,headers:{"Content-Type":`application/json`,"DD-API-KEY":d},body:JSON.stringify({series:[{metric:e,type:1,points:[{timestamp:Math.floor(Date.now()/1e3),value:1}],tags:a}]})}).then(e=>{!e.ok&&l&&e.text().then(t=>{process.stderr.write(`[logger] DD API error ${e.status}: ${t}\n`)}).catch(()=>void 0)}).catch(e=>{l&&process.stderr.write(`[logger] DD API fetch failed: ${String(e)}\n`)})},m=new r;function h(e){let t=m.getStore();if(t)for(let[n,r]of Object.entries(e))typeof r!=`string`&&typeof r!=`number`&&typeof r!=`boolean`||(t[n]=r)}function g(e){return m.run({},e)}function _(e,t,n){m.run({},n)}function v(){return m.getStore()??{}}let y=function(e){return e.trace=`trace`,e.debug=`debug`,e.info=`info`,e.warn=`warn`,e.error=`error`,e.fatal=`fatal`,e}({});const b=e=>e||(process.env.LOG_LEVEL?process.env.LOG_LEVEL:process.env.NODE_ENV&&[`production`,`staging`,`test`].includes(process.env.NODE_ENV)?y.info:(process.env.NODE_ENV,y.debug)),x=(e,n,r,i)=>{let o;return o=process.env.NODE_ENV===`production`||i?.disablePrettier?t(a({level:process.env.PINO_LOG_LEVEL||`info`,...n},r)):t({level:process.env.PINO_LOG_LEVEL||`info`,transport:{target:`pino-pretty`,options:{colorize:!0}},...n}),o.level=e,o};var S=class e{#e=[v];#t;constructor(t,r,i){this.addContextMiddleware=e=>this.#e.push(e),this.addToContext=e=>h(e),this.trace=(e,t)=>this.winstonLikeLoggerCall(y.trace,e,t),this.traceLazy=e=>this.lazyLoggerCall(y.trace,e),this.debug=(e,t)=>this.winstonLikeLoggerCall(y.debug,e,t),this.debugLazy=e=>this.lazyLoggerCall(y.debug,e),this.info=(e,t)=>this.winstonLikeLoggerCall(y.info,e,t),this.infoLazy=e=>this.lazyLoggerCall(y.info,e),this.warn=(e,t)=>this.winstonLikeLoggerCall(y.warn,e,t),this.warnLazy=e=>this.lazyLoggerCall(y.warn,e),this.error=(e,t)=>this.winstonLikeLoggerCall(y.error,e,t),this.errorLazy=e=>this.lazyLoggerCall(y.error,e),this.fatal=(e,t)=>this.winstonLikeLoggerCall(y.fatal,e,t),this.fatalLazy=e=>this.lazyLoggerCall(y.fatal,e),this.silent=(e,t)=>{},this.trackEvent=(e,t={})=>{p(e,t)},this.child=(...t)=>{let n=new e;if(n.#e=[...this.#e],typeof t[0]==`string`){let[e,r]=t;n.#t=this.#t.child(r,{msgPrefix:`[${e}] `})}else if(typeof t[0]==`object`)n.#t=this.#t.child(t[0]);else throw Error(`Invalid arguments to child logger`);return n},this.#t=x(b(t),{mixin:()=>this.addMetadata(),serializers:{...n,e:n.errWithCause,err:n.errWithCause,error:n.errWithCause,errors(e){return Array.isArray(e)?e.map(n.errWithCause):n.errWithCause(e)}}},r,i)}winstonLikeLoggerCall(e,t,n){t&&typeof t==`object`&&typeof n==`string`?this.#t[e](t,n):n?this.#t[e](n,t):this.#t[e](t)}lazyLoggerCall(e,t){if(!this.#t.isLevelEnabled(e))return;let[n,r]=t();this.winstonLikeLoggerCall(e,n,r)}addMetadata(){let e={};return this.#e.forEach(t=>{let n=t();Object.assign(e,n)}),e}get level(){return this.#t.level}},C=(e,t,n)=>new S(e,t,n);export{y as LogLevel,S as LoggerInstanceManager,h as addToContext,C as default,_ as loggerContextMiddleware,g as runWithLoggerContext};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["levelToSeverity: Record<LevelOrString, string>","ddMode: DDMode","#contextMiddlewares","context","#logger","newMetadata: Record<string, unknown>"],"sources":["../src/gcpLogOptions.ts","../src/datadogClient.ts","../src/context.ts","../src/index.ts"],"sourcesContent":["// Based on https://github.com/simenandre/pino-cloud-logging/blob/7816b2e4dec3dd18ef34c0f3f241d88a4cab0b90/src/main.ts\n// The repo is licensed under the Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0\n// Extracted since the repo no longer receives updates\n\nimport type { LevelOrString, LoggerOptions } from 'pino';\n\n// Map Pino levels to Google Cloud Logging severity levels\n// https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity\nconst levelToSeverity: Record<LevelOrString, string> = {\n trace: 'DEBUG',\n debug: 'DEBUG',\n info: 'INFO',\n warn: 'WARNING',\n error: 'ERROR',\n fatal: 'CRITICAL',\n};\n\nexport interface ServiceContext {\n serviceName?: string;\n version?: string;\n tags?: Record<string, string>;\n}\n\nexport function gcpLogOptions(\n options?: LoggerOptions,\n context: ServiceContext = {},\n): LoggerOptions {\n const { serviceName, version, tags } = context;\n\n const baseObj = {\n ...(serviceName && version && { serviceContext: { service: serviceName, version } }),\n ...tags,\n };\n const base = Object.keys(baseObj).length ? baseObj : null;\n\n return {\n // https://cloud.google.com/error-reporting/docs/formatting-error-messages#json_representation\n base,\n formatters: {\n level: (label: string) => ({\n severity: levelToSeverity[label] ?? levelToSeverity.info,\n // `@type` property tells Error Reporting to track even if there is no `stack_trace`\n ...(['error', 'fatal'].includes(label) && { '@type': 'type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent' }),\n }),\n\n log(object) {\n const logObject = object as { err?: Error; error?: Error; e?: Error; };\n const stackTrace = logObject.err?.stack ?? logObject.error?.stack ?? logObject.e?.stack;\n // eslint-disable-next-line camelcase\n return { ...object, ...(stackTrace && { stack_trace: stackTrace }) };\n },\n },\n messageKey: 'message',\n ...options,\n };\n}\n","import { createRequire } from 'node:module';\n\nconst _require = createRequire(import.meta.url);\n\ninterface DDTracer {\n dogstatsd: {\n increment: (metric: string, value: number, tags?: Record<string, string | number>) => void;\n };\n}\n\nconst tryRequire = (path: string): DDTracer | null => {\n try {\n const t = _require(path) as DDTracer;\n return t?.dogstatsd ? t : null;\n } catch {\n return null;\n }\n};\n\nconst tracer = tryRequire('dd-trace') ?? tryRequire('/opt/datadog/apm/library/js/node_modules/dd-trace');\nconst isDebugLevel = ['debug', 'trace'].includes(process.env.LOG_LEVEL || process.env.PINO_LOG_LEVEL || '');\n\nconst ddSite = process.env.DD_SITE || 'datadoghq.eu';\nconst ddApiKey = !tracer ? process.env.DD_API_KEY : null;\n\nexport type DDMode = 'dd-trace' | 'api' | 'none';\nexport const ddMode: DDMode = tracer ? 'dd-trace' : ddApiKey ? 'api' : 'none';\nprocess.stdout.write(`[logger] Datadog metrics mode initialized: ${ddMode}\\n`);\n\nexport const sendDDEvent = (eventName: string, data: Record<string, unknown>): void => {\n const service = process.env.DD_SERVICE || process.env.SERVICE_NAME || 'unknown';\n const env = process.env.DD_ENV || process.env.ENV_NAME || 'local';\n\n const primitiveData = Object.fromEntries(\n Object.entries(data).filter(([, v]) => typeof v === 'string' || typeof v === 'number'),\n ) as Record<string, string | number>;\n\n if (tracer) {\n tracer.dogstatsd.increment(eventName, 1, { service, env, ...primitiveData });\n return;\n }\n\n if (!ddApiKey) return;\n\n const tags = [\n `service:${service}`,\n `env:${env}`,\n ...Object.entries(primitiveData).map(([k, v]) => `${k}:${String(v)}`),\n ];\n\n fetch(`https://api.${ddSite}/api/v2/series`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'DD-API-KEY': ddApiKey },\n body: JSON.stringify({\n series: [{\n metric: eventName,\n type: 1,\n points: [{ timestamp: Math.floor(Date.now() / 1000), value: 1 }],\n tags,\n }],\n }),\n }).then((res) => {\n if (!res.ok && isDebugLevel) {\n res.text().then((body) => {\n process.stderr.write(`[logger] DD API error ${res.status}: ${body}\\n`);\n }).catch(() => undefined);\n }\n }).catch((err) => {\n if (isDebugLevel) {\n process.stderr.write(`[logger] DD API fetch failed: ${String(err)}\\n`);\n }\n });\n};\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\ntype LogContext = Record<string, string | number | boolean>;\n\nconst storage = new AsyncLocalStorage<LogContext>();\n\nexport function addToContext(context: Record<string, string | number | boolean>): void {\n const store = storage.getStore();\n if (!store) return;\n for (const [key, value] of Object.entries(context)) {\n if (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean') continue;\n store[key] = value;\n }\n}\n\nexport function runWithLoggerContext<T>(fn: () => T): T {\n return storage.run({}, fn);\n}\n\nexport function loggerContextMiddleware(_req: unknown, _res: unknown, next: () => void): void {\n storage.run({}, next);\n}\n\nexport function getContext(): LogContext {\n return storage.getStore() ?? {};\n}\n","import Pino, { type LoggerOptions, stdSerializers } from 'pino';\nimport { gcpLogOptions, type ServiceContext } from './gcpLogOptions';\nimport { sendDDEvent } from './datadogClient';\nimport { getContext, addToContext, runWithLoggerContext, loggerContextMiddleware } from './context';\n\nexport { type ServiceContext };\nexport { addToContext, runWithLoggerContext, loggerContextMiddleware };\n\nexport enum LogLevel {\n trace = 'trace',\n debug = 'debug',\n info = 'info',\n warn = 'warn',\n error = 'error',\n fatal = 'fatal',\n}\ntype LazyLogFn = () => [string] | [string, unknown];\n\nconst getLevel = (logLevel?: LogLevel): LogLevel => {\n if (logLevel) return logLevel;\n if (process.env.LOG_LEVEL) return process.env.LOG_LEVEL as LogLevel;\n if (process.env.NODE_ENV && ['production', 'staging', 'test'].includes(process.env.NODE_ENV)) return LogLevel.info;\n if (process.env.NODE_ENV === 'development') return LogLevel.debug;\n return LogLevel.debug;\n};\n\nconst createLoggerInstance = (level: LogLevel, options: Omit<LoggerOptions, 'transport'>, context?: ServiceContext): Pino.Logger => {\n let loggerInstance;\n if (process.env.NODE_ENV === 'production') {\n loggerInstance = Pino(gcpLogOptions({\n level: process.env.PINO_LOG_LEVEL || 'info',\n ...options,\n } as object, context));\n } else {\n loggerInstance = Pino({\n level: process.env.PINO_LOG_LEVEL || 'info',\n transport: {\n target: 'pino-pretty',\n options: {\n colorize: true,\n },\n },\n ...options,\n });\n }\n loggerInstance.level = level;\n return loggerInstance;\n};\n\ntype MiddlewareFunction = () => Record<string, unknown>;\n\nexport class LoggerInstanceManager {\n #contextMiddlewares: MiddlewareFunction[] = [getContext];\n\n #logger: Pino.Logger;\n\n constructor(logLevel?: LogLevel, context?: ServiceContext) {\n this.#logger = createLoggerInstance(getLevel(logLevel), {\n mixin: () => this.addMetadata(),\n serializers: {\n ...stdSerializers,\n e: stdSerializers.errWithCause,\n err: stdSerializers.errWithCause,\n error: stdSerializers.errWithCause,\n errors(val) {\n if (Array.isArray(val)) {\n return val.map(stdSerializers.errWithCause);\n }\n return stdSerializers.errWithCause(val);\n },\n },\n }, context);\n }\n\n // To support winston like logging in pino\n private winstonLikeLoggerCall(logLevel: LogLevel, message: string, meta: unknown): void {\n if (message && typeof message === 'object' && typeof meta === 'string') {\n // Fastify sends the message as the second parameter when logging (which is how pino actually works),\n this.#logger[logLevel](message as object, meta);\n } else if (meta) {\n this.#logger[logLevel](meta, message);\n } else {\n this.#logger[logLevel](message);\n }\n }\n\n private lazyLoggerCall(logLevel: LogLevel, fn: LazyLogFn): void {\n if (!this.#logger.isLevelEnabled(logLevel)) {\n return;\n }\n const [message, meta] = fn();\n this.winstonLikeLoggerCall(logLevel, message, meta);\n }\n\n private addMetadata(): Record<string, unknown> {\n const newMetadata: Record<string, unknown> = {};\n this.#contextMiddlewares.forEach((middleware) => {\n const metadata = middleware();\n Object.assign(newMetadata, metadata);\n });\n return newMetadata;\n }\n\n addContextMiddleware = (middleware: MiddlewareFunction): number => this.#contextMiddlewares.push(middleware);\n\n addToContext = (context: Record<string, string | number | boolean>): void => addToContext(context);\n\n trace = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.trace, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the trace level is enabled */\n traceLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.trace, fn);\n\n debug = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.debug, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the debug level is enabled */\n debugLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.debug, fn);\n\n info = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.info, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the info level is enabled */\n infoLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.info, fn);\n\n warn = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.warn, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the warn level is enabled */\n warnLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.warn, fn);\n\n error = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.error, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the error level is enabled */\n errorLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.error, fn);\n\n fatal = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.fatal, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the fatal level is enabled */\n fatalLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.fatal, fn);\n\n /** No-op logging method for silent level (required for Fastify compatibility) */\n silent = (_message: string, _meta?: unknown): void => {\n // no-op\n };\n\n trackEvent = (eventName: string, data: Record<string, unknown> = {}): void => {\n sendDDEvent(eventName, data);\n };\n\n child: OverloadedChildLoggerMethod = (...args: [metadata: Record<string, unknown>] | [instanceNamePrefix: string, metadata: Record<string, unknown>]) => {\n const childLoggerInstanceManager = new LoggerInstanceManager();\n childLoggerInstanceManager.#contextMiddlewares = [...this.#contextMiddlewares];\n\n if (typeof args[0] === 'string') {\n // Overload: child(instanceNamePrefix: string, metadata: Record<string, unknown>)\n const [instanceNamePrefix, metadata] = args;\n childLoggerInstanceManager.#logger = this.#logger.child(metadata!, { msgPrefix: `[${instanceNamePrefix}] ` });\n } else if (typeof args[0] === 'object') {\n // Overload: child(metadata: Record<string, unknown>)\n childLoggerInstanceManager.#logger = this.#logger.child(args[0]);\n } else {\n throw new Error('Invalid arguments to child logger');\n }\n return childLoggerInstanceManager;\n };\n\n get level(): Pino.LevelWithSilentOrString {\n return this.#logger.level;\n }\n}\n\ninterface OverloadedChildLoggerMethod {\n (metadata: Record<string, unknown>): LoggerInstanceManager;\n (instanceNamePrefix: string, metadata: Record<string, unknown>): LoggerInstanceManager;\n}\n\nexport default (loglevel?: `${LogLevel}`, context?: ServiceContext): LoggerInstanceManager => new LoggerInstanceManager(loglevel as LogLevel, context);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["levelToSeverity: Record<LevelOrString, string>","ddMode: DDMode","#contextMiddlewares","context","#logger","newMetadata: Record<string, unknown>"],"sources":["../src/gcpLogOptions.ts","../src/datadogClient.ts","../src/context.ts","../src/index.ts"],"sourcesContent":["// Based on https://github.com/simenandre/pino-cloud-logging/blob/7816b2e4dec3dd18ef34c0f3f241d88a4cab0b90/src/main.ts\n// The repo is licensed under the Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0\n// Extracted since the repo no longer receives updates\n\nimport type { LevelOrString, LoggerOptions } from 'pino';\n\n// Map Pino levels to Google Cloud Logging severity levels\n// https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity\nconst levelToSeverity: Record<LevelOrString, string> = {\n trace: 'DEBUG',\n debug: 'DEBUG',\n info: 'INFO',\n warn: 'WARNING',\n error: 'ERROR',\n fatal: 'CRITICAL',\n};\n\nexport interface ServiceContext {\n serviceName?: string;\n version?: string;\n tags?: Record<string, string>;\n}\n\nexport function gcpLogOptions(\n options?: LoggerOptions,\n context: ServiceContext = {},\n): LoggerOptions {\n const { serviceName, version, tags } = context;\n\n const baseObj = {\n ...(serviceName && version && { serviceContext: { service: serviceName, version } }),\n ...tags,\n };\n const base = Object.keys(baseObj).length ? baseObj : null;\n\n return {\n // https://cloud.google.com/error-reporting/docs/formatting-error-messages#json_representation\n base,\n formatters: {\n level: (label: string) => ({\n severity: levelToSeverity[label] ?? levelToSeverity.info,\n // `@type` property tells Error Reporting to track even if there is no `stack_trace`\n ...(['error', 'fatal'].includes(label) && { '@type': 'type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent' }),\n }),\n\n log(object) {\n const logObject = object as { err?: Error; error?: Error; e?: Error; };\n const stackTrace = logObject.err?.stack ?? logObject.error?.stack ?? logObject.e?.stack;\n // eslint-disable-next-line camelcase\n return { ...object, ...(stackTrace && { stack_trace: stackTrace }) };\n },\n },\n messageKey: 'message',\n ...options,\n };\n}\n","import { createRequire } from 'node:module';\n\nconst _require = createRequire(import.meta.url);\n\ninterface DDTracer {\n dogstatsd: {\n increment: (metric: string, value: number, tags?: Record<string, string | number>) => void;\n };\n}\n\nconst tryRequire = (path: string): DDTracer | null => {\n try {\n const t = _require(path) as DDTracer;\n return t?.dogstatsd ? t : null;\n } catch {\n return null;\n }\n};\n\nconst tracer = tryRequire('dd-trace') ?? tryRequire('/opt/datadog/apm/library/js/node_modules/dd-trace');\nconst isDebugLevel = ['debug', 'trace'].includes(process.env.LOG_LEVEL || process.env.PINO_LOG_LEVEL || '');\n\nconst ddSite = process.env.DD_SITE || 'datadoghq.eu';\nconst ddApiKey = !tracer ? process.env.DD_API_KEY : null;\n\nexport type DDMode = 'dd-trace' | 'api' | 'none';\nexport const ddMode: DDMode = tracer ? 'dd-trace' : ddApiKey ? 'api' : 'none';\nprocess.stdout.write(`[logger] Datadog metrics mode initialized: ${ddMode}\\n`);\n\nexport const sendDDEvent = (eventName: string, data: Record<string, unknown>): void => {\n const service = process.env.DD_SERVICE || process.env.SERVICE_NAME || 'unknown';\n const env = process.env.DD_ENV || process.env.ENV_NAME || 'local';\n\n const primitiveData = Object.fromEntries(\n Object.entries(data).filter(([, v]) => typeof v === 'string' || typeof v === 'number'),\n ) as Record<string, string | number>;\n\n if (tracer) {\n tracer.dogstatsd.increment(eventName, 1, { service, env, ...primitiveData });\n return;\n }\n\n if (!ddApiKey) return;\n\n const tags = [\n `service:${service}`,\n `env:${env}`,\n ...Object.entries(primitiveData).map(([k, v]) => `${k}:${String(v)}`),\n ];\n\n fetch(`https://api.${ddSite}/api/v2/series`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'DD-API-KEY': ddApiKey },\n body: JSON.stringify({\n series: [{\n metric: eventName,\n type: 1,\n points: [{ timestamp: Math.floor(Date.now() / 1000), value: 1 }],\n tags,\n }],\n }),\n }).then((res) => {\n if (!res.ok && isDebugLevel) {\n res.text().then((body) => {\n process.stderr.write(`[logger] DD API error ${res.status}: ${body}\\n`);\n }).catch(() => undefined);\n }\n }).catch((err) => {\n if (isDebugLevel) {\n process.stderr.write(`[logger] DD API fetch failed: ${String(err)}\\n`);\n }\n });\n};\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\ntype LogContext = Record<string, string | number | boolean>;\n\nconst storage = new AsyncLocalStorage<LogContext>();\n\nexport function addToContext(context: Record<string, string | number | boolean>): void {\n const store = storage.getStore();\n if (!store) return;\n for (const [key, value] of Object.entries(context)) {\n if (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean') continue;\n store[key] = value;\n }\n}\n\nexport function runWithLoggerContext<T>(fn: () => T): T {\n return storage.run({}, fn);\n}\n\nexport function loggerContextMiddleware(_req: unknown, _res: unknown, next: () => void): void {\n storage.run({}, next);\n}\n\nexport function getContext(): LogContext {\n return storage.getStore() ?? {};\n}\n","import Pino, { type LoggerOptions, stdSerializers } from 'pino';\nimport { gcpLogOptions, type ServiceContext } from './gcpLogOptions';\nimport { sendDDEvent } from './datadogClient';\nimport { getContext, addToContext, runWithLoggerContext, loggerContextMiddleware } from './context';\n\nexport { type ServiceContext };\nexport { addToContext, runWithLoggerContext, loggerContextMiddleware };\n\nexport enum LogLevel {\n trace = 'trace',\n debug = 'debug',\n info = 'info',\n warn = 'warn',\n error = 'error',\n fatal = 'fatal',\n}\ntype LazyLogFn = () => [string] | [string, unknown];\n\nexport interface LoggerConfig {\n /**\n * Opt out of the `pino-pretty` transport and always emit structured\n * single-line JSON, regardless of `NODE_ENV`. Useful for non-production\n * deployments (e.g. staging on GCP) where pino-pretty's multi-line output is\n * split into a separate log entry per row.\n */\n disablePrettier?: boolean;\n}\n\nconst getLevel = (logLevel?: LogLevel): LogLevel => {\n if (logLevel) return logLevel;\n if (process.env.LOG_LEVEL) return process.env.LOG_LEVEL as LogLevel;\n if (process.env.NODE_ENV && ['production', 'staging', 'test'].includes(process.env.NODE_ENV)) return LogLevel.info;\n if (process.env.NODE_ENV === 'development') return LogLevel.debug;\n return LogLevel.debug;\n};\n\nconst createLoggerInstance = (level: LogLevel, options: Omit<LoggerOptions, 'transport'>, context?: ServiceContext, config?: LoggerConfig): Pino.Logger => {\n let loggerInstance;\n if (process.env.NODE_ENV === 'production' || config?.disablePrettier) {\n loggerInstance = Pino(gcpLogOptions({\n level: process.env.PINO_LOG_LEVEL || 'info',\n ...options,\n } as object, context));\n } else {\n loggerInstance = Pino({\n level: process.env.PINO_LOG_LEVEL || 'info',\n transport: {\n target: 'pino-pretty',\n options: {\n colorize: true,\n },\n },\n ...options,\n });\n }\n loggerInstance.level = level;\n return loggerInstance;\n};\n\ntype MiddlewareFunction = () => Record<string, unknown>;\n\nexport class LoggerInstanceManager {\n #contextMiddlewares: MiddlewareFunction[] = [getContext];\n\n #logger: Pino.Logger;\n\n constructor(logLevel?: LogLevel, context?: ServiceContext, config?: LoggerConfig) {\n this.#logger = createLoggerInstance(getLevel(logLevel), {\n mixin: () => this.addMetadata(),\n serializers: {\n ...stdSerializers,\n e: stdSerializers.errWithCause,\n err: stdSerializers.errWithCause,\n error: stdSerializers.errWithCause,\n errors(val) {\n if (Array.isArray(val)) {\n return val.map(stdSerializers.errWithCause);\n }\n return stdSerializers.errWithCause(val);\n },\n },\n }, context, config);\n }\n\n // To support winston like logging in pino\n private winstonLikeLoggerCall(logLevel: LogLevel, message: string, meta: unknown): void {\n if (message && typeof message === 'object' && typeof meta === 'string') {\n // Fastify sends the message as the second parameter when logging (which is how pino actually works),\n this.#logger[logLevel](message as object, meta);\n } else if (meta) {\n this.#logger[logLevel](meta, message);\n } else {\n this.#logger[logLevel](message);\n }\n }\n\n private lazyLoggerCall(logLevel: LogLevel, fn: LazyLogFn): void {\n if (!this.#logger.isLevelEnabled(logLevel)) {\n return;\n }\n const [message, meta] = fn();\n this.winstonLikeLoggerCall(logLevel, message, meta);\n }\n\n private addMetadata(): Record<string, unknown> {\n const newMetadata: Record<string, unknown> = {};\n this.#contextMiddlewares.forEach((middleware) => {\n const metadata = middleware();\n Object.assign(newMetadata, metadata);\n });\n return newMetadata;\n }\n\n addContextMiddleware = (middleware: MiddlewareFunction): number => this.#contextMiddlewares.push(middleware);\n\n addToContext = (context: Record<string, string | number | boolean>): void => addToContext(context);\n\n trace = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.trace, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the trace level is enabled */\n traceLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.trace, fn);\n\n debug = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.debug, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the debug level is enabled */\n debugLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.debug, fn);\n\n info = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.info, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the info level is enabled */\n infoLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.info, fn);\n\n warn = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.warn, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the warn level is enabled */\n warnLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.warn, fn);\n\n error = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.error, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the error level is enabled */\n errorLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.error, fn);\n\n fatal = (message: string, meta?: unknown): void => this.winstonLikeLoggerCall(LogLevel.fatal, message, meta);\n /** A lazy version of trace that only evaluates the message and metadata only if the fatal level is enabled */\n fatalLazy = (fn: LazyLogFn): void => this.lazyLoggerCall(LogLevel.fatal, fn);\n\n /** No-op logging method for silent level (required for Fastify compatibility) */\n silent = (_message: string, _meta?: unknown): void => {\n // no-op\n };\n\n trackEvent = (eventName: string, data: Record<string, unknown> = {}): void => {\n sendDDEvent(eventName, data);\n };\n\n child: OverloadedChildLoggerMethod = (...args: [metadata: Record<string, unknown>] | [instanceNamePrefix: string, metadata: Record<string, unknown>]) => {\n const childLoggerInstanceManager = new LoggerInstanceManager();\n childLoggerInstanceManager.#contextMiddlewares = [...this.#contextMiddlewares];\n\n if (typeof args[0] === 'string') {\n // Overload: child(instanceNamePrefix: string, metadata: Record<string, unknown>)\n const [instanceNamePrefix, metadata] = args;\n childLoggerInstanceManager.#logger = this.#logger.child(metadata!, { msgPrefix: `[${instanceNamePrefix}] ` });\n } else if (typeof args[0] === 'object') {\n // Overload: child(metadata: Record<string, unknown>)\n childLoggerInstanceManager.#logger = this.#logger.child(args[0]);\n } else {\n throw new Error('Invalid arguments to child logger');\n }\n return childLoggerInstanceManager;\n };\n\n get level(): Pino.LevelWithSilentOrString {\n return this.#logger.level;\n }\n}\n\ninterface OverloadedChildLoggerMethod {\n (metadata: Record<string, unknown>): LoggerInstanceManager;\n (instanceNamePrefix: string, metadata: Record<string, unknown>): LoggerInstanceManager;\n}\n\nexport default (loglevel?: `${LogLevel}`, context?: ServiceContext, config?: LoggerConfig): LoggerInstanceManager => new LoggerInstanceManager(loglevel as LogLevel, context, config);\n"],"mappings":"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"}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -15,6 +15,17 @@ logger.error('errors displayed in logs/error.log', new Error('test error'));
|
|
|
15
15
|
logger.debug('debug with object', { a: 5 });
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
+
## Output format
|
|
19
|
+
|
|
20
|
+
By default the logger emits structured single-line JSON only when `NODE_ENV === 'production'`; otherwise it uses the multi-line `pino-pretty` transport. In a deployed non-production environment (e.g. staging on GCP) pino-pretty's multi-line output gets split into a separate log entry per row. Pass `disablePrettier` to force structured JSON regardless of `NODE_ENV`:
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
import Logger from '@autofleet/logger';
|
|
24
|
+
|
|
25
|
+
// 3rd arg: LoggerConfig — { disablePrettier?: boolean }
|
|
26
|
+
const logger = Logger(undefined, { serviceName: 'my-service', version: '1.0.0' }, { disablePrettier: true });
|
|
27
|
+
```
|
|
28
|
+
|
|
18
29
|
## Request-scoped context
|
|
19
30
|
|
|
20
31
|
Use `addToContext` to attach fields that automatically appear on every log within the same async request chain, isolated per concurrent request.
|