/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2021 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2023 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
"bytes"
"fmt"
"os"
+ "sync"
"time"
"go.cypherpunks.ru/recfile"
"golang.org/x/sys/unix"
)
+const LogFdPrefix = "FD:"
+
+var (
+ LogFd *os.File
+ LogFdLock sync.Mutex
+)
+
type LE struct {
K string
V interface{}
type LEs []LE
func (les LEs) Rec() string {
- fields := make([]recfile.Field, 0, len(les)+1)
- fields = append(fields, recfile.Field{
- Name: "When", Value: time.Now().UTC().Format(time.RFC3339Nano),
- })
- var val string
- for _, le := range les {
- switch v := le.V.(type) {
- case int, int8, uint8, int64, uint64:
- val = fmt.Sprintf("%d", v)
- case bool:
- val = fmt.Sprintf("%v", v)
- default:
- val = fmt.Sprintf("%s", v)
- }
- fields = append(fields, recfile.Field{Name: le.K, Value: val})
- }
b := bytes.NewBuffer(make([]byte, 0, 1<<10))
w := recfile.NewWriter(b)
_, err := w.RecordStart()
if err != nil {
panic(err)
}
- _, err = w.WriteFields(fields...)
+ _, err = w.WriteFields(recfile.Field{
+ Name: "When",
+ Value: time.Now().UTC().Format(time.RFC3339Nano),
+ })
if err != nil {
panic(err)
}
+ for _, le := range les {
+ switch v := le.V.(type) {
+ case int, int8, uint8, int64, uint64:
+ _, err = w.WriteFields(recfile.Field{
+ Name: le.K,
+ Value: fmt.Sprintf("%d", v),
+ })
+ case bool:
+ _, err = w.WriteFields(recfile.Field{
+ Name: le.K,
+ Value: fmt.Sprintf("%v", v),
+ })
+ case []string:
+ if len(v) > 0 {
+ _, err = w.WriteFieldMultiline(le.K, v)
+ }
+ default:
+ _, err = w.WriteFields(recfile.Field{
+ Name: le.K,
+ Value: fmt.Sprintf("%s", v),
+ })
+ }
+ if err != nil {
+ panic(err)
+ }
+ }
return b.String()
}
func (ctx *Ctx) Log(rec string) {
+ if LogFd != nil {
+ LogFdLock.Lock()
+ LogFd.WriteString(rec)
+ LogFdLock.Unlock()
+ return
+ }
fdLock, err := os.OpenFile(
ctx.LogPath+".lock",
os.O_CREATE|os.O_WRONLY,
fmt.Fprintln(os.Stderr, "Can not open log:", err)
return
}
- fd.WriteString(rec) // #nosec G104
- fd.Close() // #nosec G104
+ fd.WriteString(rec)
+ fd.Close()
}
func (ctx *Ctx) LogD(who string, les LEs, msg func(LEs) string) {
les = append(LEs{{"Who", who}}, les...)
les = append(les, LE{"Msg", msg(les)})
rec := les.Rec()
+ if ctx.Debug {
+ fmt.Fprint(os.Stderr, rec)
+ }
if !ctx.Quiet {
fmt.Fprintln(os.Stderr, ctx.HumanizeRec(rec))
}
les = append(LEs{{"Err", err.Error()}, {"Who", who}}, les...)
les = append(les, LE{"Msg", msg(les)})
rec := les.Rec()
+ if ctx.Debug {
+ fmt.Fprint(os.Stderr, rec)
+ }
if !ctx.Quiet {
fmt.Fprintln(os.Stderr, ctx.HumanizeRec(rec))
}