commit 6b625554a4904a33025b6430748d06d75429f55b Author: Sebastian Tobie Date: Sat Jul 23 22:39:09 2022 +0200 added my own version of the journaldwriter in short: - no JSON in the log - some useful metadata alone the JSONĀ file got on my nerves diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6802bc4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..3d2f716 --- /dev/null +++ b/go.mod @@ -0,0 +1,19 @@ +module gitea.sebastian-tobie.de/sebastian/generic + +go 1.18 + +require github.com/rs/zerolog v1.27.0 + +require ( + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/x448/float16 v0.8.4 // indirect +) + +require ( + github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534 + github.com/fxamacker/cbor/v2 v2.4.0 + github.com/hashicorp/go-multierror v1.1.1 + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..d1e00cf --- /dev/null +++ b/go.sum @@ -0,0 +1,22 @@ +github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534 h1:rtAn27wIbmOGUs7RIbVgPEjb31ehTVniDwPGXyMxm5U= +github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= +github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= +github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/logging/journald.go b/logging/journald.go new file mode 100644 index 0000000..f6e1ca1 --- /dev/null +++ b/logging/journald.go @@ -0,0 +1,135 @@ +//go:build !windows +// +build !windows + +// This package consists of parts of github.com/rs/zerolog i copied from. +// I removed the JSON argument part and added some more relevant data (The position of the caller and the goroutine) + +package logging + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "runtime" + "strings" + + "github.com/coreos/go-systemd/v22/journal" + "github.com/fxamacker/cbor/v2" + "github.com/rs/zerolog" +) + +const defaultJournalDPrio = journal.PriNotice + +func binaryFmt(p []byte) bool { + if len(p) > 0 && p[0] > 0x7F { + return true + } + return false +} + +// NewJournalDWriter returns a zerolog log destination +// to be used as parameter to New() calls. Writing logs +// to this writer will send the log messages to journalD +// running in this system. +func NewJournalDWriter() io.Writer { + return journalWriter{} +} + +type journalWriter struct { +} + +// levelToJPrio converts zerolog Level string into +// journalD's priority values. JournalD has more +// priorities than zerolog. +func levelToJPrio(zLevel string) journal.Priority { + lvl, _ := zerolog.ParseLevel(zLevel) + + switch lvl { + case zerolog.TraceLevel: + return journal.PriDebug + case zerolog.DebugLevel: + return journal.PriDebug + case zerolog.InfoLevel: + return journal.PriInfo + case zerolog.WarnLevel: + return journal.PriWarning + case zerolog.ErrorLevel: + return journal.PriErr + case zerolog.FatalLevel: + return journal.PriCrit + case zerolog.PanicLevel: + return journal.PriEmerg + case zerolog.NoLevel: + return journal.PriNotice + } + return defaultJournalDPrio +} + +func (w journalWriter) Write(p []byte) (n int, err error) { + var event map[string]interface{} + origPLen := len(p) + if binaryFmt(p) { + cbord := cbor.NewDecoder(bytes.NewReader(p)) + err = cbord.Decode(&event) + } else { + jsond := json.NewDecoder(bytes.NewReader(p)) + err = jsond.Decode(&event) + } + jPrio := defaultJournalDPrio + args := make(map[string]string) + if err != nil { + return + } + if l, ok := event[zerolog.LevelFieldName].(string); ok { + jPrio = levelToJPrio(l) + } + + msg := "" + for key, value := range event { + jKey := strings.ToUpper(key) + switch key { + case zerolog.LevelFieldName, zerolog.TimestampFieldName: + continue + case zerolog.MessageFieldName: + msg, _ = value.(string) + continue + } + + switch v := value.(type) { + case string: + args[jKey] = v + case json.Number: + args[jKey] = fmt.Sprint(value) + default: + b, err := zerolog.InterfaceMarshalFunc(value) + if err != nil { + args[jKey] = fmt.Sprintf("[error: %v]", err) + } else { + args[jKey] = string(b) + } + } + } + args["TID"] = fmt.Sprint(runtime.NumGoroutine()) + var callers = make([]uintptr, 10) + // skipping the function itself + runtime.Callers(2, callers) + var frames = runtime.CallersFrames(callers) + var frame, next = frames.Next() + for next { + if !strings.Contains(frame.File, "rs/zerolog") { + args["CODE_FILE"] = frame.File + args["CODE_LINE"] = fmt.Sprint(frame.Line) + args["CODE_FUNC"] = frame.Function + break + } + frame, next = frames.Next() + } + err = journal.Send(msg, jPrio, args) + + if err == nil { + n = origPLen + } + + return +}