Sync and async sinks, redaction, and a queryable HTTP service keep concurrent logs tied to a trace id. Co-authored-by: Cursor <cursoragent@cursor.com>
57 lines
1.1 KiB
Go
57 lines
1.1 KiB
Go
package sink
|
|
|
|
import (
|
|
"io"
|
|
"os"
|
|
"sync"
|
|
|
|
"logging-system/logsys"
|
|
)
|
|
|
|
// Console 把日志写到 io.Writer。Format 为 human 或 json,空值按 human。
|
|
type Console struct {
|
|
mu sync.Mutex
|
|
Out io.Writer
|
|
Format string
|
|
}
|
|
|
|
// Write 写入一行。
|
|
func (c *Console) Write(e logsys.Entry) error {
|
|
if c.Out == nil {
|
|
c.Out = os.Stderr
|
|
}
|
|
line, err := formatLine(c.Format, e, true)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
_, err = c.Out.Write(line)
|
|
return err
|
|
}
|
|
|
|
// Sync 无独立缓冲。
|
|
func (c *Console) Sync() error { return nil }
|
|
|
|
// Close 不关闭底层 Writer(它通常是 stderr)。
|
|
func (c *Console) Close() error { return nil }
|
|
|
|
func formatLine(format string, e logsys.Entry, humanDefault bool) ([]byte, error) {
|
|
if format == "" && humanDefault {
|
|
format = "human"
|
|
}
|
|
if format == "" || format == "json" {
|
|
return logsys.FormatJSON(e)
|
|
}
|
|
if format == "human" {
|
|
return []byte(logsys.FormatHuman(e)), nil
|
|
}
|
|
return nil, errFormat(format)
|
|
}
|
|
|
|
type formatError string
|
|
|
|
func errFormat(f string) error { return formatError(f) }
|
|
|
|
func (f formatError) Error() string { return "sink: unknown format " + string(f) }
|