...

Source file src/github.com/sirupsen/logrus/json_formatter.go

Documentation: github.com/sirupsen/logrus

     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  }
   129  

View as plain text