gitee.com/hongliu9527/go-tools@v0.0.8/logger/formatter.go (about)

     1  /*
     2   * @Author: hongliu
     3   * @Date: 2022-04-26 09:39:39
     4   * @LastEditors: hongliu
     5   * @LastEditTime: 2022-04-26 09:42:51
     6   * @FilePath: \go-tools\logger\formatter.go
     7   * @Description:
     8   *
     9   * Copyright (c) 2022 by 洪流, All Rights Reserved.
    10   */
    11  
    12  package logger
    13  
    14  import (
    15  	"bytes"
    16  	"fmt"
    17  	"sort"
    18  	"strings"
    19  	"time"
    20  
    21  	"github.com/sirupsen/logrus"
    22  )
    23  
    24  // 对应终端字体颜色
    25  const (
    26  	colorRed    = 31
    27  	colorGreen  = 32
    28  	colorYellow = 33
    29  	colorBlue   = 36
    30  )
    31  
    32  // getColorByLevel 定义不同日志等级颜色
    33  func getColorByLevel(level logrus.Level) int {
    34  	switch level {
    35  	case logrus.DebugLevel:
    36  		return colorGreen
    37  	case logrus.WarnLevel:
    38  		return colorYellow
    39  	case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel:
    40  		return colorRed
    41  	default:
    42  		return colorBlue
    43  	}
    44  }
    45  
    46  // Formatter 自定义格式控制选项
    47  type Formatter struct {
    48  	FieldsOrder     []string // default: fields sorted alphabetically
    49  	TimestampFormat string   // default: time.StampMilli = "Jan _2 15:04:05.000"
    50  	HideKeys        bool     // show [fieldValue] instead of [fieldKey:fieldValue]
    51  	NoColors        bool     // disable colors
    52  	NoFieldsColors  bool     // color only level, default is level + fields
    53  	ShowFullLevel   bool     // true to show full level [WARNING] instead [WARN]
    54  	TrimMessages    bool     // true to trim whitespace on messages
    55  }
    56  
    57  // Format 自定义格式函数
    58  func (f *Formatter) Format(entry *logrus.Entry) ([]byte, error) {
    59  	b := &bytes.Buffer{}
    60  
    61  	// 设置时间字符串格式
    62  	timestampFormat := f.TimestampFormat
    63  	if timestampFormat == "" {
    64  		timestampFormat = time.RFC3339
    65  	}
    66  
    67  	// 按照日志等级填充ASC-II颜色特殊符号
    68  	levelColor := getColorByLevel(entry.Level)
    69  	level := strings.ToUpper(entry.Level.String())
    70  	if !f.NoColors {
    71  		fmt.Fprintf(b, "\x1b[%dm", levelColor)
    72  	}
    73  
    74  	// 填充日志等级,使用"[]"包裹
    75  	b.WriteString(" [")
    76  	if f.ShowFullLevel {
    77  		b.WriteString(level)
    78  	} else {
    79  		b.WriteString(level[:4])
    80  	}
    81  	b.WriteString("] ")
    82  
    83  	if !f.NoColors && f.NoFieldsColors {
    84  		b.WriteString("\x1b[0m")
    85  	}
    86  
    87  	// 填充时间格式字符串,使用"[]"包裹
    88  	b.WriteString("[")
    89  	b.WriteString(entry.Time.Format(timestampFormat))
    90  	b.WriteString("] ")
    91  
    92  	// 填充消息字段,用于结构化日志
    93  	if f.FieldsOrder == nil {
    94  		f.writeFields(b, entry)
    95  	} else {
    96  		f.writeOrderedFields(b, entry)
    97  	}
    98  
    99  	// 填充日志内容
   100  	if f.TrimMessages {
   101  		b.WriteString(strings.TrimSpace(entry.Message))
   102  	} else {
   103  		b.WriteString(entry.Message)
   104  	}
   105  	b.WriteByte('\n')
   106  
   107  	if !f.NoColors && !f.NoFieldsColors {
   108  		b.WriteString("\x1b[0m")
   109  	}
   110  
   111  	return b.Bytes(), nil
   112  }
   113  
   114  // writeFields 写入每个日志字段
   115  func (f *Formatter) writeFields(b *bytes.Buffer, entry *logrus.Entry) {
   116  	if len(entry.Data) != 0 {
   117  		fields := make([]string, 0, len(entry.Data))
   118  		for field := range entry.Data {
   119  			fields = append(fields, field)
   120  		}
   121  
   122  		sort.Strings(fields)
   123  
   124  		for _, field := range fields {
   125  			f.writeField(b, entry, field)
   126  		}
   127  	}
   128  }
   129  
   130  // writeOrderedFields 按顺序写入日志字段
   131  func (f *Formatter) writeOrderedFields(b *bytes.Buffer, entry *logrus.Entry) {
   132  	length := len(entry.Data)
   133  	foundFieldsMap := map[string]bool{}
   134  	for _, field := range f.FieldsOrder {
   135  		if _, ok := entry.Data[field]; ok {
   136  			foundFieldsMap[field] = true
   137  			length--
   138  			f.writeField(b, entry, field)
   139  		}
   140  	}
   141  
   142  	if length > 0 {
   143  		notFoundFields := make([]string, 0, length)
   144  		for field := range entry.Data {
   145  			if foundFieldsMap[field] == false {
   146  				notFoundFields = append(notFoundFields, field)
   147  			}
   148  		}
   149  
   150  		sort.Strings(notFoundFields)
   151  
   152  		for _, field := range notFoundFields {
   153  			f.writeField(b, entry, field)
   154  		}
   155  	}
   156  }
   157  
   158  func (f *Formatter) writeField(b *bytes.Buffer, entry *logrus.Entry, field string) {
   159  	if f.HideKeys {
   160  		fmt.Fprintf(b, "[%v] ", entry.Data[field])
   161  	} else {
   162  		fmt.Fprintf(b, "[%s:%v] ", field, entry.Data[field])
   163  	}
   164  }