From d2fc90a3aab7b3849bcb28a688def4b305e8a7e9 Mon Sep 17 00:00:00 2001 From: Alana McKenzie <43767132+amckenzie132@users.noreply.github.com> Date: Thu, 14 Apr 2022 10:32:06 -0700 Subject: [PATCH] Redirect standard logs (#5) --- CHANGELOG.md | 4 ++++ internal/logger/logger.go | 32 +++++++++++++++++++++++++++++ internal/logger/logger_test.go | 37 ++++++++++++++++++++++++++++++++++ pkg/proxy/proxy.go | 5 +++++ 4 files changed, 78 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bc6f0e9..b22e40b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Load config from Config file, and from env vars. Use viper for that - Automatically alocates a random port, if the specified one is in-use +## [0.1.18] - 2022-04-13 +## Changed +- Redirect standard output to configured logger + ## [0.1.17] - 2022-04-12 ## Changed - Log request and response at INFO level diff --git a/internal/logger/logger.go b/internal/logger/logger.go index a043a1dc..82c9b0ca 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -5,10 +5,13 @@ package logger import ( + "bytes" "fmt" + "io/ioutil" "log" "os" "path/filepath" + "strings" "time" "github.com/go-playground/validator/v10" @@ -112,5 +115,34 @@ type ProxyLogger struct { // Printf satisfies `goproxy` logging interface. Default logging level will be // `Debug`. func (pL *ProxyLogger) Printf(format string, v ...interface{}) { + format = strings.TrimSpace(format) pL.Logger.Debuglnf(format, v...) } + +type StandardLogger struct { + Logger *sypl.Sypl +} + +// Write satisfies the standard logging interface. Default logging level will be +// `Debug`. +func (pL *StandardLogger) Write(p []byte) (int, error) { + p = bytes.TrimSpace(p) + pL.Logger.Debug(string(p)) + return len(p), nil +} + +// RedirectStandardLogs redirects logs created with the standard library global logger +// to the ProxyLogger. +func RedirectStandardLogs() { + log.SetFlags(0) + log.SetPrefix("") + standardLogger := &StandardLogger{ + Logger: Get().New("go"), + } + log.SetOutput(standardLogger) +} + +// DisableStandardLogs disables logs created with the standard library global logger +func DisableStandardLogs() { + log.SetOutput(ioutil.Discard) +} diff --git a/internal/logger/logger_test.go b/internal/logger/logger_test.go index 4be7e1d1..4203d5a4 100644 --- a/internal/logger/logger_test.go +++ b/internal/logger/logger_test.go @@ -5,7 +5,15 @@ package logger import ( + "log" + "strings" "testing" + + "github.com/saucelabs/sypl" + "github.com/saucelabs/sypl/level" + "github.com/saucelabs/sypl/output" + "github.com/saucelabs/sypl/processor" + "github.com/saucelabs/sypl/shared" ) func TestSetup(t *testing.T) { @@ -58,3 +66,32 @@ func TestSetup(t *testing.T) { }) } } + + +func TestRedirectStandardLogs(t *testing.T) { + // set global proxy logger + proxyLogger = sypl.NewDefault("test", level.Debug) + defer func(){proxyLogger = nil}() + + // proxyLogger sends output to a buffer + buffer, outputBuffer := output.SafeBuffer(level.Trace, processor.PrefixBasedOnMask(shared.DefaultTimestampFormat)) + proxyLogger.AddOutputs(outputBuffer) + + // test standard logger before and after redirect + beforeMsg := "Before redirect" + afterMsg := "After redirect" + log.Println(beforeMsg) + + RedirectStandardLogs() + log.Println(afterMsg) + + bufferStr := buffer.String() + + if strings.Contains(bufferStr, beforeMsg) { + t.Errorf("%s should not appear in proxy logger: %s", beforeMsg, bufferStr) + } + if !strings.Contains(bufferStr, afterMsg) { + t.Errorf("%s should appear in proxy logger: %s", afterMsg, bufferStr) + } + +} \ No newline at end of file diff --git a/pkg/proxy/proxy.go b/pkg/proxy/proxy.go index b083b41e..5f47aa8d 100644 --- a/pkg/proxy/proxy.go +++ b/pkg/proxy/proxy.go @@ -602,6 +602,11 @@ func New( proxy.Logger = proxyLogger proxy.Verbose = true + + // Ensure any standard log messages use a configured logger + logger.RedirectStandardLogs() + } else { + logger.DisableStandardLogs() } proxy.KeepDestinationHeaders = true