2022-07-12 07:17:29 +00:00
|
|
|
package log
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"time"
|
|
|
|
|
2022-07-30 06:50:33 +00:00
|
|
|
"github.com/sagernet/sing/common"
|
2022-07-12 07:17:29 +00:00
|
|
|
F "github.com/sagernet/sing/common/format"
|
|
|
|
"github.com/sagernet/sing/common/observable"
|
2023-12-04 03:47:25 +00:00
|
|
|
"github.com/sagernet/sing/service/filemanager"
|
2022-07-12 07:17:29 +00:00
|
|
|
)
|
|
|
|
|
2023-12-04 03:47:25 +00:00
|
|
|
var _ Factory = (*defaultFactory)(nil)
|
2022-07-12 07:17:29 +00:00
|
|
|
|
2023-12-04 03:47:25 +00:00
|
|
|
type defaultFactory struct {
|
|
|
|
ctx context.Context
|
2022-10-25 04:55:00 +00:00
|
|
|
formatter Formatter
|
|
|
|
platformFormatter Formatter
|
|
|
|
writer io.Writer
|
2023-12-04 03:47:25 +00:00
|
|
|
file *os.File
|
|
|
|
filePath string
|
2023-11-15 05:05:33 +00:00
|
|
|
platformWriter PlatformWriter
|
2023-12-04 03:47:25 +00:00
|
|
|
needObservable bool
|
2022-10-25 04:55:00 +00:00
|
|
|
level Level
|
|
|
|
subscriber *observable.Subscriber[Entry]
|
|
|
|
observer *observable.Observer[Entry]
|
2022-07-12 07:17:29 +00:00
|
|
|
}
|
|
|
|
|
2023-12-04 03:47:25 +00:00
|
|
|
func NewDefaultFactory(
|
|
|
|
ctx context.Context,
|
|
|
|
formatter Formatter,
|
|
|
|
writer io.Writer,
|
|
|
|
filePath string,
|
|
|
|
platformWriter PlatformWriter,
|
|
|
|
needObservable bool,
|
|
|
|
) ObservableFactory {
|
|
|
|
factory := &defaultFactory{
|
|
|
|
ctx: ctx,
|
2022-10-25 04:55:00 +00:00
|
|
|
formatter: formatter,
|
|
|
|
platformFormatter: Formatter{
|
2023-07-02 08:45:30 +00:00
|
|
|
BaseTime: formatter.BaseTime,
|
|
|
|
DisableLineBreak: true,
|
2022-10-25 04:55:00 +00:00
|
|
|
},
|
|
|
|
writer: writer,
|
2023-12-04 03:47:25 +00:00
|
|
|
filePath: filePath,
|
2022-10-25 04:55:00 +00:00
|
|
|
platformWriter: platformWriter,
|
2023-12-04 03:47:25 +00:00
|
|
|
needObservable: needObservable,
|
2022-10-25 04:55:00 +00:00
|
|
|
level: LevelTrace,
|
|
|
|
subscriber: observable.NewSubscriber[Entry](128),
|
2022-07-12 07:17:29 +00:00
|
|
|
}
|
2023-11-15 05:05:33 +00:00
|
|
|
if platformWriter != nil {
|
|
|
|
factory.platformFormatter.DisableColors = platformWriter.DisableColors()
|
|
|
|
}
|
2024-05-03 07:34:07 +00:00
|
|
|
if needObservable {
|
|
|
|
factory.observer = observable.NewObserver[Entry](factory.subscriber, 64)
|
|
|
|
}
|
2022-07-12 07:17:29 +00:00
|
|
|
return factory
|
|
|
|
}
|
|
|
|
|
2023-12-04 03:47:25 +00:00
|
|
|
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),
|
2024-05-03 07:34:07 +00:00
|
|
|
f.subscriber,
|
2023-12-04 03:47:25 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *defaultFactory) Level() Level {
|
2022-07-12 07:17:29 +00:00
|
|
|
return f.level
|
|
|
|
}
|
|
|
|
|
2023-12-04 03:47:25 +00:00
|
|
|
func (f *defaultFactory) SetLevel(level Level) {
|
2022-07-12 07:17:29 +00:00
|
|
|
f.level = level
|
|
|
|
}
|
|
|
|
|
2023-12-04 03:47:25 +00:00
|
|
|
func (f *defaultFactory) Logger() ContextLogger {
|
2022-07-12 07:17:29 +00:00
|
|
|
return f.NewLogger("")
|
|
|
|
}
|
|
|
|
|
2023-12-04 03:47:25 +00:00
|
|
|
func (f *defaultFactory) NewLogger(tag string) ContextLogger {
|
2022-07-12 07:17:29 +00:00
|
|
|
return &observableLogger{f, tag}
|
|
|
|
}
|
|
|
|
|
2023-12-04 03:47:25 +00:00
|
|
|
func (f *defaultFactory) Subscribe() (subscription observable.Subscription[Entry], done <-chan struct{}, err error) {
|
2022-07-12 07:17:29 +00:00
|
|
|
return f.observer.Subscribe()
|
|
|
|
}
|
|
|
|
|
2023-12-04 03:47:25 +00:00
|
|
|
func (f *defaultFactory) UnSubscribe(sub observable.Subscription[Entry]) {
|
2022-07-12 07:17:29 +00:00
|
|
|
f.observer.UnSubscribe(sub)
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ ContextLogger = (*observableLogger)(nil)
|
|
|
|
|
|
|
|
type observableLogger struct {
|
2023-12-04 03:47:25 +00:00
|
|
|
*defaultFactory
|
2022-07-12 07:17:29 +00:00
|
|
|
tag string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *observableLogger) Log(ctx context.Context, level Level, args []any) {
|
2022-08-03 10:55:39 +00:00
|
|
|
level = OverrideLevelFromContext(level, ctx)
|
2022-07-12 07:17:29 +00:00
|
|
|
if level > l.level {
|
|
|
|
return
|
|
|
|
}
|
2022-10-25 04:55:00 +00:00
|
|
|
nowTime := time.Now()
|
2023-12-04 03:47:25 +00:00
|
|
|
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)
|
|
|
|
}
|
2022-07-12 07:17:29 +00:00
|
|
|
}
|
2022-10-25 04:55:00 +00:00
|
|
|
if l.platformWriter != nil {
|
2023-11-15 05:05:33 +00:00
|
|
|
l.platformWriter.WriteMessage(level, l.platformFormatter.Format(ctx, level, l.tag, F.ToString(args...), nowTime))
|
2022-10-25 04:55:00 +00:00
|
|
|
}
|
2022-07-12 07:17:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *observableLogger) Trace(args ...any) {
|
2022-07-13 11:01:20 +00:00
|
|
|
l.TraceContext(context.Background(), args...)
|
2022-07-12 07:17:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *observableLogger) Debug(args ...any) {
|
2022-07-13 11:01:20 +00:00
|
|
|
l.DebugContext(context.Background(), args...)
|
2022-07-12 07:17:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *observableLogger) Info(args ...any) {
|
2022-07-13 11:01:20 +00:00
|
|
|
l.InfoContext(context.Background(), args...)
|
2022-07-12 07:17:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *observableLogger) Warn(args ...any) {
|
2022-07-13 11:01:20 +00:00
|
|
|
l.WarnContext(context.Background(), args...)
|
2022-07-12 07:17:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *observableLogger) Error(args ...any) {
|
2022-07-13 11:01:20 +00:00
|
|
|
l.ErrorContext(context.Background(), args...)
|
2022-07-12 07:17:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *observableLogger) Fatal(args ...any) {
|
2022-07-13 11:01:20 +00:00
|
|
|
l.FatalContext(context.Background(), args...)
|
2022-07-12 07:17:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *observableLogger) Panic(args ...any) {
|
2022-07-13 11:01:20 +00:00
|
|
|
l.PanicContext(context.Background(), args...)
|
2022-07-12 07:17:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|