@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 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 r;return r=process.env.NODE_ENV===`production`?(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}),r.level=e,r};var k=class e{#e=[T];#t;constructor(t,n){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)}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)=>new k(e,t);exports.LogLevel=E,exports.LoggerInstanceManager=k,exports.addToContext=S,exports.default=A,exports.loggerContextMiddleware=w,exports.runWithLoggerContext=C;
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
@@ -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 i;return i=process.env.NODE_ENV===`production`?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}),i.level=e,i};var S=class e{#e=[v];#t;constructor(t,r){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)}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)=>new S(e,t);export{y as LogLevel,S as LoggerInstanceManager,h as addToContext,C as default,_ as loggerContextMiddleware,g as runWithLoggerContext};
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/logger",
3
- "version": "4.6.2",
3
+ "version": "4.7.0-0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
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.