fix: align admin behavior and Kratos integrations
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DailyWriter writes log entries to <root>/<yyyy-mm-dd>/<name>. It keeps the
|
||||
// file handle open for the active day and rotates on the first write after
|
||||
// midnight, matching the directory layout consumed by the log viewer.
|
||||
type DailyWriter struct {
|
||||
mu sync.Mutex
|
||||
root string
|
||||
name string
|
||||
date string
|
||||
file *os.File
|
||||
}
|
||||
|
||||
func NewDailyWriter(root, name string) *DailyWriter {
|
||||
return &DailyWriter{root: root, name: name}
|
||||
}
|
||||
|
||||
func (w *DailyWriter) Write(value []byte) (int, error) {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
date := time.Now().Format("2006-01-02")
|
||||
if w.file == nil || w.date != date {
|
||||
if w.file != nil {
|
||||
_ = w.file.Close()
|
||||
}
|
||||
directory := filepath.Join(w.root, date)
|
||||
if err := os.MkdirAll(directory, 0o755); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
file, err := os.OpenFile(filepath.Join(directory, w.name), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
w.file, w.date = file, date
|
||||
}
|
||||
return w.file.Write(value)
|
||||
}
|
||||
|
||||
func (w *DailyWriter) Close() error {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
if w.file == nil {
|
||||
return nil
|
||||
}
|
||||
err := w.file.Close()
|
||||
w.file = nil
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
"github.com/go-kratos/kratos/contrib/otel/v3/tracing"
|
||||
kratoslog "github.com/go-kratos/kratos/v3/log"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/exp/zapslog"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
// NewZapLogger adapts a Zap core to the slog logger used by Kratos v3.
|
||||
// The file layout remains compatible with the administration log viewer.
|
||||
func NewZapLogger(root, filename string, attrs ...any) (*slog.Logger, func()) {
|
||||
file := NewDailyWriter(root, filename)
|
||||
encoder := zap.NewProductionEncoderConfig()
|
||||
encoder.EncodeTime = zapcore.ISO8601TimeEncoder
|
||||
encoder.EncodeLevel = zapcore.LowercaseLevelEncoder
|
||||
core := zapcore.NewCore(
|
||||
zapcore.NewJSONEncoder(encoder),
|
||||
zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(file)),
|
||||
zap.NewAtomicLevelAt(zap.InfoLevel),
|
||||
)
|
||||
zapLogger := zap.New(core)
|
||||
handler := zapslog.NewHandler(zapLogger.Core(), zapslog.WithCaller(true), zapslog.AddStacktraceAt(slog.LevelError))
|
||||
logger := kratoslog.NewLogger(handler, kratoslog.WithExtractor(tracing.TraceAttrs)).With(attrs...)
|
||||
cleanup := func() {
|
||||
_ = zapLogger.Sync()
|
||||
_ = file.Close()
|
||||
}
|
||||
return logger, cleanup
|
||||
}
|
||||
Reference in New Issue
Block a user