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>
92 lines
1.5 KiB
Go
92 lines
1.5 KiB
Go
package sink
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"logging-system/logsys"
|
|
)
|
|
|
|
// Fanout 把同一条日志写到多个出口。单个出口失败不影响其他出口。
|
|
type Fanout struct {
|
|
Sinks []logsys.Sink
|
|
}
|
|
|
|
// Write 逐个写入。
|
|
func (f Fanout) Write(e logsys.Entry) error {
|
|
var errs []error
|
|
for _, s := range f.Sinks {
|
|
if s == nil {
|
|
continue
|
|
}
|
|
if err := s.Write(e); err != nil {
|
|
errs = append(errs, err)
|
|
}
|
|
}
|
|
return errors.Join(errs...)
|
|
}
|
|
|
|
// Sync 刷出全部出口。
|
|
func (f Fanout) Sync() error {
|
|
var errs []error
|
|
for _, s := range f.Sinks {
|
|
if s == nil {
|
|
continue
|
|
}
|
|
if err := s.Sync(); err != nil {
|
|
errs = append(errs, err)
|
|
}
|
|
}
|
|
return errors.Join(errs...)
|
|
}
|
|
|
|
// Close 关闭全部出口。
|
|
func (f Fanout) Close() error {
|
|
var errs []error
|
|
for _, s := range f.Sinks {
|
|
if s == nil {
|
|
continue
|
|
}
|
|
if err := s.Close(); err != nil {
|
|
errs = append(errs, err)
|
|
}
|
|
}
|
|
return errors.Join(errs...)
|
|
}
|
|
|
|
// MinLevel 丢弃低于阈值的日志。
|
|
type MinLevel struct {
|
|
Min logsys.Level
|
|
Next logsys.Sink
|
|
}
|
|
|
|
// Write 在级别足够时转发。
|
|
func (m MinLevel) Write(e logsys.Entry) error {
|
|
lv, err := logsys.ParseLevel(e.Level)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if lv < m.Min {
|
|
return nil
|
|
}
|
|
if m.Next == nil {
|
|
return nil
|
|
}
|
|
return m.Next.Write(e)
|
|
}
|
|
|
|
// Sync 转发。
|
|
func (m MinLevel) Sync() error {
|
|
if m.Next == nil {
|
|
return nil
|
|
}
|
|
return m.Next.Sync()
|
|
}
|
|
|
|
// Close 转发。
|
|
func (m MinLevel) Close() error {
|
|
if m.Next == nil {
|
|
return nil
|
|
}
|
|
return m.Next.Close()
|
|
}
|