github.com/wangyougui/gf/v2@v2.6.5/os/glog/glog_logger_handler.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/wangyougui/gf. 6 7 package glog 8 9 import ( 10 "bytes" 11 "context" 12 "time" 13 14 "github.com/wangyougui/gf/v2/util/gconv" 15 ) 16 17 // Handler is function handler for custom logging content outputs. 18 type Handler func(ctx context.Context, in *HandlerInput) 19 20 // HandlerInput is the input parameter struct for logging Handler. 21 type HandlerInput struct { 22 internalHandlerInfo 23 Logger *Logger // Current Logger object. 24 Buffer *bytes.Buffer // Buffer for logging content outputs. 25 Time time.Time // Logging time, which is the time that logging triggers. 26 TimeFormat string // Formatted time string, like "2016-01-09 12:00:00". 27 Color int // Using color, like COLOR_RED, COLOR_BLUE, etc. Eg: 34 28 Level int // Using level, like LEVEL_INFO, LEVEL_ERRO, etc. Eg: 256 29 LevelFormat string // Formatted level string, like "DEBU", "ERRO", etc. Eg: ERRO 30 CallerFunc string // The source function name that calls logging, only available if F_CALLER_FN set. 31 CallerPath string // The source file path and its line number that calls logging, only available if F_FILE_SHORT or F_FILE_LONG set. 32 CtxStr string // The retrieved context value string from context, only available if Config.CtxKeys configured. 33 TraceId string // Trace id, only available if OpenTelemetry is enabled. 34 Prefix string // Custom prefix string for logging content. 35 Content string // Content is the main logging content without error stack string produced by logger. 36 Values []any // The passed un-formatted values array to logger. 37 Stack string // Stack string produced by logger, only available if Config.StStatus configured. 38 IsAsync bool // IsAsync marks it is in asynchronous logging. 39 } 40 41 type internalHandlerInfo struct { 42 index int // Middleware handling index for internal usage. 43 handlers []Handler // Handler array calling bu index. 44 } 45 46 // defaultHandler is the default handler for package. 47 var defaultHandler Handler 48 49 // doFinalPrint is a handler for logging content printing. 50 // This handler outputs logging content to file/stdout/write if any of them configured. 51 func doFinalPrint(ctx context.Context, in *HandlerInput) { 52 buffer := in.Logger.doFinalPrint(ctx, in) 53 if in.Buffer.Len() == 0 { 54 in.Buffer = buffer 55 } 56 } 57 58 // SetDefaultHandler sets default handler for package. 59 func SetDefaultHandler(handler Handler) { 60 defaultHandler = handler 61 } 62 63 // GetDefaultHandler returns the default handler of package. 64 func GetDefaultHandler() Handler { 65 return defaultHandler 66 } 67 68 // Next calls the next logging handler in middleware way. 69 func (in *HandlerInput) Next(ctx context.Context) { 70 in.index++ 71 if in.index < len(in.handlers) { 72 in.handlers[in.index](ctx, in) 73 } 74 } 75 76 // String returns the logging content formatted by default logging handler. 77 func (in *HandlerInput) String(withColor ...bool) string { 78 formatWithColor := false 79 if len(withColor) > 0 { 80 formatWithColor = withColor[0] 81 } 82 return in.getDefaultBuffer(formatWithColor).String() 83 } 84 85 func (in *HandlerInput) getDefaultBuffer(withColor bool) *bytes.Buffer { 86 buffer := bytes.NewBuffer(nil) 87 if in.Logger.config.HeaderPrint { 88 if in.TimeFormat != "" { 89 buffer.WriteString(in.TimeFormat) 90 } 91 if in.Logger.config.LevelPrint && in.LevelFormat != "" { 92 var levelStr = "[" + in.LevelFormat + "]" 93 if withColor { 94 in.addStringToBuffer(buffer, in.Logger.getColoredStr( 95 in.Logger.getColorByLevel(in.Level), levelStr, 96 )) 97 } else { 98 in.addStringToBuffer(buffer, levelStr) 99 } 100 } 101 } 102 if in.TraceId != "" { 103 in.addStringToBuffer(buffer, "{"+in.TraceId+"}") 104 } 105 if in.CtxStr != "" { 106 in.addStringToBuffer(buffer, "{"+in.CtxStr+"}") 107 } 108 if in.Logger.config.HeaderPrint { 109 if in.Prefix != "" { 110 in.addStringToBuffer(buffer, in.Prefix) 111 } 112 if in.CallerFunc != "" { 113 in.addStringToBuffer(buffer, in.CallerFunc) 114 } 115 if in.CallerPath != "" { 116 in.addStringToBuffer(buffer, in.CallerPath) 117 } 118 } 119 120 if in.Content != "" { 121 in.addStringToBuffer(buffer, in.Content) 122 } 123 124 // Convert values string content. 125 var valueContent string 126 for _, v := range in.Values { 127 valueContent = gconv.String(v) 128 if len(valueContent) == 0 { 129 continue 130 } 131 if buffer.Len() > 0 { 132 if buffer.Bytes()[buffer.Len()-1] == '\n' { 133 // Remove one blank line(\n\n). 134 if valueContent[0] == '\n' { 135 valueContent = valueContent[1:] 136 } 137 buffer.WriteString(valueContent) 138 } else { 139 buffer.WriteString(" " + valueContent) 140 } 141 } else { 142 buffer.WriteString(valueContent) 143 } 144 } 145 146 if in.Stack != "" { 147 in.addStringToBuffer(buffer, "\nStack:\n"+in.Stack) 148 } 149 // avoid a single space at the end of a line. 150 buffer.WriteString("\n") 151 return buffer 152 } 153 154 func (in *HandlerInput) getRealBuffer(withColor bool) *bytes.Buffer { 155 if in.Buffer.Len() > 0 { 156 return in.Buffer 157 } 158 return in.getDefaultBuffer(withColor) 159 } 160 161 func (in *HandlerInput) addStringToBuffer(buffer *bytes.Buffer, strings ...string) { 162 for _, s := range strings { 163 if buffer.Len() > 0 { 164 buffer.WriteByte(' ') 165 } 166 buffer.WriteString(s) 167 } 168 }