github.com/ethereum-optimism/optimism@v1.7.2/packages/common-ts/src/common/logger.ts (about)

     1  import pino, { LoggerOptions as PinoLoggerOptions } from 'pino'
     2  import pinoms, { Streams } from 'pino-multi-stream'
     3  import { createWriteStream } from 'pino-sentry'
     4  import { NodeOptions } from '@sentry/node'
     5  
     6  export const logLevels = [
     7    'trace',
     8    'debug',
     9    'info',
    10    'warn',
    11    'error',
    12    'fatal',
    13  ] as const
    14  export type LogLevel = (typeof logLevels)[number]
    15  
    16  export interface LoggerOptions {
    17    name: string
    18    level?: LogLevel
    19    sentryOptions?: NodeOptions
    20    streams?: Streams
    21  }
    22  
    23  /**
    24   * Temporary wrapper class to maintain earlier module interface.
    25   */
    26  export class Logger {
    27    options: LoggerOptions
    28    inner: pino.Logger
    29  
    30    constructor(options: LoggerOptions) {
    31      this.options = options
    32  
    33      const loggerOptions: PinoLoggerOptions = {
    34        name: options.name,
    35  
    36        level: options.level || 'debug',
    37  
    38        // Remove pid and hostname considering production runs inside docker
    39        base: null,
    40      }
    41  
    42      let loggerStreams: Streams = [{ stream: process.stdout }]
    43      if (options.sentryOptions) {
    44        loggerStreams.push({
    45          level: 'error',
    46          stream: createWriteStream({
    47            ...options.sentryOptions,
    48            stackAttributeKey: 'err',
    49          }),
    50        })
    51      }
    52      if (options.streams) {
    53        loggerStreams = loggerStreams.concat(options.streams)
    54      }
    55  
    56      this.inner = pino(loggerOptions, pinoms.multistream(loggerStreams))
    57    }
    58  
    59    child(bindings: pino.Bindings): Logger {
    60      const inner = this.inner.child(bindings)
    61      const logger = new Logger(this.options)
    62      logger.inner = inner
    63      return logger
    64    }
    65  
    66    trace(msg: string, o?: object, ...args: any[]): void {
    67      if (o) {
    68        this.inner.trace(o, msg, ...args)
    69      } else {
    70        this.inner.trace(msg, ...args)
    71      }
    72    }
    73  
    74    debug(msg: string, o?: object, ...args: any[]): void {
    75      if (o) {
    76        this.inner.debug(o, msg, ...args)
    77      } else {
    78        this.inner.debug(msg, ...args)
    79      }
    80    }
    81  
    82    info(msg: string, o?: object, ...args: any[]): void {
    83      if (o) {
    84        this.inner.info(o, msg, ...args)
    85      } else {
    86        this.inner.info(msg, ...args)
    87      }
    88    }
    89  
    90    warn(msg: string, o?: object, ...args: any[]): void {
    91      if (o) {
    92        this.inner.warn(o, msg, ...args)
    93      } else {
    94        this.inner.warn(msg, ...args)
    95      }
    96    }
    97  
    98    warning(msg: string, o?: object, ...args: any[]): void {
    99      if (o) {
   100        this.inner.warn(o, msg, ...args)
   101      } else {
   102        this.inner.warn(msg, ...args)
   103      }
   104    }
   105  
   106    error(msg: string, o?: object, ...args: any[]): void {
   107      if (o) {
   108        // Formatting error log for Sentry
   109        const context = {
   110          extra: { ...o },
   111        }
   112        this.inner.error(context, msg, ...args)
   113      } else {
   114        this.inner.error(msg, ...args)
   115      }
   116    }
   117  
   118    fatal(msg: string, o?: object, ...args: any[]): void {
   119      if (o) {
   120        const context = {
   121          extra: { ...o },
   122        }
   123        this.inner.fatal(context, msg, ...args)
   124      } else {
   125        this.inner.fatal(msg, ...args)
   126      }
   127    }
   128  }