123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- package log
- import (
- "context"
- "io"
- "os"
- "time"
- "github.com/sagernet/sing/common"
- F "github.com/sagernet/sing/common/format"
- "github.com/sagernet/sing/common/observable"
- "github.com/sagernet/sing/service/filemanager"
- )
- var _ Factory = (*defaultFactory)(nil)
- type defaultFactory struct {
- ctx context.Context
- formatter Formatter
- platformFormatter Formatter
- writer io.Writer
- file *os.File
- filePath string
- platformWriter PlatformWriter
- needObservable bool
- level Level
- subscriber *observable.Subscriber[Entry]
- observer *observable.Observer[Entry]
- }
- func NewDefaultFactory(
- ctx context.Context,
- formatter Formatter,
- writer io.Writer,
- filePath string,
- platformWriter PlatformWriter,
- needObservable bool,
- ) ObservableFactory {
- factory := &defaultFactory{
- ctx: ctx,
- formatter: formatter,
- platformFormatter: Formatter{
- BaseTime: formatter.BaseTime,
- DisableLineBreak: true,
- },
- writer: writer,
- filePath: filePath,
- platformWriter: platformWriter,
- needObservable: needObservable,
- level: LevelTrace,
- subscriber: observable.NewSubscriber[Entry](128),
- }
- if platformWriter != nil {
- factory.platformFormatter.DisableColors = platformWriter.DisableColors()
- }
- if needObservable {
- factory.observer = observable.NewObserver[Entry](factory.subscriber, 64)
- }
- return factory
- }
- func (f *defaultFactory) Start() error {
- if f.filePath != "" {
- logFile, err := filemanager.OpenFile(f.ctx, f.filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
- if err != nil {
- return err
- }
- f.writer = logFile
- f.file = logFile
- }
- return nil
- }
- func (f *defaultFactory) Close() error {
- return common.Close(
- common.PtrOrNil(f.file),
- f.subscriber,
- )
- }
- func (f *defaultFactory) Level() Level {
- return f.level
- }
- func (f *defaultFactory) SetLevel(level Level) {
- f.level = level
- }
- func (f *defaultFactory) Logger() ContextLogger {
- return f.NewLogger("")
- }
- func (f *defaultFactory) NewLogger(tag string) ContextLogger {
- return &observableLogger{f, tag}
- }
- func (f *defaultFactory) Subscribe() (subscription observable.Subscription[Entry], done <-chan struct{}, err error) {
- return f.observer.Subscribe()
- }
- func (f *defaultFactory) UnSubscribe(sub observable.Subscription[Entry]) {
- f.observer.UnSubscribe(sub)
- }
- var _ ContextLogger = (*observableLogger)(nil)
- type observableLogger struct {
- *defaultFactory
- tag string
- }
- func (l *observableLogger) Log(ctx context.Context, level Level, args []any) {
- level = OverrideLevelFromContext(level, ctx)
- if level > l.level {
- return
- }
- nowTime := time.Now()
- if l.needObservable {
- message, messageSimple := l.formatter.FormatWithSimple(ctx, level, l.tag, F.ToString(args...), nowTime)
- if level == LevelPanic {
- panic(message)
- }
- l.writer.Write([]byte(message))
- if level == LevelFatal {
- os.Exit(1)
- }
- l.subscriber.Emit(Entry{level, messageSimple})
- } else {
- message := l.formatter.Format(ctx, level, l.tag, F.ToString(args...), nowTime)
- if level == LevelPanic {
- panic(message)
- }
- l.writer.Write([]byte(message))
- if level == LevelFatal {
- os.Exit(1)
- }
- }
- if l.platformWriter != nil {
- l.platformWriter.WriteMessage(level, l.platformFormatter.Format(ctx, level, l.tag, F.ToString(args...), nowTime))
- }
- }
- func (l *observableLogger) Trace(args ...any) {
- l.TraceContext(context.Background(), args...)
- }
- func (l *observableLogger) Debug(args ...any) {
- l.DebugContext(context.Background(), args...)
- }
- func (l *observableLogger) Info(args ...any) {
- l.InfoContext(context.Background(), args...)
- }
- func (l *observableLogger) Warn(args ...any) {
- l.WarnContext(context.Background(), args...)
- }
- func (l *observableLogger) Error(args ...any) {
- l.ErrorContext(context.Background(), args...)
- }
- func (l *observableLogger) Fatal(args ...any) {
- l.FatalContext(context.Background(), args...)
- }
- func (l *observableLogger) Panic(args ...any) {
- l.PanicContext(context.Background(), args...)
- }
- func (l *observableLogger) TraceContext(ctx context.Context, args ...any) {
- l.Log(ctx, LevelTrace, args)
- }
- func (l *observableLogger) DebugContext(ctx context.Context, args ...any) {
- l.Log(ctx, LevelDebug, args)
- }
- func (l *observableLogger) InfoContext(ctx context.Context, args ...any) {
- l.Log(ctx, LevelInfo, args)
- }
- func (l *observableLogger) WarnContext(ctx context.Context, args ...any) {
- l.Log(ctx, LevelWarn, args)
- }
- func (l *observableLogger) ErrorContext(ctx context.Context, args ...any) {
- l.Log(ctx, LevelError, args)
- }
- func (l *observableLogger) FatalContext(ctx context.Context, args ...any) {
- l.Log(ctx, LevelFatal, args)
- }
- func (l *observableLogger) PanicContext(ctx context.Context, args ...any) {
- l.Log(ctx, LevelPanic, args)
- }
|