log: allow toggling sockstat logs via c2n component logging

Signed-off-by: Will Norris <will@tailscale.com>
pull/7710/head
Will Norris 2 years ago committed by Will Norris
parent 920ec69241
commit 7c99210e68

@ -315,6 +315,9 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, store ipn.StateStor
if err != nil { if err != nil {
log.Printf("error setting up sockstat logger: %v", err) log.Printf("error setting up sockstat logger: %v", err)
} }
if b.sockstatLogger != nil {
b.sockstatLogger.SetLoggingEnabled(true)
}
} }
// Default filter blocks everything and logs nothing, until Start() is called. // Default filter blocks everything and logs nothing, until Start() is called.
@ -365,6 +368,7 @@ type componentLogState struct {
var debuggableComponents = []string{ var debuggableComponents = []string{
"magicsock", "magicsock",
"sockstats",
} }
func componentStateKey(component string) ipn.StateKey { func componentStateKey(component string) ipn.StateKey {
@ -389,6 +393,10 @@ func (b *LocalBackend) SetComponentDebugLogging(component string, until time.Tim
return err return err
} }
setEnabled = mc.SetDebugLoggingEnabled setEnabled = mc.SetDebugLoggingEnabled
case "sockstats":
if b.sockstatLogger != nil {
setEnabled = b.sockstatLogger.SetLoggingEnabled
}
} }
if setEnabled == nil || !slices.Contains(debuggableComponents, component) { if setEnabled == nil || !slices.Contains(debuggableComponents, component) {
return fmt.Errorf("unknown component %q", component) return fmt.Errorf("unknown component %q", component)

@ -12,6 +12,7 @@ import (
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"sync/atomic"
"time" "time"
"tailscale.com/logpolicy" "tailscale.com/logpolicy"
@ -29,6 +30,8 @@ const pollPeriod = time.Second / 10
// Logger logs statistics about network sockets. // Logger logs statistics about network sockets.
type Logger struct { type Logger struct {
enabled atomic.Bool
ctx context.Context ctx context.Context
cancelFn context.CancelFunc cancelFn context.CancelFunc
@ -69,7 +72,7 @@ func SockstatLogID(logID logid.PublicID) logid.PrivateID {
// NewLogger returns a new Logger that will store stats in logdir. // NewLogger returns a new Logger that will store stats in logdir.
// On platforms that do not support sockstat logging, a nil Logger will be returned. // On platforms that do not support sockstat logging, a nil Logger will be returned.
// The returned Logger must be shut down with Shutdown when it is no longer needed. // The returned Logger is not yet enabled, and must be shut down with Shutdown when it is no longer needed.
func NewLogger(logdir string, logf logger.Logf, logID logid.PublicID) (*Logger, error) { func NewLogger(logdir string, logf logger.Logf, logID logid.PublicID) (*Logger, error) {
if !sockstats.IsAvailable { if !sockstats.IsAvailable {
return nil, nil return nil, nil
@ -84,14 +87,11 @@ func NewLogger(logdir string, logf logger.Logf, logID logid.PublicID) (*Logger,
return nil, err return nil, err
} }
ctx, cancel := context.WithCancel(context.Background())
logger := &Logger{ logger := &Logger{
ctx: ctx, ticker: time.NewTicker(pollPeriod),
cancelFn: cancel, logf: logf,
ticker: time.NewTicker(pollPeriod), filch: filch,
logf: logf, tr: logpolicy.NewLogtailTransport(logtail.DefaultHost),
filch: filch,
tr: logpolicy.NewLogtailTransport(logtail.DefaultHost),
} }
logger.logger = logtail.NewLogger(logtail.Config{ logger.logger = logtail.NewLogger(logtail.Config{
BaseURL: logpolicy.LogURL(), BaseURL: logpolicy.LogURL(),
@ -114,11 +114,24 @@ func NewLogger(logdir string, logf logger.Logf, logID logid.PublicID) (*Logger,
HTTPC: &http.Client{Transport: logger.tr}, HTTPC: &http.Client{Transport: logger.tr},
}, logf) }, logf)
go logger.poll()
return logger, nil return logger, nil
} }
// SetLoggingEnabled enables or disables logging.
// When disabled, socket stats are not polled and no new logs are written to disk.
// Existing logs can still be fetched via the C2N API.
func (l *Logger) SetLoggingEnabled(v bool) {
old := l.enabled.Load()
if old != v && l.enabled.CompareAndSwap(old, v) {
if v {
l.ctx, l.cancelFn = context.WithCancel(context.Background())
go l.poll()
} else {
l.cancelFn()
}
}
}
func (l *Logger) Write(p []byte) (int, error) { func (l *Logger) Write(p []byte) (int, error) {
return l.logger.Write(p) return l.logger.Write(p)
} }
@ -173,7 +186,9 @@ func (l *Logger) Flush() {
} }
func (l *Logger) Shutdown() { func (l *Logger) Shutdown() {
l.cancelFn() if l.cancelFn != nil {
l.cancelFn()
}
l.ticker.Stop() l.ticker.Stop()
l.filch.Close() l.filch.Close()
l.logger.Shutdown(context.Background()) l.logger.Shutdown(context.Background())

Loading…
Cancel
Save