You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			129 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
			
		
		
	
	
			129 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
| package logrus
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"encoding/json"
 | |
| 	"fmt"
 | |
| 	"runtime"
 | |
| )
 | |
| 
 | |
| type fieldKey string
 | |
| 
 | |
| // FieldMap allows customization of the key names for default fields.
 | |
| type FieldMap map[fieldKey]string
 | |
| 
 | |
| func (f FieldMap) resolve(key fieldKey) string {
 | |
| 	if k, ok := f[key]; ok {
 | |
| 		return k
 | |
| 	}
 | |
| 
 | |
| 	return string(key)
 | |
| }
 | |
| 
 | |
| // JSONFormatter formats logs into parsable json
 | |
| type JSONFormatter struct {
 | |
| 	// TimestampFormat sets the format used for marshaling timestamps.
 | |
| 	// The format to use is the same than for time.Format or time.Parse from the standard
 | |
| 	// library.
 | |
| 	// The standard Library already provides a set of predefined format.
 | |
| 	TimestampFormat string
 | |
| 
 | |
| 	// DisableTimestamp allows disabling automatic timestamps in output
 | |
| 	DisableTimestamp bool
 | |
| 
 | |
| 	// DisableHTMLEscape allows disabling html escaping in output
 | |
| 	DisableHTMLEscape bool
 | |
| 
 | |
| 	// DataKey allows users to put all the log entry parameters into a nested dictionary at a given key.
 | |
| 	DataKey string
 | |
| 
 | |
| 	// FieldMap allows users to customize the names of keys for default fields.
 | |
| 	// As an example:
 | |
| 	// formatter := &JSONFormatter{
 | |
| 	//   	FieldMap: FieldMap{
 | |
| 	// 		 FieldKeyTime:  "@timestamp",
 | |
| 	// 		 FieldKeyLevel: "@level",
 | |
| 	// 		 FieldKeyMsg:   "@message",
 | |
| 	// 		 FieldKeyFunc:  "@caller",
 | |
| 	//    },
 | |
| 	// }
 | |
| 	FieldMap FieldMap
 | |
| 
 | |
| 	// CallerPrettyfier can be set by the user to modify the content
 | |
| 	// of the function and file keys in the json data when ReportCaller is
 | |
| 	// activated. If any of the returned value is the empty string the
 | |
| 	// corresponding key will be removed from json fields.
 | |
| 	CallerPrettyfier func(*runtime.Frame) (function string, file string)
 | |
| 
 | |
| 	// PrettyPrint will indent all json logs
 | |
| 	PrettyPrint bool
 | |
| }
 | |
| 
 | |
| // Format renders a single log entry
 | |
| func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
 | |
| 	data := make(Fields, len(entry.Data)+4)
 | |
| 	for k, v := range entry.Data {
 | |
| 		switch v := v.(type) {
 | |
| 		case error:
 | |
| 			// Otherwise errors are ignored by `encoding/json`
 | |
| 			// https://github.com/sirupsen/logrus/issues/137
 | |
| 			data[k] = v.Error()
 | |
| 		default:
 | |
| 			data[k] = v
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if f.DataKey != "" {
 | |
| 		newData := make(Fields, 4)
 | |
| 		newData[f.DataKey] = data
 | |
| 		data = newData
 | |
| 	}
 | |
| 
 | |
| 	prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
 | |
| 
 | |
| 	timestampFormat := f.TimestampFormat
 | |
| 	if timestampFormat == "" {
 | |
| 		timestampFormat = defaultTimestampFormat
 | |
| 	}
 | |
| 
 | |
| 	if entry.err != "" {
 | |
| 		data[f.FieldMap.resolve(FieldKeyLogrusError)] = entry.err
 | |
| 	}
 | |
| 	if !f.DisableTimestamp {
 | |
| 		data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat)
 | |
| 	}
 | |
| 	data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
 | |
| 	data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
 | |
| 	if entry.HasCaller() {
 | |
| 		funcVal := entry.Caller.Function
 | |
| 		fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
 | |
| 		if f.CallerPrettyfier != nil {
 | |
| 			funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
 | |
| 		}
 | |
| 		if funcVal != "" {
 | |
| 			data[f.FieldMap.resolve(FieldKeyFunc)] = funcVal
 | |
| 		}
 | |
| 		if fileVal != "" {
 | |
| 			data[f.FieldMap.resolve(FieldKeyFile)] = fileVal
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	var b *bytes.Buffer
 | |
| 	if entry.Buffer != nil {
 | |
| 		b = entry.Buffer
 | |
| 	} else {
 | |
| 		b = &bytes.Buffer{}
 | |
| 	}
 | |
| 
 | |
| 	encoder := json.NewEncoder(b)
 | |
| 	encoder.SetEscapeHTML(!f.DisableHTMLEscape)
 | |
| 	if f.PrettyPrint {
 | |
| 		encoder.SetIndent("", "  ")
 | |
| 	}
 | |
| 	if err := encoder.Encode(data); err != nil {
 | |
| 		return nil, fmt.Errorf("failed to marshal fields to JSON, %w", err)
 | |
| 	}
 | |
| 
 | |
| 	return b.Bytes(), nil
 | |
| }
 |