75f3dd141c
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CI and Release / lint-frontend (push) Has been cancelled
CI and Release / dockerfile-scan (push) Has been cancelled
CI and Release / test-frontend (push) Has been cancelled
CI and Release / lint-verification-agent (push) Has been cancelled
CI and Release / test-verification-agent (push) Has been cancelled
CI and Release / e2e-verification-agent (push) Has been cancelled
CI and Release / test-backend (push) Has been cancelled
CI and Release / build-dev-image (push) Has been cancelled
CI and Release / push-dev-image (push) Has been cancelled
CI and Release / build-image (push) Has been cancelled
CI and Release / build-verification-image (push) Has been cancelled
CI and Release / determine-version (push) Has been cancelled
CI and Release / push-image (push) Has been cancelled
CI and Release / push-verification-image (12) (push) Has been cancelled
CI and Release / lint-backend (push) Has been cancelled
CI and Release / push-verification-image (17) (push) Has been cancelled
CI and Release / push-verification-image (18) (push) Has been cancelled
CI and Release / release (push) Has been cancelled
CI and Release / publish-helm-chart (push) Has been cancelled
CI and Release / push-verification-image (13) (push) Has been cancelled
CI and Release / push-verification-image (14) (push) Has been cancelled
CI and Release / push-verification-image (15) (push) Has been cancelled
CI and Release / push-verification-image (16) (push) Has been cancelled
116 lines
2.4 KiB
Go
116 lines
2.4 KiB
Go
package logger
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"log/slog"
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
logFileName = "databasus-verification.log"
|
|
oldLogFileName = "databasus-verification.log.old"
|
|
maxLogFileSize = 5 * 1024 * 1024 // 5MB
|
|
)
|
|
|
|
type rotatingWriter struct {
|
|
mu sync.Mutex
|
|
file *os.File
|
|
currentSize int64
|
|
maxSize int64
|
|
logPath string
|
|
oldLogPath string
|
|
}
|
|
|
|
func (w *rotatingWriter) Write(p []byte) (int, error) {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
|
|
if w.currentSize+int64(len(p)) > w.maxSize {
|
|
if err := w.rotate(); err != nil {
|
|
return 0, fmt.Errorf("failed to rotate log file: %w", err)
|
|
}
|
|
}
|
|
|
|
n, err := w.file.Write(p)
|
|
w.currentSize += int64(n)
|
|
|
|
return n, err
|
|
}
|
|
|
|
func (w *rotatingWriter) rotate() error {
|
|
if err := w.file.Close(); err != nil {
|
|
return fmt.Errorf("failed to close %s: %w", w.logPath, err)
|
|
}
|
|
|
|
if err := os.Remove(w.oldLogPath); err != nil && !os.IsNotExist(err) {
|
|
return fmt.Errorf("failed to remove %s: %w", w.oldLogPath, err)
|
|
}
|
|
|
|
if err := os.Rename(w.logPath, w.oldLogPath); err != nil {
|
|
return fmt.Errorf("failed to rename %s to %s: %w", w.logPath, w.oldLogPath, err)
|
|
}
|
|
|
|
f, err := os.OpenFile(w.logPath, os.O_CREATE|os.O_WRONLY, 0o644)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create new %s: %w", w.logPath, err)
|
|
}
|
|
|
|
w.file = f
|
|
w.currentSize = 0
|
|
|
|
return nil
|
|
}
|
|
|
|
var loggerInstance *slog.Logger
|
|
|
|
var initLogger = sync.OnceFunc(initialize)
|
|
|
|
func GetLogger() *slog.Logger {
|
|
initLogger()
|
|
return loggerInstance
|
|
}
|
|
|
|
func initialize() {
|
|
writer := buildWriter()
|
|
|
|
loggerInstance = slog.New(slog.NewTextHandler(writer, &slog.HandlerOptions{
|
|
Level: slog.LevelInfo,
|
|
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
|
|
if a.Key == slog.TimeKey {
|
|
a.Value = slog.StringValue(time.Now().Format("2006/01/02 15:04:05"))
|
|
}
|
|
if a.Key == slog.LevelKey {
|
|
return slog.Attr{}
|
|
}
|
|
|
|
return a
|
|
},
|
|
}))
|
|
}
|
|
|
|
func buildWriter() io.Writer {
|
|
f, err := os.OpenFile(logFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Warning: failed to open %s for logging: %v\n", logFileName, err)
|
|
return os.Stdout
|
|
}
|
|
|
|
var currentSize int64
|
|
if info, err := f.Stat(); err == nil {
|
|
currentSize = info.Size()
|
|
}
|
|
|
|
rw := &rotatingWriter{
|
|
file: f,
|
|
currentSize: currentSize,
|
|
maxSize: maxLogFileSize,
|
|
logPath: logFileName,
|
|
oldLogPath: oldLogFileName,
|
|
}
|
|
|
|
return io.MultiWriter(os.Stdout, rw)
|
|
}
|