Add syslog CEE support (#262)
This commit is contained in:
parent
72acd6cfe8
commit
e11d470c08
42
syslog.go
42
syslog.go
|
@ -7,6 +7,10 @@ import (
|
|||
"io"
|
||||
)
|
||||
|
||||
// See http://cee.mitre.org/language/1.0-beta1/clt.html#syslog
|
||||
// or https://www.rsyslog.com/json-elasticsearch/
|
||||
const ceePrefix = "@cee:"
|
||||
|
||||
// SyslogWriter is an interface matching a syslog.Writer struct.
|
||||
type SyslogWriter interface {
|
||||
io.Writer
|
||||
|
@ -19,17 +23,34 @@ type SyslogWriter interface {
|
|||
}
|
||||
|
||||
type syslogWriter struct {
|
||||
w SyslogWriter
|
||||
w SyslogWriter
|
||||
prefix string
|
||||
}
|
||||
|
||||
// SyslogLevelWriter wraps a SyslogWriter and call the right syslog level
|
||||
// method matching the zerolog level.
|
||||
func SyslogLevelWriter(w SyslogWriter) LevelWriter {
|
||||
return syslogWriter{w}
|
||||
return syslogWriter{w, ""}
|
||||
}
|
||||
|
||||
// SyslogCEEWriter wraps a SyslogWriter with a SyslogLevelWriter that adds a
|
||||
// MITRE CEE prefix for JSON syslog entries, compatible with rsyslog
|
||||
// and syslog-ng JSON logging support.
|
||||
// See https://www.rsyslog.com/json-elasticsearch/
|
||||
func SyslogCEEWriter(w SyslogWriter) LevelWriter {
|
||||
return syslogWriter{w, ceePrefix}
|
||||
}
|
||||
|
||||
func (sw syslogWriter) Write(p []byte) (n int, err error) {
|
||||
return sw.w.Write(p)
|
||||
var pn int
|
||||
if sw.prefix != "" {
|
||||
pn, err = sw.w.Write([]byte(sw.prefix))
|
||||
if err != nil {
|
||||
return pn, err
|
||||
}
|
||||
}
|
||||
n, err = sw.w.Write(p)
|
||||
return pn + n, err
|
||||
}
|
||||
|
||||
// WriteLevel implements LevelWriter interface.
|
||||
|
@ -37,22 +58,23 @@ func (sw syslogWriter) WriteLevel(level Level, p []byte) (n int, err error) {
|
|||
switch level {
|
||||
case TraceLevel:
|
||||
case DebugLevel:
|
||||
err = sw.w.Debug(string(p))
|
||||
err = sw.w.Debug(sw.prefix + string(p))
|
||||
case InfoLevel:
|
||||
err = sw.w.Info(string(p))
|
||||
err = sw.w.Info(sw.prefix + string(p))
|
||||
case WarnLevel:
|
||||
err = sw.w.Warning(string(p))
|
||||
err = sw.w.Warning(sw.prefix + string(p))
|
||||
case ErrorLevel:
|
||||
err = sw.w.Err(string(p))
|
||||
err = sw.w.Err(sw.prefix + string(p))
|
||||
case FatalLevel:
|
||||
err = sw.w.Emerg(string(p))
|
||||
err = sw.w.Emerg(sw.prefix + string(p))
|
||||
case PanicLevel:
|
||||
err = sw.w.Crit(string(p))
|
||||
err = sw.w.Crit(sw.prefix + string(p))
|
||||
case NoLevel:
|
||||
err = sw.w.Info(string(p))
|
||||
err = sw.w.Info(sw.prefix + string(p))
|
||||
default:
|
||||
panic("invalid level")
|
||||
}
|
||||
// Any CEE prefix is not part of the message, so we don't include its length
|
||||
n = len(p)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
package zerolog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -68,3 +70,39 @@ func TestSyslogWriter(t *testing.T) {
|
|||
t.Errorf("Invalid syslog message routing: want %v, got %v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
type testCEEwriter struct {
|
||||
buf *bytes.Buffer
|
||||
}
|
||||
|
||||
// Only implement one method as we're just testing the prefixing
|
||||
func (c testCEEwriter) Debug(m string) error { return nil }
|
||||
|
||||
func (c testCEEwriter) Info(m string) error {
|
||||
_, err := c.buf.Write([]byte(m))
|
||||
return err
|
||||
}
|
||||
|
||||
func (c testCEEwriter) Warning(m string) error { return nil }
|
||||
|
||||
func (c testCEEwriter) Err(m string) error { return nil }
|
||||
|
||||
func (c testCEEwriter) Emerg(m string) error { return nil }
|
||||
|
||||
func (c testCEEwriter) Crit(m string) error { return nil }
|
||||
|
||||
func (c testCEEwriter) Write(b []byte) (int, error) {
|
||||
return c.buf.Write(b)
|
||||
}
|
||||
|
||||
func TestSyslogWriter_WithCEE(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
sw := testCEEwriter{&buf}
|
||||
log := New(SyslogCEEWriter(sw))
|
||||
log.Info().Str("key", "value").Msg("message string")
|
||||
got := string(buf.Bytes())
|
||||
want := "@cee:{"
|
||||
if !strings.HasPrefix(got, want) {
|
||||
t.Errorf("Bad CEE message start: want %v, got %v", want, got)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue