github.com/searKing/golang/go@v1.2.117/log/slog/glog_handler.go (about) 1 // Copyright 2023 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package slog 6 7 import ( 8 "context" 9 "io" 10 "log/slog" 11 "sync" 12 ) 13 14 var _ slog.Handler = (*GlogHandler)(nil) 15 16 type GlogHandler struct { 17 *commonHandler 18 } 19 20 // NewGlogHandler creates a GlogHandler that writes to w, 21 // using the given options. 22 // If opts is nil, the default options are used. 23 // # LOG LINE PREFIX FORMAT 24 // 25 // Log lines have this form: 26 // 27 // Lyyyymmdd hh:mm:ss.uuuuuu threadid file:line] msg... 28 // 29 // where the fields are defined as follows: 30 // 31 // L A single character, representing the log level 32 // (eg 'I' for INFO) 33 // yyyy The year 34 // mm The month (zero padded; ie May is '05') 35 // dd The day (zero padded) 36 // hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds 37 // threadid The space-padded thread ID as returned by GetTID() 38 // (this matches the PID on Linux) 39 // file The file name 40 // line The line number 41 // msg The user-supplied message 42 // 43 // Example: 44 // 45 // I1103 11:57:31.739339 24395 google.cc:2341] Command line: ./some_prog 46 // I1103 11:57:31.739403 24395 google.cc:2342] Process id 24395 47 func NewGlogHandler(w io.Writer, opts *slog.HandlerOptions) *GlogHandler { 48 if opts == nil { 49 opts = &slog.HandlerOptions{ 50 AddSource: true, 51 } 52 } 53 return &GlogHandler{ 54 &commonHandler{ 55 ReplaceLevelString: func(l slog.Level) string { 56 switch { 57 case l < slog.LevelInfo: 58 return "D" 59 case l < slog.LevelWarn: 60 return "I" 61 case l < slog.LevelError: 62 return "W" 63 default: 64 return "E" 65 } 66 }, 67 opts: *opts, 68 AttrSep: ", ", 69 DisableQuote: true, 70 SourcePrettier: ShortSource, 71 sharedVar: &sharedVar{once: &sync.Once{}}, 72 mu: &sync.Mutex{}, 73 w: w, 74 }, 75 } 76 } 77 78 // NewGlogHumanHandler creates a human-readable GlogHandler that writes to w, 79 // using the given options. 80 // If opts is nil, the default options are used. 81 // # LOG LINE PREFIX FORMAT 82 // 83 // Log lines have this form: 84 // 85 // [LLLLL] [yyyymmdd hh:mm:ss.uuuuuu] [threadid] [file:line(func)] msg... 86 // 87 // where the fields are defined as follows: 88 // 89 // LLLLL Five characters, representing the log level 90 // (eg 'INFO ' for INFO) 91 // yyyy The year 92 // mm The month (zero padded; ie May is '05') 93 // dd The day (zero padded) 94 // hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds 95 // threadid The space-padded thread ID as returned by GetTID() 96 // (this matches the PID on Linux) 97 // file The file name 98 // line The line number 99 // func The func name 100 // msg The user-supplied message 101 // 102 // Example: 103 // 104 // [INFO ] [20081103 11:57:31.739339] [24395] [google.cc:2341](main) Command line: ./some_prog 105 // [INFO ] [20081103 11:57:31.739403] [24395] [google.cc:2342](main) Process id 24395 106 func NewGlogHumanHandler(w io.Writer, opts *slog.HandlerOptions) *GlogHandler { 107 if opts == nil { 108 opts = &slog.HandlerOptions{ 109 AddSource: true, 110 } 111 } 112 return &GlogHandler{ 113 &commonHandler{ 114 opts: *opts, 115 AttrSep: ", ", 116 DisableQuote: true, 117 PadLevelText: true, 118 HumanReadable: true, 119 SourcePrettier: ShortSource, 120 WithFuncName: true, 121 sharedVar: &sharedVar{once: &sync.Once{}}, 122 mu: &sync.Mutex{}, 123 w: w, 124 }, 125 } 126 } 127 128 // Enabled reports whether the handler handles records at the given level. 129 // The handler ignores records whose level is lower. 130 func (h *GlogHandler) Enabled(_ context.Context, level slog.Level) bool { 131 return h.commonHandler.enabled(level) 132 } 133 134 // WithAttrs returns a new GlogHandler whose attributes consists 135 // of h's attributes followed by attrs. 136 func (h *GlogHandler) WithAttrs(attrs []slog.Attr) slog.Handler { 137 return &GlogHandler{commonHandler: h.commonHandler.withAttrs(attrs)} 138 } 139 140 func (h *GlogHandler) WithGroup(name string) slog.Handler { 141 return &GlogHandler{commonHandler: h.commonHandler.withGroup(name)} 142 } 143 144 // Handle formats its argument Record as a JSON object on a single line. 145 // 146 // If the Record's time is zero, the time is omitted. 147 // Otherwise, the key is "time" 148 // and the value is output as with GlogDate. 149 // 150 // If the Record's level is zero, the level is omitted. 151 // Otherwise, the key is "level" 152 // and the value of [Level.String] is output. 153 // 154 // If the AddSource option is set and source information is available, 155 // the key is "source", and the value is a record of type [Source]. 156 // 157 // The message's key is "msg". 158 // 159 // To modify these or other attributes, or remove them from the output, use 160 // [HandlerOptions.ReplaceAttr]. 161 // 162 // Values are formatted as with an [encoding/json.Encoder] with SetEscapeHTML(false), 163 // with two exceptions. 164 // 165 // First, an Attr whose Value is of type error is formatted as a string, by 166 // calling its Error method. Only errors in Attrs receive this special treatment, 167 // not errors embedded in structs, slices, maps or other data structures that 168 // are processed by the encoding/json package. 169 // 170 // Second, an encoding failure does not cause Handle to return an error. 171 // Instead, the error message is formatted as a string. 172 // 173 // Each call to Handle results in a single serialized call to io.Writer.Write. 174 // 175 // Header formats a log header as defined by the C++ implementation. 176 // It returns a buffer containing the formatted header and the user's file and line number. 177 // The depth specifies how many stack frames above lives the source line to be identified in the log message. 178 // 179 // # LOG LINE PREFIX FORMAT 180 // 181 // Log lines have this form: 182 // 183 // Lyyyymmdd hh:mm:ss.uuuuuu threadid file:line] msg... 184 // 185 // where the fields are defined as follows: 186 // 187 // L A single character, representing the log level 188 // (eg 'I' for INFO) 189 // yyyy The year 190 // mm The month (zero padded; ie May is '05') 191 // dd The day (zero padded) 192 // hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds 193 // threadid The space-padded thread ID as returned by GetTID() 194 // (this matches the PID on Linux) 195 // file The file name 196 // line The line number 197 // msg The user-supplied message 198 // 199 // Example: 200 // 201 // I1103 11:57:31.739339 24395 google.cc:2341] Command line: ./some_prog 202 // I1103 11:57:31.739403 24395 google.cc:2342] Process id 24395 203 // 204 // NOTE: although the microseconds are useful for comparing events on 205 // a single machine, clocks on different machines may not be well 206 // synchronized. Hence, use caution when comparing the low bits of 207 // timestamps from different machines. 208 func (h *GlogHandler) Handle(_ context.Context, r slog.Record) error { 209 return h.commonHandler.handle(r) 210 }