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  }