Skip to content

Instantly share code, notes, and snippets.

@cee-dub
Created July 10, 2020 16:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cee-dub/f17400a4fc4db8bf7c3e80751005edaf to your computer and use it in GitHub Desktop.
Save cee-dub/f17400a4fc4db8bf7c3e80751005edaf to your computer and use it in GitHub Desktop.
Basic ordered JSON logger inspired by go-kit
package olog
import (
"encoding"
"encoding/json"
"fmt"
"github.com/go-kit/kit/log"
"github.com/mickep76/mapslice-json"
)
type orderedJSONLogger struct {
enc *json.Encoder
}
func (l *orderedJSONLogger) Log(keyvals ...interface{}) error {
n := (len(keyvals) + 1) / 2 // +1 to handle case when len is odd
message := make(mapslice.MapSlice, 0, n)
// Assemble entry fields
for i := 0; i < len(keyvals); i += 2 {
k := keyvals[i]
var v interface{} = log.ErrMissingValue
if i+1 < len(keyvals) {
v = keyvals[i+1]
}
message = addLogField(message, k, v)
}
return l.enc.Encode(message)
}
func addLogField(dst mapslice.MapSlice, k, v interface{}) mapslice.MapSlice {
var key string
switch x := k.(type) {
case string:
key = x
case fmt.Stringer:
key = safeString(x)
default:
key = fmt.Sprint(x)
}
// We want json.Marshaler and encoding.TextMarshaler to take priority over
// err.Error() and v.String(). But json.Marshal (called later) does that
// by default, so we force a no-op in those 2 cases.
switch x := v.(type) {
case json.Marshaler:
case encoding.TextMarshaler:
case error:
v = safeError(x)
case fmt.Stringer:
v = safeString(x)
}
return append(dst, mapslice.MapItem{Key: key, Value: v})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment