mirror of https://github.com/dexidp/dex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
3.0 KiB
121 lines
3.0 KiB
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. |
|
TimestampFormat string |
|
|
|
// DisableTimestamp allows disabling automatic timestamps in output |
|
DisableTimestamp 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) |
|
if f.PrettyPrint { |
|
encoder.SetIndent("", " ") |
|
} |
|
if err := encoder.Encode(data); err != nil { |
|
return nil, fmt.Errorf("failed to marshal fields to JSON, %v", err) |
|
} |
|
|
|
return b.Bytes(), nil |
|
}
|
|
|