Skip to content

Commit 42783a1

Browse files
committed
Remove null byte from log output
Strip the [v\x00JSON] prefix used by logtail for structured logging before passing log messages to user-defined Logf. This prevents null bytes from appearing in log files when the logging bypasses logtail processing. Fixes: SagerNet/sing-box#3481
1 parent 46e097f commit 42783a1

File tree

1 file changed

+26
-1
lines changed

1 file changed

+26
-1
lines changed

tsnet/tsnet.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,12 @@ func (s *Server) start() (reterr error) {
573573
if s.Logf == nil {
574574
return
575575
}
576-
s.Logf(format, a...)
576+
// Format the log message and remove the [v\x00JSON] prefix
577+
// that is used internally by logtail for structured logging.
578+
// See: https://github.com/SagerNet/sing-box/issues/3481
579+
msg := fmt.Sprintf(format, a...)
580+
msg = removeJSONLogPrefix(msg)
581+
s.Logf("%s", msg)
577582
}
578583

579584
sys := tsd.NewSystem()
@@ -1371,3 +1376,23 @@ type addr struct{ ln *listener }
13711376

13721377
func (a addr) Network() string { return a.ln.keys[0].network }
13731378
func (a addr) String() string { return a.ln.addr }
1379+
1380+
// vJSONPrefix is the magic prefix used by logtail for structured JSON logging.
1381+
// The null byte (\x00) is used as a marker that logtail recognizes and strips,
1382+
// but if the log bypasses logtail processing, it appears in the output.
1383+
const vJSONPrefix = "[v\x00JSON]"
1384+
1385+
// removeJSONLogPrefix removes the [v\x00JSON] prefix and log level digit
1386+
// from a log message. This prefix is used internally by tailscale's logger
1387+
// for structured logging, but should not appear in user-visible logs.
1388+
func removeJSONLogPrefix(msg string) string {
1389+
if idx := strings.Index(msg, vJSONPrefix); idx != -1 {
1390+
rest := msg[idx+len(vJSONPrefix):]
1391+
if len(rest) >= 1 && rest[0] >= '0' && rest[0] <= '9' {
1392+
// Skip the log level digit
1393+
return msg[:idx] + rest[1:]
1394+
}
1395+
return msg[:idx] + rest
1396+
}
1397+
return msg
1398+
}

0 commit comments

Comments
 (0)