Skip to content

Commit

Permalink
Add std logging compatibility and interception options (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
ldemailly authored Aug 4, 2023
1 parent d41a448 commit 31afb57
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 8 deletions.
26 changes: 26 additions & 0 deletions http_logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package log
import (
"crypto/tls"
"fmt"
"log"
"net/http"
"strings"
)
Expand Down Expand Up @@ -72,3 +73,28 @@ func LogRequest(r *http.Request, msg string, extraAttributes ...KeyVal) {
}
S(Info, msg, attr...)
}

type logWriter struct {
source string
level Level
}

// Returns a Std logger that will log to the given level with the given source attribute.
// Can be passed for instance to net/http/httputil.ReverseProxy.ErrorLog.
func NewStdLogger(source string, level Level) *log.Logger {
return log.New(logWriter{source, level}, "", 0)
}

func (w logWriter) Write(p []byte) (n int, err error) {
// Force JSON to avoid infinite loop and also skip file/line so it doesn't show this file as the source
// (TODO consider passing the level up the stack to look for the caller)
s(w.level, false, true, strings.TrimSpace(string(p)), Str("src", w.source))
return len(p), nil
}

// InterceptStandardLogger changes the output of the standard logger to use ours, at the given
// level, with the source "std", as a catchall.
func InterceptStandardLogger(level Level) {
log.SetFlags(0)
log.SetOutput(logWriter{"std", level})
}
37 changes: 37 additions & 0 deletions http_logging_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"log"
"net/http"
"testing"
)
Expand Down Expand Up @@ -70,3 +71,39 @@ func TestTLSInfo(t *testing.T) {
t.Errorf("unexpected for no tls:\n%s\nvs:\n%s\n", got, expected)
}
}

func TestInterceptStandardLogger(t *testing.T) {
SetLogLevel(Warning)
Config.LogFileAndLine = true
Config.JSON = false // check that despite this, it'll be json anyway (so it doesn't go infinite loop)
Config.NoTimestamp = true
var b bytes.Buffer
w := bufio.NewWriter(&b)
SetOutput(w)
InterceptStandardLogger(Warning)
log.Printf("\n\na test\n\n")
w.Flush()
actual := b.String()
expected := `{"level":"warn","msg":"a test","src":"std"}` + "\n"
if actual != expected {
t.Errorf("unexpected:\n%s\nvs:\n%s\n", actual, expected)
}
}

func TestNewStdLogger(t *testing.T) {
SetLogLevel(Info)
Config.LogFileAndLine = true
Config.JSON = false
Config.NoTimestamp = true
var b bytes.Buffer
w := bufio.NewWriter(&b)
SetOutput(w)
logger := NewStdLogger("test src", Info)
logger.Printf("\n\nanother test\n\n")
w.Flush()
actual := b.String()
expected := `{"level":"info","msg":"another test","src":"test src"}` + "\n"
if actual != expected {
t.Errorf("unexpected:\n%s\nvs:\n%s\n", actual, expected)
}
}
17 changes: 9 additions & 8 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,17 +532,18 @@ func Attr[T ValueTypes](key string, value T) KeyVal {

// S logs a message of the given level with additional attributes.
func S(lvl Level, msg string, attrs ...KeyVal) {
s(lvl, Config.LogFileAndLine, Config.JSON, msg, attrs...)
}

func s(lvl Level, logFileAndLine bool, json bool, msg string, attrs ...KeyVal) {
if !Log(lvl) {
return
}
// extra := ""
// if Config.GoroutineID {
// }
buf := strings.Builder{}
var format string
if Color {
format = Colors.Reset + ", " + Colors.Blue + "%s" + Colors.Reset + "=" + LevelToColor[lvl] + "%q"
} else if Config.JSON {
} else if json {
format = ",%q:%q"
} else {
format = ", %s=%q"
Expand All @@ -561,14 +562,14 @@ func S(lvl Level, msg string, attrs ...KeyVal) {
} else {
lvl1Char = "[" + LevelToStrA[lvl][0:1] + "]"
}
if Config.LogFileAndLine { //nolint:nestif
_, file, line, _ := runtime.Caller(1)
if logFileAndLine { //nolint:nestif
_, file, line, _ := runtime.Caller(2)
file = file[strings.LastIndex(file, "/")+1:]
if Color {
jsonWrite(fmt.Sprintf("%s%s%s %s:%d%s%s%s%s%s\n",
colorTimestamp(), colorGID(), ColorLevelToStr(lvl),
file, line, prefix, LevelToColor[lvl], msg, buf.String(), Colors.Reset))
} else if Config.JSON {
} else if json {
jsonWrite(fmt.Sprintf("{%s\"level\":%s,%s\"file\":%q,\"line\":%d,\"msg\":%q%s}\n",
jsonTimestamp(), LevelToJSON[lvl], jsonGID(), file, line, msg, buf.String()))
} else {
Expand All @@ -578,7 +579,7 @@ func S(lvl Level, msg string, attrs ...KeyVal) {
if Color {
jsonWrite(fmt.Sprintf("%s%s%s%s%s%s%s%s\n",
colorTimestamp(), colorGID(), ColorLevelToStr(lvl), prefix, LevelToColor[lvl], msg, buf.String(), Colors.Reset))
} else if Config.JSON {
} else if json {
jsonWrite(fmt.Sprintf("{%s\"level\":%s,\"msg\":%q%s}\n",
jsonTimestamp(), LevelToJSON[lvl], msg, buf.String()))
} else {
Expand Down

0 comments on commit 31afb57

Please sign in to comment.