Created
March 30, 2018 10:15
-
-
Save xissy/17262b53e62c2ecbaaa347d31d224890 to your computer and use it in GitHub Desktop.
Logrus JSON formatter for Apex Up
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/json" | |
"fmt" | |
"time" | |
"github.com/sirupsen/logrus" | |
) | |
type ApexUpJSONFormatter struct { | |
// TimestampFormat sets the format used for marshaling timestamps. | |
TimestampFormat string | |
// DisableTimestamp allows disabling automatic timestamps in output | |
DisableTimestamp bool | |
// 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", | |
// }, | |
// } | |
FieldMap FieldMap | |
} | |
type Fields map[string]interface{} | |
type fieldKey string | |
// FieldMap allows customization of the key names for default fields. | |
type FieldMap map[fieldKey]string | |
// Default key names for the default fields | |
const ( | |
FieldKeyMsg = "message" | |
FieldKeyLevel = "level" | |
FieldKeyTime = "timestamp" | |
) | |
func (f FieldMap) resolve(key fieldKey) string { | |
if k, ok := f[key]; ok { | |
return k | |
} | |
return string(key) | |
} | |
const defaultTimestampFormat = time.RFC3339 | |
func prefixFieldClashes(data Fields, fieldMap FieldMap) { | |
timeKey := fieldMap.resolve(FieldKeyTime) | |
if t, ok := data[timeKey]; ok { | |
data["fields."+timeKey] = t | |
} | |
msgKey := fieldMap.resolve(FieldKeyMsg) | |
if m, ok := data[msgKey]; ok { | |
data["fields."+msgKey] = m | |
} | |
levelKey := fieldMap.resolve(FieldKeyLevel) | |
if l, ok := data[levelKey]; ok { | |
data["fields."+levelKey] = l | |
} | |
} | |
func (f *ApexUpJSONFormatter) Format(entry *logrus.Entry) ([]byte, error) { | |
data := make(Fields, len(entry.Data)+3) | |
data["fields"] = make(map[string]interface{}) | |
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: | |
fieldsData := data["fields"].(map[string]interface{}) | |
fieldsData[k] = v | |
} | |
} | |
prefixFieldClashes(data, f.FieldMap) | |
timestampFormat := f.TimestampFormat | |
if timestampFormat == "" { | |
timestampFormat = defaultTimestampFormat | |
} | |
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() | |
serialized, err := json.Marshal(data) | |
if err != nil { | |
return nil, fmt.Errorf("failed to marshal fields to JSON, %v", err) | |
} | |
return append(serialized, '\n'), nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment