Files
core/log/format.go
2024-04-24 15:42:11 +02:00

145 lines
2.6 KiB
Go

package log
import (
"fmt"
"sort"
"strconv"
"time"
"github.com/datarhei/core/v16/encoding/json"
)
type Formatter interface {
Bytes(e *Event) []byte
String(e *Event) string
}
type jsonFormatter struct{}
func NewJSONFormatter() Formatter {
return &jsonFormatter{}
}
func (f *jsonFormatter) Bytes(e *Event) []byte {
e.Data["ts"] = e.Time
e.Data["component"] = e.Component
if len(e.Caller) != 0 {
e.Data["caller"] = e.Caller
}
if len(e.Message) != 0 {
e.Data["message"] = e.Message
}
data, _ := json.Marshal(&e)
return data
}
func (f *jsonFormatter) String(e *Event) string {
return string(f.Bytes(e))
}
type consoleFormatter struct {
color bool
}
func NewConsoleFormatter(useColor bool) Formatter {
return &consoleFormatter{
color: useColor,
}
}
func (f *consoleFormatter) Bytes(e *Event) []byte {
return []byte(f.String(e))
}
func (f *consoleFormatter) String(e *Event) string {
datetime := e.Time.UTC().Format(time.RFC3339)
level := e.Level.String()
if f.color {
switch e.Level {
case Ldebug:
level = fmt.Sprintf("\033[35m%s\033[0m", level)
case Linfo:
level = fmt.Sprintf("\033[34m%s\033[0m", level)
case Lwarn:
level = fmt.Sprintf("\033[33m%s\033[0m", level)
case Lerror:
level = fmt.Sprintf("\033[31m\033[5m%s\033[0m", level)
default:
}
}
message := fmt.Sprintf("%s %s %s", f.writeKV("ts", datetime), f.writeKV("level", level), f.writeKV("component", f.quote(e.Component)))
if len(e.Message) != 0 {
message += fmt.Sprintf(" %s", f.writeKV("msg", f.quote(e.Message)))
}
// Sort the map keys
keys := make([]string, len(e.Data))
i := 0
for key := range e.Data {
keys[i] = key
i++
}
if i > 1 {
sort.Strings(keys)
}
v := ""
for _, key := range keys {
value := e.Data[key]
switch val := value.(type) {
case bool:
if val {
v = "true"
} else {
v = "false"
}
case string:
v = f.quote(val)
case error:
v = f.quote(val.Error())
default:
if str, ok := val.(fmt.Stringer); ok {
v = f.quote(str.String())
} else {
if jsonvalue, err := json.Marshal(value); err == nil {
v = string(jsonvalue)
} else {
v = f.quote(err.Error())
}
}
}
message += fmt.Sprintf(" %s", f.writeKV(key, v))
}
message += "\n"
return message
}
func (f *consoleFormatter) writeKV(key string, value string) string {
if !f.color {
return fmt.Sprintf("%s=%s", key, value)
}
if key == "error" {
value = "\033[31m" + value + "\033[0m"
}
return fmt.Sprintf("\033[90m%s=\033[0m%s", key, value)
}
func (f *consoleFormatter) quote(s string) string {
return strconv.Quote(s)
}