mirror of
https://gitea.com/gitea/runner.git
synced 2026-11-13 03:13:42 +00:00
refactor(logging): add a logging abstraction and move the job logger onto it (#1295)
Add `act/common/logging`: a printf-style `Logger` on a slog-shaped `Handler`, with a logrus-backed handler as the only backend, plus a `logtest` handler for tests. Move the job logger onto it: `common.Logger` returns `*logging.Logger`, the job log formatters and the `Reporter` hook become handlers, and composite step IDs travel in the context. Logging is tightly coupled to logrus types (hooks, formatters, `Entry.Data`). Going through our own interface first lets the remaining call sites move over with unchanged behavior, and lets the backend be swapped for `log/slog` in one place afterwards. The global process logger and its masking formatter stay on logrus for now. Assisted-by: Codet Co-authored-by: bircni <[email protected]> Reviewed-on: https://gitea.com/gitea/runner/pulls/1295 Reviewed-by: bircni <[email protected]>
This commit is contained in:
1 parent
ad9eeb668a
commit
de961b91eb
50 files changed
+1241
-438
No files matched your search
@@ -0,0 +1,87 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type logrusHandler struct {
|
||||
entry *logrus.Entry
|
||||
}
|
||||
|
||||
// NewLogrusHandler writes to l, so its level, hooks, formatter and output all apply.
|
||||
func NewLogrusHandler(l *logrus.Logger) Handler {
|
||||
return &logrusHandler{entry: logrus.NewEntry(l)}
|
||||
}
|
||||
|
||||
func (h *logrusHandler) Enabled(_ context.Context, level Level) bool {
|
||||
return h.entry.Logger.IsLevelEnabled(toLogrusLevel(level))
|
||||
}
|
||||
|
||||
func (h *logrusHandler) Handle(ctx context.Context, r Record) error {
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
e := h.entry.WithContext(ctx) // always a copy, so the fields below never reach h.entry
|
||||
if !r.Time.IsZero() {
|
||||
e = e.WithTime(r.Time)
|
||||
}
|
||||
if len(r.Attrs) > 0 {
|
||||
e = e.WithFields(attrsToFields(r.Attrs))
|
||||
}
|
||||
if r.PC != 0 && e.Logger.ReportCaller {
|
||||
// logrus only skips its own frames, so without this it would report the logging package
|
||||
frame, _ := runtime.CallersFrames([]uintptr{r.PC}).Next()
|
||||
e.Caller = &frame
|
||||
}
|
||||
e.Log(toLogrusLevel(r.Level), r.Message)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *logrusHandler) WithAttrs(attrs []Attr) Handler {
|
||||
return &logrusHandler{entry: h.entry.WithFields(attrsToFields(attrs))}
|
||||
}
|
||||
|
||||
func attrsToFields(attrs []Attr) logrus.Fields {
|
||||
fields := make(logrus.Fields, len(attrs))
|
||||
for _, a := range attrs {
|
||||
fields[a.Key] = a.Value
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
func toLogrusLevel(l Level) logrus.Level {
|
||||
switch {
|
||||
case l <= LevelTrace:
|
||||
return logrus.TraceLevel
|
||||
case l <= LevelDebug:
|
||||
return logrus.DebugLevel
|
||||
case l <= LevelInfo:
|
||||
return logrus.InfoLevel
|
||||
case l <= LevelWarn:
|
||||
return logrus.WarnLevel
|
||||
default:
|
||||
return logrus.ErrorLevel
|
||||
}
|
||||
}
|
||||
|
||||
// fromLogrusLevel maps logrus's Fatal and Panic to LevelError.
|
||||
func fromLogrusLevel(l logrus.Level) Level {
|
||||
switch l {
|
||||
case logrus.TraceLevel:
|
||||
return LevelTrace
|
||||
case logrus.DebugLevel:
|
||||
return LevelDebug
|
||||
case logrus.InfoLevel:
|
||||
return LevelInfo
|
||||
case logrus.WarnLevel:
|
||||
return LevelWarn
|
||||
default:
|
||||
return LevelError
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user