github.com/MetalBlockchain/metalgo@v1.11.9/utils/logging/format.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package logging 5 6 import ( 7 "errors" 8 "fmt" 9 "strings" 10 11 "go.uber.org/zap/zapcore" 12 "golang.org/x/term" 13 ) 14 15 // Format modes available 16 const ( 17 Plain Format = iota 18 Colors 19 JSON 20 21 termTimeFormat = "[01-02|15:04:05.000]" 22 ) 23 24 var ( 25 errUnknownFormat = errors.New("unknown format") 26 27 defaultEncoderConfig = zapcore.EncoderConfig{ 28 TimeKey: "timestamp", 29 LevelKey: "level", 30 NameKey: "logger", 31 CallerKey: "caller", 32 MessageKey: "msg", 33 StacktraceKey: "stacktrace", 34 EncodeDuration: zapcore.StringDurationEncoder, 35 EncodeCaller: zapcore.ShortCallerEncoder, 36 } 37 jsonEncoderConfig zapcore.EncoderConfig 38 39 termTimeEncoder = zapcore.TimeEncoderOfLayout(termTimeFormat) 40 ) 41 42 func init() { 43 jsonEncoderConfig = defaultEncoderConfig 44 jsonEncoderConfig.EncodeLevel = jsonLevelEncoder 45 jsonEncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder 46 jsonEncoderConfig.EncodeDuration = zapcore.NanosDurationEncoder 47 } 48 49 // Highlight mode to apply to displayed logs 50 type Format int 51 52 // ToFormat chooses a highlighting mode 53 func ToFormat(h string, fd uintptr) (Format, error) { 54 switch strings.ToUpper(h) { 55 case "PLAIN": 56 return Plain, nil 57 case "COLORS": 58 return Colors, nil 59 case "JSON": 60 return JSON, nil 61 case "AUTO": 62 if !term.IsTerminal(int(fd)) { 63 return Plain, nil 64 } 65 return Colors, nil 66 default: 67 return Plain, fmt.Errorf("unknown format mode: %s", h) 68 } 69 } 70 71 func (f Format) MarshalJSON() ([]byte, error) { 72 switch f { 73 case Plain: 74 return []byte(`"PLAIN"`), nil 75 case Colors: 76 return []byte(`"COLORS"`), nil 77 case JSON: 78 return []byte(`"JSON"`), nil 79 default: 80 return nil, errUnknownFormat 81 } 82 } 83 84 func (f Format) WrapPrefix(prefix string) string { 85 if prefix == "" || f == JSON { 86 return prefix 87 } 88 return fmt.Sprintf("<%s>", prefix) 89 } 90 91 func (f Format) ConsoleEncoder() zapcore.Encoder { 92 switch f { 93 case Colors: 94 return zapcore.NewConsoleEncoder(newTermEncoderConfig(consoleColorLevelEncoder)) 95 case JSON: 96 return zapcore.NewJSONEncoder(jsonEncoderConfig) 97 default: 98 return zapcore.NewConsoleEncoder(newTermEncoderConfig(levelEncoder)) 99 } 100 } 101 102 func (f Format) FileEncoder() zapcore.Encoder { 103 switch f { 104 case JSON: 105 return zapcore.NewJSONEncoder(jsonEncoderConfig) 106 default: 107 return zapcore.NewConsoleEncoder(newTermEncoderConfig(levelEncoder)) 108 } 109 } 110 111 func newTermEncoderConfig(lvlEncoder zapcore.LevelEncoder) zapcore.EncoderConfig { 112 config := defaultEncoderConfig 113 config.EncodeLevel = lvlEncoder 114 config.EncodeTime = termTimeEncoder 115 config.ConsoleSeparator = " " 116 return config 117 } 118 119 func levelEncoder(l zapcore.Level, enc zapcore.PrimitiveArrayEncoder) { 120 enc.AppendString(Level(l).String()) 121 } 122 123 func jsonLevelEncoder(l zapcore.Level, enc zapcore.PrimitiveArrayEncoder) { 124 enc.AppendString(Level(l).LowerString()) 125 } 126 127 func consoleColorLevelEncoder(l zapcore.Level, enc zapcore.PrimitiveArrayEncoder) { 128 s, ok := levelToCapitalColorString[Level(l)] 129 if !ok { 130 s = unknownLevelColor.Wrap(l.String()) 131 } 132 enc.AppendString(s) 133 }