diff --git a/logpolicy/logpolicy.go b/logpolicy/logpolicy.go index 8ba2a2e62..e201df765 100644 --- a/logpolicy/logpolicy.go +++ b/logpolicy/logpolicy.go @@ -520,7 +520,7 @@ func New(collection string) *Policy { } } - c := logtail.Config{ + conf := logtail.Config{ Collection: newc.Collection, PrivateID: newc.PrivateID, Stderr: logWriter{console}, @@ -534,16 +534,16 @@ func New(collection string) *Policy { HTTPC: &http.Client{Transport: NewLogtailTransport(logtail.DefaultHost)}, } if collection == logtail.CollectionNode { - c.MetricsDelta = clientmetric.EncodeLogTailMetricsDelta - c.IncludeProcID = true - c.IncludeProcSequence = true + conf.MetricsDelta = clientmetric.EncodeLogTailMetricsDelta + conf.IncludeProcID = true + conf.IncludeProcSequence = true } if val := getLogTarget(); val != "" { log.Println("You have enabled a non-default log target. Doing without being told to by Tailscale staff or your network administrator will make getting support difficult.") - c.BaseURL = val + conf.BaseURL = val u, _ := url.Parse(val) - c.HTTPC = &http.Client{Transport: NewLogtailTransport(u.Host)} + conf.HTTPC = &http.Client{Transport: NewLogtailTransport(u.Host)} } filchOptions := filch.Options{ @@ -566,16 +566,16 @@ func New(collection string) *Policy { filchBuf, filchErr := filch.New(filchPrefix, filchOptions) if filchBuf != nil { - c.Buffer = filchBuf + conf.Buffer = filchBuf if filchBuf.OrigStderr != nil { - c.Stderr = filchBuf.OrigStderr + conf.Stderr = filchBuf.OrigStderr } } - lw := logtail.NewLogger(c, log.Printf) + lw := logtail.NewLogger(conf, log.Printf) var logOutput io.Writer = lw - if runtime.GOOS == "windows" && c.Collection == logtail.CollectionNode { + if runtime.GOOS == "windows" && conf.Collection == logtail.CollectionNode { logID := newc.PublicID.String() exe, _ := os.Executable() if strings.EqualFold(filepath.Base(exe), "tailscaled.exe") { diff --git a/logtail/buffer.go b/logtail/buffer.go index e33427fc5..196382c49 100644 --- a/logtail/buffer.go +++ b/logtail/buffer.go @@ -21,6 +21,8 @@ type Buffer interface { TryReadLine() ([]byte, error) // Write writes a log line into the ring buffer. + // + // Write takes ownership of the provided slice. Write([]byte) (int, error) } diff --git a/logtail/logtail.go b/logtail/logtail.go index 8d159b358..6da67848f 100644 --- a/logtail/logtail.go +++ b/logtail/logtail.go @@ -167,8 +167,9 @@ type Logger struct { procID uint32 includeProcSequence bool - writeLock sync.Mutex // guards increments of procSequence - procSequence uint64 + + writeLock sync.Mutex // guards increments of procSequence + procSequence uint64 shutdownStart chan struct{} // closed when shutdown begins shutdownDone chan struct{} // closed when shutdown complete @@ -454,7 +455,7 @@ func Disable() { logtailDisabled.Set(true) } -func (l *Logger) send(jsonBlob []byte) (int, error) { +func (l *Logger) sendLocked(jsonBlob []byte) (int, error) { if logtailDisabled.Get() { return len(jsonBlob), nil } @@ -578,7 +579,7 @@ func (l *Logger) encodeText(buf []byte, skipClientTime bool, procID uint32, proc return b } -func (l *Logger) encode(buf []byte, level int) []byte { +func (l *Logger) encodeLocked(buf []byte, level int) []byte { if l.includeProcSequence { l.procSequence++ } @@ -659,10 +660,12 @@ func (l *Logger) Write(buf []byte) (int, error) { l.stderr.Write(withNL) } } + l.writeLock.Lock() - b := l.encode(buf, level) - _, err := l.send(b) - l.writeLock.Unlock() + defer l.writeLock.Unlock() + + b := l.encodeLocked(buf, level) + _, err := l.sendLocked(b) return len(buf), err }