github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/log/logger.go (about)

     1  package log
     2  
     3  import (
     4  	"context"
     5  	"log/slog"
     6  	"math"
     7  	"os"
     8  	"runtime"
     9  	"time"
    10  )
    11  
    12  const errorKey = "LOG_ERROR"
    13  
    14  const (
    15  	legacyLevelCrit = iota
    16  	legacyLevelError
    17  	legacyLevelWarn
    18  	legacyLevelInfo
    19  	legacyLevelDebug
    20  	legacyLevelTrace
    21  )
    22  
    23  const (
    24  	levelMaxVerbosity slog.Level = math.MinInt
    25  	LevelTrace        slog.Level = -8
    26  	LevelDebug                   = slog.LevelDebug
    27  	LevelInfo                    = slog.LevelInfo
    28  	LevelWarn                    = slog.LevelWarn
    29  	LevelError                   = slog.LevelError
    30  	LevelCrit         slog.Level = 12
    31  
    32  	// for backward-compatibility
    33  	LvlTrace = LevelTrace
    34  	LvlInfo  = LevelInfo
    35  	LvlDebug = LevelDebug
    36  )
    37  
    38  // convert from old Geth verbosity level constants
    39  // to levels defined by slog
    40  func FromLegacyLevel(lvl int) slog.Level {
    41  	switch lvl {
    42  	case legacyLevelCrit:
    43  		return LevelCrit
    44  	case legacyLevelError:
    45  		return slog.LevelError
    46  	case legacyLevelWarn:
    47  		return slog.LevelWarn
    48  	case legacyLevelInfo:
    49  		return slog.LevelInfo
    50  	case legacyLevelDebug:
    51  		return slog.LevelDebug
    52  	case legacyLevelTrace:
    53  		return LevelTrace
    54  	default:
    55  		break
    56  	}
    57  
    58  	// TODO: should we allow use of custom levels or force them to match existing max/min if they fall outside the range as I am doing here?
    59  	if lvl > legacyLevelTrace {
    60  		return LevelTrace
    61  	}
    62  	return LevelCrit
    63  }
    64  
    65  // LevelAlignedString returns a 5-character string containing the name of a Lvl.
    66  func LevelAlignedString(l slog.Level) string {
    67  	switch l {
    68  	case LevelTrace:
    69  		return "TRACE"
    70  	case slog.LevelDebug:
    71  		return "DEBUG"
    72  	case slog.LevelInfo:
    73  		return "INFO "
    74  	case slog.LevelWarn:
    75  		return "WARN "
    76  	case slog.LevelError:
    77  		return "ERROR"
    78  	case LevelCrit:
    79  		return "CRIT "
    80  	default:
    81  		return "unknown level"
    82  	}
    83  }
    84  
    85  // LevelString returns a string containing the name of a Lvl.
    86  func LevelString(l slog.Level) string {
    87  	switch l {
    88  	case LevelTrace:
    89  		return "trace"
    90  	case slog.LevelDebug:
    91  		return "debug"
    92  	case slog.LevelInfo:
    93  		return "info"
    94  	case slog.LevelWarn:
    95  		return "warn"
    96  	case slog.LevelError:
    97  		return "error"
    98  	case LevelCrit:
    99  		return "crit"
   100  	default:
   101  		return "unknown"
   102  	}
   103  }
   104  
   105  // A Logger writes key/value pairs to a Handler
   106  type Logger interface {
   107  	// With returns a new Logger that has this logger's attributes plus the given attributes
   108  	With(ctx ...interface{}) Logger
   109  
   110  	// With returns a new Logger that has this logger's attributes plus the given attributes. Identical to 'With'.
   111  	New(ctx ...interface{}) Logger
   112  
   113  	// Log logs a message at the specified level with context key/value pairs
   114  	Log(level slog.Level, msg string, ctx ...interface{})
   115  
   116  	// Trace log a message at the trace level with context key/value pairs
   117  	Trace(msg string, ctx ...interface{})
   118  
   119  	// Debug logs a message at the debug level with context key/value pairs
   120  	Debug(msg string, ctx ...interface{})
   121  
   122  	// Info logs a message at the info level with context key/value pairs
   123  	Info(msg string, ctx ...interface{})
   124  
   125  	// Warn logs a message at the warn level with context key/value pairs
   126  	Warn(msg string, ctx ...interface{})
   127  
   128  	// Error logs a message at the error level with context key/value pairs
   129  	Error(msg string, ctx ...interface{})
   130  
   131  	// Crit logs a message at the crit level with context key/value pairs, and exits
   132  	Crit(msg string, ctx ...interface{})
   133  
   134  	// Write logs a message at the specified level
   135  	Write(level slog.Level, msg string, attrs ...any)
   136  
   137  	// Enabled reports whether l emits log records at the given context and level.
   138  	Enabled(ctx context.Context, level slog.Level) bool
   139  
   140  	// Handler returns the underlying handler of the inner logger.
   141  	Handler() slog.Handler
   142  }
   143  
   144  type logger struct {
   145  	inner *slog.Logger
   146  }
   147  
   148  // NewLogger returns a logger with the specified handler set
   149  func NewLogger(h slog.Handler) Logger {
   150  	return &logger{
   151  		slog.New(h),
   152  	}
   153  }
   154  
   155  func (l *logger) Handler() slog.Handler {
   156  	return l.inner.Handler()
   157  }
   158  
   159  // Write logs a message at the specified level:
   160  func (l *logger) Write(level slog.Level, msg string, attrs ...any) {
   161  	if !l.inner.Enabled(context.Background(), level) {
   162  		return
   163  	}
   164  
   165  	var pcs [1]uintptr
   166  	runtime.Callers(3, pcs[:])
   167  
   168  	if len(attrs)%2 != 0 {
   169  		attrs = append(attrs, nil, errorKey, "Normalized odd number of arguments by adding nil")
   170  	}
   171  	r := slog.NewRecord(time.Now(), level, msg, pcs[0])
   172  	r.Add(attrs...)
   173  	l.inner.Handler().Handle(context.Background(), r)
   174  }
   175  
   176  func (l *logger) Log(level slog.Level, msg string, attrs ...any) {
   177  	l.Write(level, msg, attrs...)
   178  }
   179  
   180  func (l *logger) With(ctx ...interface{}) Logger {
   181  	return &logger{l.inner.With(ctx...)}
   182  }
   183  
   184  func (l *logger) New(ctx ...interface{}) Logger {
   185  	return l.With(ctx...)
   186  }
   187  
   188  // Enabled reports whether l emits log records at the given context and level.
   189  func (l *logger) Enabled(ctx context.Context, level slog.Level) bool {
   190  	return l.inner.Enabled(ctx, level)
   191  }
   192  
   193  func (l *logger) Trace(msg string, ctx ...interface{}) {
   194  	l.Write(LevelTrace, msg, ctx...)
   195  }
   196  
   197  func (l *logger) Debug(msg string, ctx ...interface{}) {
   198  	l.Write(slog.LevelDebug, msg, ctx...)
   199  }
   200  
   201  func (l *logger) Info(msg string, ctx ...interface{}) {
   202  	l.Write(slog.LevelInfo, msg, ctx...)
   203  }
   204  
   205  func (l *logger) Warn(msg string, ctx ...any) {
   206  	l.Write(slog.LevelWarn, msg, ctx...)
   207  }
   208  
   209  func (l *logger) Error(msg string, ctx ...interface{}) {
   210  	l.Write(slog.LevelError, msg, ctx...)
   211  }
   212  
   213  func (l *logger) Crit(msg string, ctx ...interface{}) {
   214  	l.Write(LevelCrit, msg, ctx...)
   215  	os.Exit(1)
   216  }