mirror of
https://gitea.com/gitea/act_runner.git
synced 2026-11-01 04:48:49 +08: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 <bircni@icloud.com> Reviewed-on: https://gitea.com/gitea/runner/pulls/1295 Reviewed-by: bircni <bircni@icloud.com>
115 lines
2.9 KiB
Go
115 lines
2.9 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package logging
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"slices"
|
|
"time"
|
|
)
|
|
|
|
// Attr is a structured key/value pair attached to a log record.
|
|
type Attr struct {
|
|
Key string
|
|
Value any
|
|
}
|
|
|
|
// Record is one log event. Attrs holds the call-site attributes only, the ones added with
|
|
// Logger.With are accumulated by the Handler.
|
|
type Record struct {
|
|
Time time.Time
|
|
Level Level
|
|
Message string
|
|
PC uintptr // program counter of the logging call, 0 if unknown
|
|
Attrs []Attr
|
|
}
|
|
|
|
// Attr returns the value of the last attribute named key.
|
|
func (r Record) Attr(key string) (any, bool) {
|
|
for _, a := range slices.Backward(r.Attrs) {
|
|
if a.Key == key {
|
|
return a.Value, true
|
|
}
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
// Handler consumes records, and is shaped like slog.Handler so that a slog backend can replace
|
|
// the current one without touching callers. Handle must not modify the Attrs slice it is given.
|
|
type Handler interface {
|
|
Enabled(ctx context.Context, level Level) bool
|
|
Handle(ctx context.Context, r Record) error
|
|
// WithAttrs returns a Handler that adds attrs to every record it handles.
|
|
WithAttrs(attrs []Attr) Handler
|
|
}
|
|
|
|
type multiHandler []Handler
|
|
|
|
// NewMultiHandler fans every record out to all handlers that have its level enabled.
|
|
func NewMultiHandler(handlers ...Handler) Handler {
|
|
return multiHandler(handlers)
|
|
}
|
|
|
|
func (m multiHandler) Enabled(ctx context.Context, level Level) bool {
|
|
for _, h := range m {
|
|
if h.Enabled(ctx, level) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (m multiHandler) Handle(ctx context.Context, r Record) error {
|
|
var errs []error
|
|
for _, h := range m {
|
|
if h.Enabled(ctx, r.Level) {
|
|
errs = append(errs, h.Handle(ctx, r))
|
|
}
|
|
}
|
|
return errors.Join(errs...)
|
|
}
|
|
|
|
func (m multiHandler) WithAttrs(attrs []Attr) Handler {
|
|
out := make(multiHandler, len(m))
|
|
for i, h := range m {
|
|
out[i] = h.WithAttrs(attrs)
|
|
}
|
|
return out
|
|
}
|
|
|
|
type discardHandler struct{}
|
|
|
|
// DiscardHandler drops every record.
|
|
var DiscardHandler Handler = discardHandler{}
|
|
|
|
func (discardHandler) Enabled(context.Context, Level) bool { return false }
|
|
func (discardHandler) Handle(context.Context, Record) error { return nil }
|
|
func (d discardHandler) WithAttrs([]Attr) Handler { return d }
|
|
|
|
type levelHandler struct {
|
|
h Handler
|
|
minLevel Level
|
|
}
|
|
|
|
// NewLevelHandler passes only records at or above minLevel on to h.
|
|
func NewLevelHandler(h Handler, minLevel Level) Handler {
|
|
return levelHandler{h: h, minLevel: minLevel}
|
|
}
|
|
|
|
func (l levelHandler) Enabled(ctx context.Context, level Level) bool {
|
|
return level >= l.minLevel && l.h.Enabled(ctx, level)
|
|
}
|
|
|
|
func (l levelHandler) Handle(ctx context.Context, r Record) error {
|
|
if r.Level < l.minLevel {
|
|
return nil
|
|
}
|
|
return l.h.Handle(ctx, r)
|
|
}
|
|
|
|
func (l levelHandler) WithAttrs(attrs []Attr) Handler {
|
|
return levelHandler{h: l.h.WithAttrs(attrs), minLevel: l.minLevel}
|
|
}
|