From 7b6b36d7a2987adfd54cb8412ae8a41a0b7b9d08 Mon Sep 17 00:00:00 2001 From: Tessa Nordgren Date: Sun, 5 Jul 2020 15:43:07 -0700 Subject: [PATCH 1/3] first pass at a syslog handler. --- handlers/syslog/syslog.go | 68 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 handlers/syslog/syslog.go diff --git a/handlers/syslog/syslog.go b/handlers/syslog/syslog.go new file mode 100644 index 0000000..c790208 --- /dev/null +++ b/handlers/syslog/syslog.go @@ -0,0 +1,68 @@ +// Package syslog implements output to local or remote hosts via the syslog protocol. +package syslog + +import ( + "fmt" + "log/syslog" + + "github.com/apex/log" +) + +// Handler implementation. +type Handler struct { + log *syslog.Writer + // map apex levels to syslog levels. + levelsMap map[log.Level](func (m string) error) +} + +// New syslog handler. +// addr: network address of syslog host. (default: localhost)type syslogOutput func (w *syslog.Writer) +// facility: syslog facility, as defined in "log/syslog". (default: LOG_USER) +// tag: message identifier, usually the application name. (default: os.Args[0]) +func New(addr string, facility syslog.Priority, tag string) (h *Handler, err error) { + h = new(Handler) + if facility == 0 { + facility = syslog.LOG_USER + } + + if addr == "" { + if h.log, err = syslog.New(facility, tag); err != nil { + // sometimes local socket connections don't work, so try localhost before + // giving up. + if h.log, err = syslog.Dial("tcp", "localhost:514", facility, tag); err != nil { + return nil, err + } + } + } else { + if h.log, err = syslog.Dial("tcp", addr, facility, tag); err != nil { + return nil, err + } + } + + // create apex -> syslog level mapping dynamically with h.log methods. + // wish "log/syslog" had a Writer.Log(p Priority, m string) method. + h.levelsMap = map[log.Level](func (m string) error){ + log.DebugLevel: h.log.Debug, + log.InfoLevel: h.log.Info, + log.WarnLevel: h.log.Warning, + log.ErrorLevel: h.log.Err, + log.FatalLevel: h.log.Emerg, + } + + return h, nil +} + +// HandleLog implements log.Handler. +func (h *Handler) HandleLog(e *log.Entry) error { + out := e.Message + " {" + + for _, name := range e.Fields.Names() { + if name == "source" { + continue + } + out += fmt.Sprintf(" %s=\"%v\"", name, e.Fields.Get(name)) + } + out += " }" + + return h.levelsMap[e.Level](out) +} From e4c42aa4b23b8e809d9d41a9b9cf143ec85d608e Mon Sep 17 00:00:00 2001 From: Tessa Nordgren Date: Mon, 6 Jul 2020 14:35:25 -0700 Subject: [PATCH 2/3] fixed weird spacing issues --- handlers/syslog/syslog.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/handlers/syslog/syslog.go b/handlers/syslog/syslog.go index c790208..895dcba 100644 --- a/handlers/syslog/syslog.go +++ b/handlers/syslog/syslog.go @@ -2,10 +2,10 @@ package syslog import ( - "fmt" + "fmt" "log/syslog" - "github.com/apex/log" + "github.com/apex/log" ) // Handler implementation. @@ -56,12 +56,12 @@ func New(addr string, facility syslog.Priority, tag string) (h *Handler, err err func (h *Handler) HandleLog(e *log.Entry) error { out := e.Message + " {" - for _, name := range e.Fields.Names() { - if name == "source" { - continue - } - out += fmt.Sprintf(" %s=\"%v\"", name, e.Fields.Get(name)) - } + for _, name := range e.Fields.Names() { + if name == "source" { + continue + } + out += fmt.Sprintf(" %s=\"%v\"", name, e.Fields.Get(name)) + } out += " }" return h.levelsMap[e.Level](out) From eefcf0e06c534337fcbcc2854f915e229bc899f8 Mon Sep 17 00:00:00 2001 From: Tessa Nordgren Date: Wed, 22 Jul 2020 12:59:23 -0700 Subject: [PATCH 3/3] updated to use logfmt --- handlers/syslog/syslog.go | 94 +++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/handlers/syslog/syslog.go b/handlers/syslog/syslog.go index 895dcba..8738dcf 100644 --- a/handlers/syslog/syslog.go +++ b/handlers/syslog/syslog.go @@ -2,67 +2,73 @@ package syslog import ( - "fmt" - "log/syslog" + "fmt" + "log/syslog" - "github.com/apex/log" + "github.com/apex/log" + "github.com/go-logfmt/logfmt" ) // Handler implementation. type Handler struct { - log *syslog.Writer - // map apex levels to syslog levels. - levelsMap map[log.Level](func (m string) error) + log *syslog.Writer + // map apex levels to syslog levels. + levelsMap map[log.Level](func(m string) error) } // New syslog handler. -// addr: network address of syslog host. (default: localhost)type syslogOutput func (w *syslog.Writer) +// addr: network address of syslog host. (default: localhost) // facility: syslog facility, as defined in "log/syslog". (default: LOG_USER) // tag: message identifier, usually the application name. (default: os.Args[0]) func New(addr string, facility syslog.Priority, tag string) (h *Handler, err error) { - h = new(Handler) - if facility == 0 { - facility = syslog.LOG_USER - } + h = new(Handler) + if facility == 0 { + facility = syslog.LOG_USER + } - if addr == "" { - if h.log, err = syslog.New(facility, tag); err != nil { - // sometimes local socket connections don't work, so try localhost before - // giving up. - if h.log, err = syslog.Dial("tcp", "localhost:514", facility, tag); err != nil { - return nil, err - } - } - } else { - if h.log, err = syslog.Dial("tcp", addr, facility, tag); err != nil { - return nil, err - } - } + if addr == "" { + if h.log, err = syslog.New(facility, tag); err != nil { + // sometimes local socket connections don't work, so try localhost before + // giving up. + if h.log, err = syslog.Dial("tcp", "localhost:514", facility, tag); err != nil { + return nil, err + } + } + } else { + if h.log, err = syslog.Dial("tcp", addr, facility, tag); err != nil { + return nil, err + } + } - // create apex -> syslog level mapping dynamically with h.log methods. - // wish "log/syslog" had a Writer.Log(p Priority, m string) method. - h.levelsMap = map[log.Level](func (m string) error){ - log.DebugLevel: h.log.Debug, - log.InfoLevel: h.log.Info, - log.WarnLevel: h.log.Warning, - log.ErrorLevel: h.log.Err, - log.FatalLevel: h.log.Emerg, - } + // create apex -> syslog level mapping dynamically with h.log methods. + // wish "log/syslog" had a Writer.Log(p Priority, m string) method. + h.levelsMap = map[log.Level](func(m string) error){ + log.DebugLevel: h.log.Debug, + log.InfoLevel: h.log.Info, + log.WarnLevel: h.log.Warning, + log.ErrorLevel: h.log.Err, + log.FatalLevel: h.log.Emerg, + } - return h, nil + return h, nil } // HandleLog implements log.Handler. func (h *Handler) HandleLog(e *log.Entry) error { - out := e.Message + " {" + keyvals := make([]interface{}, 0, len(e.Fields.Names()) * 2) + for _, name := range e.Fields.Names() { + if name == "source" { + continue + } + keyvals = append(keyvals, name) + keyvals = append(keyvals, e.Fields.Get(name)) + } + fmt.Println("keyvals:", keyvals) - for _, name := range e.Fields.Names() { - if name == "source" { - continue - } - out += fmt.Sprintf(" %s=\"%v\"", name, e.Fields.Get(name)) - } - out += " }" - - return h.levelsMap[e.Level](out) + out, err := logfmt.MarshalKeyvals(keyvals...) + fmt.Println(string(out), err) + if err != nil { + return err + } + return h.levelsMap[e.Level](string(out)) }