gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

json_formatter.go (3389B)


      1 package logrus
      2 
      3 import (
      4 	"bytes"
      5 	"encoding/json"
      6 	"fmt"
      7 	"runtime"
      8 )
      9 
     10 type fieldKey string
     11 
     12 // FieldMap allows customization of the key names for default fields.
     13 type FieldMap map[fieldKey]string
     14 
     15 func (f FieldMap) resolve(key fieldKey) string {
     16 	if k, ok := f[key]; ok {
     17 		return k
     18 	}
     19 
     20 	return string(key)
     21 }
     22 
     23 // JSONFormatter formats logs into parsable json
     24 type JSONFormatter struct {
     25 	// TimestampFormat sets the format used for marshaling timestamps.
     26 	// The format to use is the same than for time.Format or time.Parse from the standard
     27 	// library.
     28 	// The standard Library already provides a set of predefined format.
     29 	TimestampFormat string
     30 
     31 	// DisableTimestamp allows disabling automatic timestamps in output
     32 	DisableTimestamp bool
     33 
     34 	// DisableHTMLEscape allows disabling html escaping in output
     35 	DisableHTMLEscape bool
     36 
     37 	// DataKey allows users to put all the log entry parameters into a nested dictionary at a given key.
     38 	DataKey string
     39 
     40 	// FieldMap allows users to customize the names of keys for default fields.
     41 	// As an example:
     42 	// formatter := &JSONFormatter{
     43 	//   	FieldMap: FieldMap{
     44 	// 		 FieldKeyTime:  "@timestamp",
     45 	// 		 FieldKeyLevel: "@level",
     46 	// 		 FieldKeyMsg:   "@message",
     47 	// 		 FieldKeyFunc:  "@caller",
     48 	//    },
     49 	// }
     50 	FieldMap FieldMap
     51 
     52 	// CallerPrettyfier can be set by the user to modify the content
     53 	// of the function and file keys in the json data when ReportCaller is
     54 	// activated. If any of the returned value is the empty string the
     55 	// corresponding key will be removed from json fields.
     56 	CallerPrettyfier func(*runtime.Frame) (function string, file string)
     57 
     58 	// PrettyPrint will indent all json logs
     59 	PrettyPrint bool
     60 }
     61 
     62 // Format renders a single log entry
     63 func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
     64 	data := make(Fields, len(entry.Data)+4)
     65 	for k, v := range entry.Data {
     66 		switch v := v.(type) {
     67 		case error:
     68 			// Otherwise errors are ignored by `encoding/json`
     69 			// https://github.com/sirupsen/logrus/issues/137
     70 			data[k] = v.Error()
     71 		default:
     72 			data[k] = v
     73 		}
     74 	}
     75 
     76 	if f.DataKey != "" {
     77 		newData := make(Fields, 4)
     78 		newData[f.DataKey] = data
     79 		data = newData
     80 	}
     81 
     82 	prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
     83 
     84 	timestampFormat := f.TimestampFormat
     85 	if timestampFormat == "" {
     86 		timestampFormat = defaultTimestampFormat
     87 	}
     88 
     89 	if entry.err != "" {
     90 		data[f.FieldMap.resolve(FieldKeyLogrusError)] = entry.err
     91 	}
     92 	if !f.DisableTimestamp {
     93 		data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat)
     94 	}
     95 	data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
     96 	data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
     97 	if entry.HasCaller() {
     98 		funcVal := entry.Caller.Function
     99 		fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
    100 		if f.CallerPrettyfier != nil {
    101 			funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
    102 		}
    103 		if funcVal != "" {
    104 			data[f.FieldMap.resolve(FieldKeyFunc)] = funcVal
    105 		}
    106 		if fileVal != "" {
    107 			data[f.FieldMap.resolve(FieldKeyFile)] = fileVal
    108 		}
    109 	}
    110 
    111 	var b *bytes.Buffer
    112 	if entry.Buffer != nil {
    113 		b = entry.Buffer
    114 	} else {
    115 		b = &bytes.Buffer{}
    116 	}
    117 
    118 	encoder := json.NewEncoder(b)
    119 	encoder.SetEscapeHTML(!f.DisableHTMLEscape)
    120 	if f.PrettyPrint {
    121 		encoder.SetIndent("", "  ")
    122 	}
    123 	if err := encoder.Encode(data); err != nil {
    124 		return nil, fmt.Errorf("failed to marshal fields to JSON, %w", err)
    125 	}
    126 
    127 	return b.Bytes(), nil
    128 }