{"version":3,"file":"index.cjs","names":["MastraLogger","#adapterContextRef","LogLevel","#export"],"sources":["../src/pino.ts"],"sourcesContent":["import type { LoggerTransport, LoggerAdapterContext } from '@mastra/core/logger';\nimport { LogLevel, MastraLogger, buildLogRecordData, exportTrackedException } from '@mastra/core/logger';\nimport pino from 'pino';\nimport pretty from 'pino-pretty';\n\ntype TransportMap = Record<string, LoggerTransport>;\n\nexport type { LogLevel } from '@mastra/core/logger';\n\nexport interface PinoLoggerOptions<CustomLevels extends string = never> {\n  name?: string;\n  level?: LogLevel;\n  transports?: TransportMap;\n  overrideDefaultTransports?: boolean;\n  formatters?: pino.LoggerOptions['formatters'];\n  redact?: pino.LoggerOptions['redact'];\n  mixin?: pino.MixinFn<CustomLevels>;\n  customLevels?: { [level in CustomLevels]: number };\n  /**\n   * When false, disables pino-pretty and outputs raw JSON.\n   * Useful when sending logs to aggregators like Datadog,\n   * Loki, or CloudWatch that expect single-line JSON per entry.\n   * @default true\n   */\n  prettyPrint?: boolean;\n  /**\n   * Override the key used for the log message.\n   * Defaults to Pino's built-in 'msg' key.\n   * Set to 'message' for compatibility with Google Cloud Logging,\n   * Elastic Common Schema (ECS), Datadog, and AWS CloudWatch.\n   * @example 'message'\n   */\n  messageKey?: string;\n  /**\n   * Custom pino serializers, merged over Mastra's defaults.\n   * By default the `error` key is serialized with pino's standard error\n   * serializer (alongside pino's built-in `err`), so that\n   * `logger.warn('...', { error })` records the message and stack rather\n   * than an empty object.\n   */\n  serializers?: pino.LoggerOptions['serializers'];\n}\n\ninterface PinoLoggerInternalOptions<CustomLevels extends string = never> extends PinoLoggerOptions<CustomLevels> {\n  /** @internal Used internally for child loggers */\n  _logger?: pino.Logger<CustomLevels>;\n  /** @internal Shared adapter-context ref so root and children correlate together */\n  _adapterContextRef?: { current?: LoggerAdapterContext };\n}\n\n/**\n * Provides Pino-backed logging for Mastra applications.\n *\n * @example\n * ```typescript\n * import { Mastra } from '@mastra/core/mastra';\n * import { PinoLogger } from '@mastra/loggers';\n *\n * const mastra = new Mastra({\n *   logger: new PinoLogger({ name: 'my-app', level: 'info' }),\n * });\n * ```\n *\n * @see For documentation bundled with your installed package, locate\n * `@mastra/loggers/package.json` with your project's resolver or package-manager\n * tooling, then read `dist/docs/SKILL.md` from that package root and follow its\n * reference links. Use package-manager tools for virtual or archived packages.\n *\n * @see [Pino logger documentation](https://mastra.ai/reference/logging/pino-logger)\n * if packaged docs are unavailable.\n */\nexport class PinoLogger<CustomLevels extends string = never> extends MastraLogger {\n  protected logger: pino.Logger<CustomLevels>;\n  // Mutable ref shared with child loggers: the root's mixin (which children's\n  // pino instances inherit) reads through this ref, so attaching observability\n  // to a child (e.g. `new Mastra({ logger: base.child({...}) })`) correlates\n  // the records it actually logs through.\n  #adapterContextRef: { current?: LoggerAdapterContext };\n\n  constructor(options: PinoLoggerOptions<CustomLevels> = {}) {\n    super(options);\n\n    const internalOptions = options as PinoLoggerInternalOptions<CustomLevels>;\n    this.#adapterContextRef = internalOptions._adapterContextRef ?? {};\n\n    // If an existing pino logger is provided (for child loggers), use it directly\n    if (internalOptions._logger) {\n      this.logger = internalOptions._logger;\n      return;\n    }\n\n    // Compose the user mixin with trace correlation. Pino mixins run\n    // synchronously on every log call, so the trace fields land in the\n    // native record before serialization — for ALL destinations (stdout,\n    // transports, files). Trace fields win on key conflicts.\n    const userMixin = options.mixin;\n    const correlationMixin: pino.MixinFn<CustomLevels> = (mergeObject, level, logger) => {\n      const userFields = userMixin ? userMixin(mergeObject, level, logger) : {};\n      const ctx = this.#adapterContextRef.current;\n      if (!ctx?.options.correlation) return userFields;\n      try {\n        return { ...userFields, ...(ctx.resolveTraceFields() ?? {}) };\n      } catch {\n        return userFields;\n      }\n    };\n\n    const shouldPrettyPrint = options.prettyPrint ?? true;\n    let prettyStream: ReturnType<typeof pretty> | undefined = undefined;\n    if (!options.overrideDefaultTransports && shouldPrettyPrint) {\n      prettyStream = pretty({\n        colorize: true,\n        levelFirst: true,\n        ignore: 'pid,hostname,component',\n        colorizeObjects: true,\n        translateTime: 'SYS:standard',\n        singleLine: false,\n      });\n    }\n\n    const transportsAry = [...this.getTransports().entries()];\n    this.logger = pino(\n      {\n        name: options.name || 'app',\n        level: options.level || LogLevel.INFO,\n        formatters: options.formatters,\n        redact: options.redact,\n        mixin: correlationMixin,\n        customLevels: options.customLevels,\n        messageKey: options.messageKey ?? 'msg',\n        // Pino applies its error serializer only to `errorKey` (default `err`).\n        // Mastra logs errors as `{ error }` throughout, and an Error's `message`\n        // and `stack` are non-enumerable, so without this they serialize to `{}`.\n        serializers: { error: pino.stdSerializers.err, ...options.serializers },\n      },\n      options.overrideDefaultTransports\n        ? options?.transports?.default\n        : transportsAry.length === 0\n          ? prettyStream // undefined when prettyPrint:false → pino native JSON\n          : pino.multistream([\n              ...transportsAry.map(([, transport]) => ({\n                stream: transport,\n                level: options.level || LogLevel.INFO,\n              })),\n              ...(prettyStream // only add prettyStream to multistream if it exists\n                ? [{ stream: prettyStream, level: options.level || LogLevel.INFO }]\n                : []),\n            ]),\n    );\n  }\n\n  /**\n   * Creates a child logger with additional bound context.\n   * All logs from the child logger will include the bound context.\n   *\n   * @param bindings - Key-value pairs to include in all logs from this child logger\n   * @returns A new PinoLogger instance with the bound context\n   *\n   * @example\n   * ```typescript\n   * const baseLogger = new PinoLogger({ name: 'MyApp' });\n   *\n   * // Create module-scoped logger\n   * const serviceLogger = baseLogger.child({ module: 'UserService' });\n   * serviceLogger.info('User created', { userId: '123' });\n   * // Output includes: { module: 'UserService', userId: '123', msg: 'User created' }\n   *\n   * // Create request-scoped logger\n   * const requestLogger = baseLogger.child({ requestId: req.id });\n   * requestLogger.error('Request failed', { err: error });\n   * // Output includes: { requestId: 'abc', msg: 'Request failed', err: {...} }\n   * ```\n   */\n  child(bindings: Record<string, unknown>): PinoLogger<CustomLevels> {\n    const childPino = this.logger.child(bindings);\n    const childOptions: PinoLoggerInternalOptions<CustomLevels> = {\n      name: this.name,\n      level: this.level,\n      transports: Object.fromEntries(this.transports),\n      _logger: childPino,\n      _adapterContextRef: this.#adapterContextRef,\n    };\n    return new PinoLogger(childOptions);\n  }\n\n  /**\n   * Adapter hook (see `AdaptableLogger` in `@mastra/core/logger`): enables\n   * native trace correlation (trace_id/span_id merged into the pino record\n   * via mixin, for every destination) and observability export derived from\n   * the same record. Called by Mastra during setup.\n   */\n  __attachObservability(ctx: LoggerAdapterContext): void {\n    // Shared ref: attaching to a child also enables correlation on the root\n    // mixin the child's records flow through (and vice versa).\n    this.#adapterContextRef.current = ctx;\n  }\n\n  /**\n   * The adapter context lives on the ref cell shared by the whole\n   * root/child family, so re-attach detection (multi-Mastra warning) must\n   * key on that cell — attaching to a child re-targets the root too.\n   */\n  __observabilityAttachmentKey(): object {\n    return this.#adapterContextRef;\n  }\n\n  /**\n   * Export the record derived from the same native call to observability.\n   * Runs regardless of pino's level filter and never throws into the caller.\n   */\n  #export(level: 'debug' | 'info' | 'warn' | 'error', message: string, args: Record<string, any>): void {\n    const ctx = this.#adapterContextRef.current;\n    if (!ctx?.options.export) return;\n    try {\n      // An Error passed as the args value often has no enumerable keys but\n      // must still be exported (serialized by buildLogRecordData).\n      const hasPayload = args instanceof Error || Object.keys(args).length > 0;\n      // Trace identity travels on ExportedLog.traceId/spanId (the sink is\n      // span-correlated); data stays reserved for the user payload. The mixin\n      // still injects trace fields into the native pino record for stdout.\n      ctx.getLogSink()?.[level](message, buildLogRecordData(hasPayload ? [args] : []));\n    } catch {\n      // Never let observability export break the primary logger\n    }\n  }\n\n  debug(message: string, args: Record<string, any> = {}): void {\n    this.logger.debug(args, message);\n    this.#export('debug', message, args);\n  }\n\n  info(message: string, args: Record<string, any> = {}): void {\n    this.logger.info(args, message);\n    this.#export('info', message, args);\n  }\n\n  warn(message: string, args: Record<string, any> = {}): void {\n    this.logger.warn(args, message);\n    this.#export('warn', message, args);\n  }\n\n  error(message: string, args: Record<string, any> = {}): void {\n    this.logger.error(args, message);\n    this.#export('error', message, args);\n  }\n\n  override trackException(error: Error, metadata?: Record<string, unknown>): void {\n    exportTrackedException(this.#adapterContextRef.current, error, metadata);\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuEA,IAAa,aAAb,MAAa,mBAAwDA,oBAAAA,aAAa;CAChF;CAKA;CAEA,YAAY,UAA2C,CAAC,GAAG;EACzD,MAAM,OAAO;EAEb,MAAM,kBAAkB;EACxB,KAAKC,qBAAqB,gBAAgB,sBAAsB,CAAC;EAGjE,IAAI,gBAAgB,SAAS;GAC3B,KAAK,SAAS,gBAAgB;GAC9B;EACF;EAMA,MAAM,YAAY,QAAQ;EAC1B,MAAM,oBAAgD,aAAa,OAAO,WAAW;GACnF,MAAM,aAAa,YAAY,UAAU,aAAa,OAAO,MAAM,IAAI,CAAC;GACxE,MAAM,MAAM,KAAKA,mBAAmB;GACpC,IAAI,CAAC,KAAK,QAAQ,aAAa,OAAO;GACtC,IAAI;IACF,OAAO;KAAE,GAAG;KAAY,GAAI,IAAI,mBAAmB,KAAK,CAAC;IAAG;GAC9D,QAAQ;IACN,OAAO;GACT;EACF;EAEA,MAAM,oBAAoB,QAAQ,eAAe;EACjD,IAAI,eAAsD,KAAA;EAC1D,IAAI,CAAC,QAAQ,6BAA6B,mBACxC,gBAAA,GAAA,YAAA,QAAA,CAAsB;GACpB,UAAU;GACV,YAAY;GACZ,QAAQ;GACR,iBAAiB;GACjB,eAAe;GACf,YAAY;EACd,CAAC;EAGH,MAAM,gBAAgB,CAAC,GAAG,KAAK,cAAc,CAAC,CAAC,QAAQ,CAAC;EACxD,KAAK,UAAA,GAAA,KAAA,QAAA,CACH;GACE,MAAM,QAAQ,QAAQ;GACtB,OAAO,QAAQ,SAASC,oBAAAA,SAAS;GACjC,YAAY,QAAQ;GACpB,QAAQ,QAAQ;GAChB,OAAO;GACP,cAAc,QAAQ;GACtB,YAAY,QAAQ,cAAc;GAIlC,aAAa;IAAE,OAAO,KAAA,QAAK,eAAe;IAAK,GAAG,QAAQ;GAAY;EACxE,GACA,QAAQ,4BACJ,SAAS,YAAY,UACrB,cAAc,WAAW,IACvB,eACA,KAAA,QAAK,YAAY,CACf,GAAG,cAAc,KAAK,GAAG,gBAAgB;GACvC,QAAQ;GACR,OAAO,QAAQ,SAASA,oBAAAA,SAAS;EACnC,EAAE,GACF,GAAI,eACA,CAAC;GAAE,QAAQ;GAAc,OAAO,QAAQ,SAASA,oBAAAA,SAAS;EAAK,CAAC,IAChE,CAAC,CACP,CAAC,CACT;CACF;;;;;;;;;;;;;;;;;;;;;;;CAwBA,MAAM,UAA6D;EACjE,MAAM,YAAY,KAAK,OAAO,MAAM,QAAQ;EAC5C,MAAM,eAAwD;GAC5D,MAAM,KAAK;GACX,OAAO,KAAK;GACZ,YAAY,OAAO,YAAY,KAAK,UAAU;GAC9C,SAAS;GACT,oBAAoB,KAAKD;EAC3B;EACA,OAAO,IAAI,WAAW,YAAY;CACpC;;;;;;;CAQA,sBAAsB,KAAiC;EAGrD,KAAKA,mBAAmB,UAAU;CACpC;;;;;;CAOA,+BAAuC;EACrC,OAAO,KAAKA;CACd;;;;;CAMA,QAAQ,OAA4C,SAAiB,MAAiC;EACpG,MAAM,MAAM,KAAKA,mBAAmB;EACpC,IAAI,CAAC,KAAK,QAAQ,QAAQ;EAC1B,IAAI;GAGF,MAAM,aAAa,gBAAgB,SAAS,OAAO,KAAK,IAAI,CAAC,CAAC,SAAS;GAIvE,IAAI,WAAW,CAAC,GAAG,MAAM,CAAC,UAAA,GAAA,oBAAA,mBAAA,CAA4B,aAAa,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;EACjF,QAAQ,CAER;CACF;CAEA,MAAM,SAAiB,OAA4B,CAAC,GAAS;EAC3D,KAAK,OAAO,MAAM,MAAM,OAAO;EAC/B,KAAKE,QAAQ,SAAS,SAAS,IAAI;CACrC;CAEA,KAAK,SAAiB,OAA4B,CAAC,GAAS;EAC1D,KAAK,OAAO,KAAK,MAAM,OAAO;EAC9B,KAAKA,QAAQ,QAAQ,SAAS,IAAI;CACpC;CAEA,KAAK,SAAiB,OAA4B,CAAC,GAAS;EAC1D,KAAK,OAAO,KAAK,MAAM,OAAO;EAC9B,KAAKA,QAAQ,QAAQ,SAAS,IAAI;CACpC;CAEA,MAAM,SAAiB,OAA4B,CAAC,GAAS;EAC3D,KAAK,OAAO,MAAM,MAAM,OAAO;EAC/B,KAAKA,QAAQ,SAAS,SAAS,IAAI;CACrC;CAEA,eAAwB,OAAc,UAA0C;EAC9E,CAAA,GAAA,oBAAA,uBAAA,CAAuB,KAAKF,mBAAmB,SAAS,OAAO,QAAQ;CACzE;AACF"}