X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=src%2Flog.go;h=7953a0227afe14836cb878ccbe10fa4020ad8539;hb=0367cce2741e1ce6a89a49fd5c4e9df6005c9744;hp=25a494626a9d403e93421b9e36f371fa8076f87d;hpb=16ac75d51758c249f5fc4e8fac9cf71b84331c55;p=nncp.git diff --git a/src/log.go b/src/log.go index 25a4946..7953a02 100644 --- a/src/log.go +++ b/src/log.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2021 Sergey Matveev +Copyright (C) 2016-2022 Sergey Matveev 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 @@ -21,12 +21,20 @@ import ( "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{} @@ -34,36 +42,55 @@ type LE struct { 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, @@ -90,39 +117,39 @@ func (ctx *Ctx) Log(rec string) { 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 string) { +func (ctx *Ctx) LogD(who string, les LEs, msg func(LEs) string) { if !ctx.Debug { return } les = append(LEs{{"Debug", true}, {"Who", who}}, les...) - if msg != "" { - les = append(les, LE{"Msg", msg}) - } + les = append(les, LE{"Msg", msg(les)}) fmt.Fprint(os.Stderr, les.Rec()) } -func (ctx *Ctx) LogI(who string, les LEs, msg string) { +func (ctx *Ctx) LogI(who string, les LEs, msg func(LEs) string) { les = append(LEs{{"Who", who}}, les...) - if msg != "" { - les = append(les, LE{"Msg", msg}) - } + 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)) } ctx.Log(rec) } -func (ctx *Ctx) LogE(who string, les LEs, err error, msg string) { +func (ctx *Ctx) LogE(who string, les LEs, err error, msg func(LEs) string) { les = append(LEs{{"Err", err.Error()}, {"Who", who}}, les...) - if msg != "" { - les = append(les, LE{"Msg", msg}) - } + 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)) }