Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix log stdlibadapter when prefixed #1036

Merged
merged 4 commits into from Nov 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 38 additions & 3 deletions log/stdlib.go
@@ -1,6 +1,7 @@
package log

import (
"bytes"
"io"
"log"
"regexp"
Expand All @@ -26,9 +27,11 @@ func (w StdlibWriter) Write(p []byte) (int, error) {
// messages, and place them under relevant keys.
type StdlibAdapter struct {
Logger
timestampKey string
fileKey string
messageKey string
peterbourgon marked this conversation as resolved.
Show resolved Hide resolved
timestampKey string
fileKey string
messageKey string
prefix string
joinPrefixToMsg bool
}

// StdlibAdapterOption sets a parameter for the StdlibAdapter.
Expand All @@ -49,6 +52,16 @@ func MessageKey(key string) StdlibAdapterOption {
return func(a *StdlibAdapter) { a.messageKey = key }
}

// Prefix configures the adapter to parse a prefix from stdlib log events. If
// you provide a non-empty prefix to the stdlib logger, then your should provide
// that same prefix to the adapter via this option.
//
// By default, the prefix isn't included in the msg key. Set joinPrefixToMsg to
// true if you want to include the parsed prefix in the msg.
func Prefix(prefix string, joinPrefixToMsg bool) StdlibAdapterOption {
return func(a *StdlibAdapter) { a.prefix = prefix; a.joinPrefixToMsg = joinPrefixToMsg }
}

// NewStdlibAdapter returns a new StdlibAdapter wrapper around the passed
// logger. It's designed to be passed to log.SetOutput.
func NewStdlibAdapter(logger Logger, options ...StdlibAdapterOption) io.Writer {
Expand All @@ -65,6 +78,8 @@ func NewStdlibAdapter(logger Logger, options ...StdlibAdapterOption) io.Writer {
}

func (a StdlibAdapter) Write(p []byte) (int, error) {
p = a.handlePrefix(p)

result := subexps(p)
keyvals := []interface{}{}
var timestamp string
Expand All @@ -84,6 +99,7 @@ func (a StdlibAdapter) Write(p []byte) (int, error) {
keyvals = append(keyvals, a.fileKey, file)
}
if msg, ok := result["msg"]; ok {
msg = a.handleMessagePrefix(msg)
keyvals = append(keyvals, a.messageKey, msg)
}
if err := a.Logger.Log(keyvals...); err != nil {
Expand All @@ -92,6 +108,25 @@ func (a StdlibAdapter) Write(p []byte) (int, error) {
return len(p), nil
}

func (a StdlibAdapter) handlePrefix(p []byte) []byte {
if a.prefix != "" {
p = bytes.TrimPrefix(p, []byte(a.prefix))
}
return p
}

func (a StdlibAdapter) handleMessagePrefix(msg string) string {
if a.prefix == "" {
return msg
}

msg = strings.TrimPrefix(msg, a.prefix)
if a.joinPrefixToMsg {
msg = a.prefix + msg
}
return msg
}

const (
logRegexpDate = `(?P<date>[0-9]{4}/[0-9]{2}/[0-9]{2})?[ ]?`
logRegexpTime = `(?P<time>[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?)?[ ]?`
Expand Down
50 changes: 50 additions & 0 deletions log/stdlib_test.go
Expand Up @@ -72,6 +72,56 @@ func TestStdLibAdapterExtraction(t *testing.T) {
}
peterbourgon marked this conversation as resolved.
Show resolved Hide resolved
}

func TestStdLibAdapterPrefixedExtraction(t *testing.T) {
buf := &bytes.Buffer{}
logger := NewLogfmtLogger(buf)
writer := NewStdlibAdapter(logger, Prefix("some prefix ", false))
for input, want := range map[string]string{
"some prefix hello": "msg=hello\n",
"some prefix 2009/01/23: hello": "ts=2009/01/23 msg=hello\n",
"some prefix 2009/01/23 01:23:23: hello": "ts=\"2009/01/23 01:23:23\" msg=hello\n",
"some prefix 01:23:23: hello": "ts=01:23:23 msg=hello\n",
"some prefix 2009/01/23 01:23:23.123123: hello": "ts=\"2009/01/23 01:23:23.123123\" msg=hello\n",
"some prefix 2009/01/23 01:23:23.123123 /a/b/c/d.go:23: hello": "ts=\"2009/01/23 01:23:23.123123\" caller=/a/b/c/d.go:23 msg=hello\n",
"some prefix 01:23:23.123123 /a/b/c/d.go:23: hello": "ts=01:23:23.123123 caller=/a/b/c/d.go:23 msg=hello\n",
"some prefix 2009/01/23 01:23:23 /a/b/c/d.go:23: hello": "ts=\"2009/01/23 01:23:23\" caller=/a/b/c/d.go:23 msg=hello\n",
"some prefix 2009/01/23 /a/b/c/d.go:23: hello": "ts=2009/01/23 caller=/a/b/c/d.go:23 msg=hello\n",
"some prefix /a/b/c/d.go:23: hello": "caller=/a/b/c/d.go:23 msg=hello\n",
"/a/b/c/d.go:23: some prefix hello": "caller=/a/b/c/d.go:23 msg=hello\n",
} {
buf.Reset()
fmt.Fprint(writer, input)
if have := buf.String(); want != have {
t.Errorf("%q: want %#v, have %#v", input, want, have)
}
}
}

func TestStdLibAdapterPrefixedExtractionWithJoinToMessage(t *testing.T) {
buf := &bytes.Buffer{}
logger := NewLogfmtLogger(buf)
writer := NewStdlibAdapter(logger, Prefix("some prefix ", true))
for input, want := range map[string]string{
"some prefix hello": "msg=\"some prefix hello\"\n",
"some prefix 2009/01/23: hello": "ts=2009/01/23 msg=\"some prefix hello\"\n",
"some prefix 2009/01/23 01:23:23: hello": "ts=\"2009/01/23 01:23:23\" msg=\"some prefix hello\"\n",
"some prefix 01:23:23: hello": "ts=01:23:23 msg=\"some prefix hello\"\n",
"some prefix 2009/01/23 01:23:23.123123: hello": "ts=\"2009/01/23 01:23:23.123123\" msg=\"some prefix hello\"\n",
"some prefix 2009/01/23 01:23:23.123123 /a/b/c/d.go:23: hello": "ts=\"2009/01/23 01:23:23.123123\" caller=/a/b/c/d.go:23 msg=\"some prefix hello\"\n",
"some prefix 01:23:23.123123 /a/b/c/d.go:23: hello": "ts=01:23:23.123123 caller=/a/b/c/d.go:23 msg=\"some prefix hello\"\n",
"some prefix 2009/01/23 01:23:23 /a/b/c/d.go:23: hello": "ts=\"2009/01/23 01:23:23\" caller=/a/b/c/d.go:23 msg=\"some prefix hello\"\n",
"some prefix 2009/01/23 /a/b/c/d.go:23: hello": "ts=2009/01/23 caller=/a/b/c/d.go:23 msg=\"some prefix hello\"\n",
"some prefix /a/b/c/d.go:23: hello": "caller=/a/b/c/d.go:23 msg=\"some prefix hello\"\n",
"/a/b/c/d.go:23: some prefix hello": "caller=/a/b/c/d.go:23 msg=\"some prefix hello\"\n",
} {
buf.Reset()
fmt.Fprint(writer, input)
if have := buf.String(); want != have {
t.Errorf("%q: want %#v, have %#v", input, want, have)
}
}
}

func TestStdlibAdapterSubexps(t *testing.T) {
for input, wantMap := range map[string]map[string]string{
"hello world": {
Expand Down