精简后的项目:仅保留 api/ui 源码、文档、构建依赖
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
var defaultLogger *slog.Logger
|
||||
|
||||
func init() {
|
||||
defaultLogger = slog.Default()
|
||||
}
|
||||
|
||||
type loggerKeyType string
|
||||
|
||||
const loggerKey loggerKeyType = "logger"
|
||||
|
||||
func getLogger(ctx context.Context) *slog.Logger {
|
||||
if ctx == nil {
|
||||
return defaultLogger
|
||||
}
|
||||
|
||||
logger := ctx.Value(loggerKey)
|
||||
if logger == nil {
|
||||
return defaultLogger
|
||||
}
|
||||
|
||||
ret, ok := logger.(*slog.Logger)
|
||||
if !ok {
|
||||
return defaultLogger
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// WithAttrs creates a new context containing a new logger with [args] as logging attributes.
|
||||
func WithAttrs(ctx context.Context, args ...any) context.Context {
|
||||
old := getLogger(ctx)
|
||||
new := old.With(args...)
|
||||
return context.WithValue(ctx, loggerKey, new)
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"log/slog"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
_ "github.com/photoview/photoview/api/test_utils/flags"
|
||||
)
|
||||
|
||||
func mockDefaultLogger(t *testing.T) *bytes.Buffer {
|
||||
t.Helper()
|
||||
|
||||
var output bytes.Buffer
|
||||
handler := slog.NewJSONHandler(&output, &slog.HandlerOptions{
|
||||
AddSource: false,
|
||||
Level: slog.LevelInfo,
|
||||
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
|
||||
// Remove time from the output for predictable test output.
|
||||
if a.Key == slog.TimeKey {
|
||||
return slog.Attr{}
|
||||
}
|
||||
return a
|
||||
},
|
||||
})
|
||||
|
||||
logger := slog.New(handler)
|
||||
oldLogger := defaultLogger
|
||||
defaultLogger = logger
|
||||
|
||||
t.Cleanup(func() {
|
||||
defaultLogger = oldLogger
|
||||
})
|
||||
|
||||
return &output
|
||||
}
|
||||
|
||||
func TestLogger(t *testing.T) {
|
||||
output := mockDefaultLogger(t)
|
||||
|
||||
Debug(nil, "no_context")
|
||||
Info(nil, "no_context")
|
||||
Warn(nil, "no_context")
|
||||
Error(nil, "no_context")
|
||||
|
||||
bg := context.Background()
|
||||
|
||||
Debug(bg, "bg_context")
|
||||
Info(bg, "bg_context")
|
||||
Warn(bg, "bg_context")
|
||||
Error(bg, "bg_context")
|
||||
|
||||
ctx1 := WithAttrs(context.Background(), "arg1", "value")
|
||||
Debug(ctx1, "with_context_1")
|
||||
Info(ctx1, "with_context_1")
|
||||
Warn(ctx1, "with_context_1")
|
||||
Error(ctx1, "with_context_1")
|
||||
|
||||
ctx2 := WithAttrs(ctx1, "arg2", "value")
|
||||
Debug(ctx2, "with_context_2")
|
||||
Info(ctx2, "with_context_2")
|
||||
Warn(ctx2, "with_context_2")
|
||||
Error(ctx2, "with_context_2")
|
||||
|
||||
Debug(ctx1, "with_context_1")
|
||||
Info(ctx1, "with_context_1")
|
||||
Warn(ctx1, "with_context_1")
|
||||
Error(ctx1, "with_context_1")
|
||||
|
||||
// Debug messages are filtered out due to slog.LevelInfo in mock logger
|
||||
want := `{"level":"INFO","msg":"no_context"}
|
||||
{"level":"WARN","msg":"no_context"}
|
||||
{"level":"ERROR","msg":"no_context"}
|
||||
{"level":"INFO","msg":"bg_context"}
|
||||
{"level":"WARN","msg":"bg_context"}
|
||||
{"level":"ERROR","msg":"bg_context"}
|
||||
{"level":"INFO","msg":"with_context_1","arg1":"value"}
|
||||
{"level":"WARN","msg":"with_context_1","arg1":"value"}
|
||||
{"level":"ERROR","msg":"with_context_1","arg1":"value"}
|
||||
{"level":"INFO","msg":"with_context_2","arg1":"value","arg2":"value"}
|
||||
{"level":"WARN","msg":"with_context_2","arg1":"value","arg2":"value"}
|
||||
{"level":"ERROR","msg":"with_context_2","arg1":"value","arg2":"value"}
|
||||
{"level":"INFO","msg":"with_context_1","arg1":"value"}
|
||||
{"level":"WARN","msg":"with_context_1","arg1":"value"}
|
||||
{"level":"ERROR","msg":"with_context_1","arg1":"value"}
|
||||
`
|
||||
if diff := cmp.Diff(output.String(), want); diff != "" {
|
||||
t.Errorf("diff: (-got, +want)\n%s", diff)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// Debug logs debug messages.
|
||||
func Debug(ctx context.Context, msg string, args ...any) {
|
||||
getLogger(ctx).DebugContext(ctx, msg, args...)
|
||||
}
|
||||
|
||||
// Info logs info messages.
|
||||
func Info(ctx context.Context, msg string, args ...any) {
|
||||
getLogger(ctx).InfoContext(ctx, msg, args...)
|
||||
}
|
||||
|
||||
// Warn logs warning messages.
|
||||
func Warn(ctx context.Context, msg string, args ...any) {
|
||||
getLogger(ctx).WarnContext(ctx, msg, args...)
|
||||
}
|
||||
|
||||
// Error logs error messages.
|
||||
func Error(ctx context.Context, msg string, args ...any) {
|
||||
getLogger(ctx).ErrorContext(ctx, msg, args...)
|
||||
}
|
||||
Reference in New Issue
Block a user