X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=src%2Flog.go;h=7953a0227afe14836cb878ccbe10fa4020ad8539;hb=0367cce2741e1ce6a89a49fd5c4e9df6005c9744;hp=dfa2a4c6e0c5780501fd7422c62e1a2eb342c82b;hpb=3a710c60770ddbc553ea0de627aef6153e7088c7;p=nncp.git diff --git a/src/log.go b/src/log.go index dfa2a4c..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-2020 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 @@ -18,54 +18,79 @@ along with this program. If not, see . package nncp import ( + "bytes" "fmt" "os" - "sort" - "strings" + "sync" "time" + "go.cypherpunks.ru/recfile" "golang.org/x/sys/unix" ) -type LogLevel string +const LogFdPrefix = "FD:" -type SDS map[string]interface{} +var ( + LogFd *os.File + LogFdLock sync.Mutex +) + +type LE struct { + K string + V interface{} +} +type LEs []LE -func sdFmt(who string, sds SDS) string { - keys := make([]string, 0, len(sds)) - for k, _ := range sds { - keys = append(keys, k) +func (les LEs) Rec() string { + b := bytes.NewBuffer(make([]byte, 0, 1<<10)) + w := recfile.NewWriter(b) + _, err := w.RecordStart() + if err != nil { + panic(err) } - sort.Strings(keys) - result := make([]string, 0, 1+len(keys)) - result = append(result, "["+who) - for _, k := range keys { - var value string - switch v := sds[k].(type) { + _, 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: - value = fmt.Sprintf("%d", v) + _, 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: - value = fmt.Sprintf("%s", v) + _, err = w.WriteFields(recfile.Field{ + Name: le.K, + Value: fmt.Sprintf("%s", v), + }) + } + if err != nil { + panic(err) } - result = append(result, fmt.Sprintf(`%s="%s"`, k, value)) } - return strings.Join(result, " ") + "]" + return b.String() } -func msgFmt(level LogLevel, who string, sds SDS, msg string) string { - result := fmt.Sprintf( - "%s %s %s", - level, - time.Now().UTC().Format(time.RFC3339Nano), - sdFmt(who, sds), - ) - if len(msg) > 0 { - result += " " + msg +func (ctx *Ctx) Log(rec string) { + if LogFd != nil { + LogFdLock.Lock() + LogFd.WriteString(rec) + LogFdLock.Unlock() + return } - return result + "\n" -} - -func (ctx *Ctx) Log(msg string) { fdLock, err := os.OpenFile( ctx.LogPath+".lock", os.O_CREATE|os.O_WRONLY, @@ -75,6 +100,7 @@ func (ctx *Ctx) Log(msg string) { fmt.Fprintln(os.Stderr, "Can not open lock for log:", err) return } + defer fdLock.Close() fdLockFd := int(fdLock.Fd()) err = unix.Flock(fdLockFd, unix.LOCK_EX) if err != nil { @@ -91,42 +117,41 @@ func (ctx *Ctx) Log(msg string) { fmt.Fprintln(os.Stderr, "Can not open log:", err) return } - fd.WriteString(msg) // #nosec G104 - fd.Close() // #nosec G104 + fd.WriteString(rec) + fd.Close() } -func (ctx *Ctx) LogD(who string, sds SDS, msg string) { +func (ctx *Ctx) LogD(who string, les LEs, msg func(LEs) string) { if !ctx.Debug { return } - fmt.Fprint(os.Stderr, msgFmt(LogLevel("D"), who, sds, msg)) + les = append(LEs{{"Debug", true}, {"Who", who}}, les...) + les = append(les, LE{"Msg", msg(les)}) + fmt.Fprint(os.Stderr, les.Rec()) } -func (ctx *Ctx) LogI(who string, sds SDS, msg string) { - msg = msgFmt(LogLevel("I"), who, sds, msg) - if !ctx.Quiet { - fmt.Fprintln(os.Stderr, ctx.Humanize(msg)) +func (ctx *Ctx) LogI(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) } - ctx.Log(msg) -} - -func (ctx *Ctx) LogE(who string, sds SDS, err error, msg string) { - sds["err"] = err.Error() - msg = msgFmt(LogLevel("E"), who, sds, msg) - if len(msg) > 2048 { - msg = msg[:2048] + if !ctx.Quiet { + fmt.Fprintln(os.Stderr, ctx.HumanizeRec(rec)) } - fmt.Fprintln(os.Stderr, ctx.Humanize(msg)) - ctx.Log(msg) + ctx.Log(rec) } -func SdsAdd(sds, add SDS) SDS { - neu := SDS{} - for k, v := range sds { - neu[k] = v +func (ctx *Ctx) LogE(who string, les LEs, err error, msg func(LEs) string) { + 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) } - for k, v := range add { - neu[k] = v + if !ctx.Quiet { + fmt.Fprintln(os.Stderr, ctx.HumanizeRec(rec)) } - return neu + ctx.Log(rec) }