- internal/jsjson: JSON.stringify-compatible encoder and order-preserving decoder, tested against fixtures produced by Node itself - internal/ctrl: awg-ctrl in Go (params, vpn:// keys, users, peers, sync, 3.1 upgrade, CAKE shaping, metrics, monitor job, Express-compatible HTTP layer) - internal/iauth, internal/logx: internal Ed25519 tokens and logging - tools/diffbench: Docker bench with stubbed awg/ip/tc/nft that runs one scenario against the TS and Go implementations for comparison
61 lines
1.6 KiB
Go
61 lines
1.6 KiB
Go
// Package logx — простой логгер: человекочитаемые строки в консоль и JSON-строки в
|
|
// файл (как winston в Node-версии: console «<ts> level: msg», файл {level,message,timestamp,…}).
|
|
package logx
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type Logger struct {
|
|
mu sync.Mutex
|
|
out io.Writer
|
|
file *os.File
|
|
}
|
|
|
|
// New пишет в stdout и (если dir не пуст) в dir/app.log.
|
|
func New(out io.Writer, dir string) *Logger {
|
|
l := &Logger{out: out}
|
|
if dir != "" {
|
|
if err := os.MkdirAll(dir, 0o755); err == nil {
|
|
if f, err := os.OpenFile(filepath.Join(dir, "app.log"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644); err == nil {
|
|
l.file = f
|
|
}
|
|
}
|
|
}
|
|
return l
|
|
}
|
|
|
|
func (l *Logger) log(level, msg string, kv []any) {
|
|
l.mu.Lock()
|
|
defer l.mu.Unlock()
|
|
ts := time.Now().UTC().Format("2006-01-02T15:04:05.000Z")
|
|
if l.out != nil {
|
|
fmt.Fprintf(l.out, "%s %s: %s\n", ts, level, msg)
|
|
}
|
|
if l.file != nil {
|
|
m := map[string]any{"level": level, "message": msg, "timestamp": ts}
|
|
for i := 0; i+1 < len(kv); i += 2 {
|
|
if k, ok := kv[i].(string); ok {
|
|
if e, isErr := kv[i+1].(error); isErr {
|
|
m[k] = e.Error()
|
|
} else {
|
|
m[k] = kv[i+1]
|
|
}
|
|
}
|
|
}
|
|
b, _ := json.Marshal(m)
|
|
l.file.Write(append(b, '\n'))
|
|
}
|
|
}
|
|
|
|
func (l *Logger) Info(msg string, kv ...any) { l.log("info", msg, kv) }
|
|
func (l *Logger) Warn(msg string, kv ...any) { l.log("warn", msg, kv) }
|
|
func (l *Logger) Error(msg string, kv ...any) { l.log("error", msg, kv) }
|
|
func (l *Logger) Debug(msg string, kv ...any) { l.log("debug", msg, kv) }
|