diff --git a/log/sockstatlog/logger.go b/log/sockstatlog/logger.go index e2303a19c..744b8d630 100644 --- a/log/sockstatlog/logger.go +++ b/log/sockstatlog/logger.go @@ -37,7 +37,7 @@ type Logger struct { logger *logtail.Logger filch *filch.Filch - tr *http.Transport + tr http.RoundTripper } // deltaStat represents the bytes transferred during a time period. @@ -119,6 +119,10 @@ func NewLogger(logdir string, logf logger.Logf, logID logid.PublicID) (*Logger, return logger, nil } +func (l *Logger) Write(p []byte) (int, error) { + return l.logger.Write(p) +} + // poll fetches the current socket stats at the configured time interval, // calculates the delta since the last poll, and logs any non-zero values. // This method does not return. @@ -127,7 +131,7 @@ func (l *Logger) poll() { var lastStats *sockstats.SockStats var lastTime time.Time - enc := json.NewEncoder(l.logger) + enc := json.NewEncoder(l) for { select { case <-l.ctx.Done(): @@ -169,11 +173,17 @@ func (l *Logger) Flush() { } func (l *Logger) Shutdown() { - l.ticker.Stop() - l.logger.Shutdown(l.ctx) l.cancelFn() + l.ticker.Stop() l.filch.Close() - l.tr.CloseIdleConnections() + l.logger.Shutdown(context.Background()) + + type closeIdler interface { + CloseIdleConnections() + } + if tr, ok := l.tr.(closeIdler); ok { + tr.CloseIdleConnections() + } } // delta calculates the delta stats between two SockStats snapshots. diff --git a/log/sockstatlog/logger_test.go b/log/sockstatlog/logger_test.go index 2d3e412a2..e64a5de8b 100644 --- a/log/sockstatlog/logger_test.go +++ b/log/sockstatlog/logger_test.go @@ -8,8 +8,29 @@ import ( "github.com/google/go-cmp/cmp" "tailscale.com/net/sockstats" + "tailscale.com/tstest" + "tailscale.com/types/logger" + "tailscale.com/types/logid" ) +func TestResourceCleanup(t *testing.T) { + if !sockstats.IsAvailable { + t.Skip("sockstats not available") + } + tstest.ResourceCheck(t) + td := t.TempDir() + id, err := logid.NewPrivateID() + if err != nil { + t.Fatal(err) + } + lg, err := NewLogger(td, logger.Discard, id.Public()) + if err != nil { + t.Fatal(err) + } + lg.Write([]byte("hello")) + lg.Shutdown() +} + func TestDelta(t *testing.T) { tests := []struct { name string