{"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":["Version","isBrowser","defaultFormatters"],"mappings":"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"}