mirror of
https://gitea.com/gitea/runner.git
synced 2026-11-05 23:05:45 +00:00
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]>
88 lines
2.0 KiB
Go
88 lines
2.0 KiB
Go
// 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
|
|
}
|
|
}
|