Files
old-ibcetvorke/vendor/github.com/a-h/gemini/log/log.go
2023-07-30 19:21:16 +02:00

83 lines
1.7 KiB
Go

package log
import (
"encoding/json"
"fmt"
"os"
"sync"
"time"
)
type Field func() (k string, v interface{})
func String(name string, value string) Field {
return func() (k string, v interface{}) {
return name, value
}
}
func Int(name string, value int) Field {
return func() (k string, v interface{}) {
return name, value
}
}
func Int64(name string, value int64) Field {
return func() (k string, v interface{}) {
return name, value
}
}
func Interface(name string, value interface{}) Field {
return func() (k string, v interface{}) {
return name, value
}
}
func Info(msg string, fields ...Field) {
std.Write("INFO", msg, fields...)
}
func Warn(msg string, fields ...Field) {
std.Write("WARN", msg, fields...)
}
func Error(msg string, err error, fields ...Field) {
if err != nil {
fields = append(fields, String("error", err.Error()))
}
std.Write("ERROR", msg, fields...)
}
type Logger struct {
stdout sync.Mutex
stderr sync.Mutex
enc json.Encoder
newLine []byte
}
func (s *Logger) Write(level string, msg string, fields ...Field) {
entry := make(map[string]interface{})
entry["time"] = time.Now().UTC().Format(time.RFC3339)
entry["level"] = level
entry["msg"] = msg
for i := 0; i < len(fields); i++ {
k, v := fields[i]()
entry[k] = v
}
j, err := json.Marshal(entry)
if err != nil {
j = []byte(fmt.Sprintf("log.Write: failed to marshal entry '%+v': %v", entry, err))
}
if level == "ERROR" {
s.stderr.Lock()
defer s.stderr.Unlock()
os.Stderr.Write(j)
os.Stderr.Write(s.newLine)
return
}
s.stdout.Lock()
defer s.stdout.Unlock()
os.Stdout.Write(j)
os.Stderr.Write(s.newLine)
}
var std = &Logger{newLine: []byte("\n")}