{"version":3,"file":"logger.cjs","sources":["../../src/logger.ts"],"sourcesContent":["import { defaultFormatters } from 'src/default-formatters';\nimport { Transport } from '.';\nimport { Version, isBrowser } from './runtime';\n\nconst LOG_LEVEL = 'info';\n\n/**\n * Symbol used to specify properties that should be added to the root of the log event\n * rather than to the fields property.\n *\n * @example\n * const EVENT = Symbol.for('logging.event');\n * logger.info(\"User logged in\", {\n *   userId: 123,\n *   [EVENT]: { traceId: \"abc123\" }\n * });\n */\nexport const EVENT = Symbol.for('logging.event');\n\n/**\n * LogEvent interface representing a log entry.\n * This interface defines the structure of log events processed by the logger.\n */\nexport interface LogEvent extends Record<string, any> {\n  level: string;\n  message: string;\n  fields: any;\n  _time: string;\n  '@app': {\n    [key: FrameworkIdentifier['name']]: FrameworkIdentifier['version'];\n  };\n  source: string;\n}\nexport const LogLevelValue = {\n  debug: 0,\n  info: 1,\n  warn: 2,\n  error: 3,\n  off: 100,\n} as const;\n\nexport const LogLevel = {\n  debug: 'debug',\n  info: 'info',\n  warn: 'warn',\n  error: 'error',\n  off: 'off',\n} as const;\n\nexport type LogLevelValue = (typeof LogLevelValue)[keyof typeof LogLevelValue];\nexport type LogLevel = keyof typeof LogLevelValue;\n\nexport type Formatter<T extends Record<string, any> = LogEvent, U extends Record<string, any> = LogEvent> = (\n  logEvent: T,\n) => U;\n\nexport type FrameworkIdentifier = {\n  name: `${string}-version`;\n  version: string;\n};\n\nexport type LoggerConfig = {\n  args?: Record<string | symbol, any>;\n  transports: [Transport, ...Transport[]];\n  logLevel?: LogLevel;\n  formatters?: Array<Formatter>;\n  overrideDefaultFormatters?: boolean;\n};\n\nexport class Logger {\n  children: Logger[] = [];\n  public logLevel: LogLevelValue = LogLevelValue.debug;\n  public config: LoggerConfig;\n\n  constructor(public initConfig: LoggerConfig) {\n    // check if user passed a log level, if not the default init value will be used as is.\n    if (this.initConfig.logLevel != undefined) {\n      this.logLevel = LogLevelValue[this.initConfig.logLevel];\n    } else if (LOG_LEVEL) {\n      this.logLevel = LogLevelValue[LOG_LEVEL as LogLevel];\n    }\n\n    this.config = { ...initConfig };\n\n    if (!this.config.overrideDefaultFormatters) {\n      this.config.formatters = [...defaultFormatters, ...(this.config.formatters ?? [])];\n    }\n  }\n\n  raw(log: any) {\n    this.config.transports.forEach((transport) => transport.log([log]));\n  }\n\n  /**\n   * Log a debug message\n   * @param message The log message\n   * @param options Log options that can include fields and a special EVENT symbol\n   *\n   * @example\n   * // Add fields to the log event\n   * logger.debug(\"User action\", { userId: 123 });\n   */\n  debug = (message: string, args: Record<string | symbol, any> = {}) => {\n    this.log(LogLevel.debug, message, args);\n  };\n\n  /**\n   * Log an info message\n   * @param message The log message\n   * @param options Log options that can include fields and a special EVENT symbol\n   *\n   * @example\n   * // Add fields to the log event\n   * logger.info(\"User logged in\", { userId: 123 });\n   */\n  info = (message: string, args: Record<string | symbol, any> = {}) => {\n    this.log(LogLevel.info, message, args);\n  };\n\n  /**\n   * Log a warning message\n   * @param message The log message\n   * @param options Log options that can include fields and a special EVENT symbol\n   *\n   * @example\n   * // Add fields to the log event\n   * logger.warn(\"Rate limit approaching\", { requestCount: 950 });\n   */\n  warn = (message: string, args: Record<string | symbol, any> = {}) => {\n    this.log(LogLevel.warn, message, args);\n  };\n\n  /**\n   * Log an error message\n   * @param message The log message\n   * @param options Log options that can include fields and a special EVENT symbol\n   *\n   * @example\n   * // Log an error with stack trace\n   * try {\n   *   // some code that throws\n   * } catch (err) {\n   *   logger.error(\"Operation failed\", err);\n   * }\n   */\n  error = (message: string, args: Record<string | symbol, any> = {}) => {\n    this.log(LogLevel.error, message, args);\n  };\n\n  /**\n   * Create a child logger with additional context fields\n   * @param fields Additional context fields to include in all logs from this logger\n   *\n   * @example\n   * // Create a child logger with additional fields\n   * const childLogger = logger.with({ userId: 123 });\n   */\n  with = (fields: Record<string | symbol, any>) => {\n    const { [EVENT]: argsEventFields, ...argsRest } = this.config.args ?? {};\n    const { [EVENT]: _eventFields, ...rest } = fields;\n\n    const eventFields = { ...(argsEventFields ?? {}), ...(_eventFields ?? {}) };\n\n    const childConfig = { ...this.config, args: { ...argsRest, ...rest, [EVENT]: eventFields } };\n\n    const child = new Logger(childConfig);\n    this.children.push(child);\n    return child;\n  };\n\n  private _transformEvent = (level: LogLevel, message: string, args: Record<string | symbol, any> = {}) => {\n    let rootFields = {};\n    let fields = this.config.args ?? {};\n    if (this.config.args && EVENT in this.config.args) {\n      const { [EVENT]: argsEventFields, ...argsRest } = this.config.args ?? {};\n      rootFields = { ...(argsEventFields ?? {}) };\n      fields = argsRest;\n    }\n\n    const logEvent: LogEvent = {\n      level: LogLevel[level].toString(),\n      message,\n      _time: new Date(Date.now()).toISOString(),\n      fields: fields,\n      '@app': {\n        'axiom-logging-version': Version ?? 'unknown',\n      },\n      source: isBrowser ? 'browser-log' : 'server-log',\n    };\n\n    // Apply root properties from logger config if present\n    if (rootFields && typeof rootFields === 'object') {\n      Object.assign(logEvent, rootFields);\n    }\n\n    // Handle Error objects\n    if (args instanceof Error) {\n      logEvent.fields = {\n        ...logEvent.fields,\n        message: args.message,\n        stack: args.stack,\n        name: args.name,\n      };\n    }\n\n    if (typeof args === 'object' && args !== null) {\n      // Extract root properties before JSON serialization (since symbols are lost in JSON.stringify)\n      const { [EVENT]: rootArgs, ...fieldArgs } = args as Record<string | symbol, any>;\n\n      // Process regular fields\n      const parsedArgs = JSON.parse(JSON.stringify(fieldArgs, jsonFriendlyErrorReplacer));\n\n      // Apply root properties directly to the root of logEvent\n      if (rootArgs && typeof rootArgs === 'object' && rootArgs !== null) {\n        Object.assign(logEvent, rootArgs);\n      }\n\n      // Any remaining properties in options are treated as fields\n      if (Object.keys(parsedArgs).length > 0) {\n        logEvent.fields = { ...logEvent.fields, ...parsedArgs };\n      }\n      // Handle array-like values\n    } else if (Array.isArray(args)) {\n      logEvent.fields = { ...logEvent.fields, args: args };\n    }\n\n    if (this.config.formatters && this.config.formatters.length > 0) {\n      // Apply formatters to the entire logEvent\n      return this.config.formatters.reduce((acc, formatter) => formatter(acc), logEvent);\n    }\n\n    return logEvent;\n  };\n\n  /**\n   * Log a message with the specified level\n   * @param level The log level\n   * @param message The log message\n   * @param options Log options or Error object\n   */\n  log = (level: LogLevel, message: string, args: Record<string | symbol, any> = {}) => {\n    this.config.transports.forEach((transport) => transport.log([this._transformEvent(level, message, args)]));\n  };\n\n  flush = async () => {\n    const promises = [\n      ...this.config.transports.map((transport) => transport.flush()),\n      ...this.children.map((child) => child.flush()),\n    ];\n\n    await Promise.allSettled(promises);\n  };\n}\n\nfunction jsonFriendlyErrorReplacer(_key: string, value: any) {\n  if (value instanceof Error) {\n    return {\n      // Pull all enumerable properties, supporting properties on custom Errors\n      ...value,\n      // Explicitly pull Error's non-enumerable properties\n      name: value.name,\n      message: value.message,\n      stack: value.stack,\n    };\n  }\n\n  return value;\n}\n"],"names":["defaultFormatters","Version","isBrowser"],"mappings":"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"}