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:
Lunny Xiaoandbircni committed 2026-10-11 23:26:00 +00:00
1 parent ad9eeb668a
commit de961b91eb
50 files changed
+1241 -438

No files matched your search

+2 -1
View File
@@ -8,6 +8,7 @@ import (
"fmt"
"gitea.com/gitea/runner/act/artifactcache"
"gitea.com/gitea/runner/act/common/logging"
"gitea.com/gitea/runner/internal/app/run"
"gitea.com/gitea/runner/internal/pkg/config"
@@ -60,7 +61,7 @@ func runCacheServer(configFile *string, cacheArgs *cacheServerArgs) func(cmd *co
Port: port,
InternalSecret: secret,
Policy: run.CachePolicy(cfg),
Logger: log.StandardLogger().WithField("module", "cache_request"),
Logger: logging.Default().With("module", "cache_request"),
})
if err != nil {
return err
+3 -2
View File
@@ -23,6 +23,7 @@ import (
"gitea.com/gitea/runner/act/artifactcache"
"gitea.com/gitea/runner/act/artifacts"
"gitea.com/gitea/runner/act/common"
"gitea.com/gitea/runner/act/common/logging"
"gitea.com/gitea/runner/act/runner"
"gitea.com/gitea/runner/internal/app/run"
"gitea.com/gitea/runner/internal/pkg/config"
@@ -482,7 +483,7 @@ func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command
// init a cache server
handler, err := artifactcache.StartHandler(artifactcache.Options{
Policy: run.CachePolicy(&config.Config{Cache: config.DefaultCache()}),
Logger: log.StandardLogger().WithField("module", "cache_request"),
Logger: logging.Default().With("module", "cache_request"),
})
if err != nil {
return err
@@ -553,7 +554,7 @@ func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command
}
if !execArgs.debug {
logLevel := log.InfoLevel
logLevel := logging.LevelInfo
config.JobLoggerLevel = &logLevel
}
+5 -11
View File
@@ -4,21 +4,15 @@
package run
import (
"io"
log "github.com/sirupsen/logrus"
"gitea.com/gitea/runner/act/common/logging"
)
// NullLogger is used to create a new JobLogger to discard logs. This
// will prevent these logs from being logged to the stdout, but
// forward them to the Reporter via its hook.
// forward them to the Reporter via its handler.
type NullLogger struct{}
// WithJobLogger creates a new logrus.Logger that will discard all logs.
func (n NullLogger) WithJobLogger() *log.Logger {
logger := log.New()
logger.SetOutput(io.Discard)
logger.SetLevel(log.TraceLevel)
return logger
// WithJobLogger returns a handler that discards all logs.
func (n NullLogger) WithJobLogger() logging.Handler {
return logging.DiscardHandler
}
+5 -5
View File
@@ -10,12 +10,12 @@ import (
"testing"
"time"
"gitea.com/gitea/runner/act/common/logging"
"gitea.com/gitea/runner/internal/pkg/config"
"gitea.com/gitea/runner/internal/pkg/metrics"
"gitea.com/gitea/runner/internal/pkg/report"
runnerv1 "gitea.dev/actionslib/runner/v1"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/structpb"
@@ -146,12 +146,12 @@ func TestRunPostTaskScriptIntegration(t *testing.T) {
func setReporterJobResult(t *testing.T, reporter *report.Reporter, result runnerv1.Result) {
t.Helper()
require.NoError(t, reporter.Fire(&log.Entry{
require.NoError(t, reporter.Handle(t.Context(), logging.Record{
Time: time.Now(),
Message: "job finished",
Data: log.Fields{
"stage": "Post",
"jobResult": metrics.ResultToStatusLabel(result),
Attrs: []logging.Attr{
{Key: "stage", Value: "Post"},
{Key: "jobResult", Value: metrics.ResultToStatusLabel(result)},
},
}))
}
+3 -2
View File
@@ -28,6 +28,7 @@ import (
"gitea.com/gitea/runner/act/artifactcache"
"gitea.com/gitea/runner/act/common"
"gitea.com/gitea/runner/act/common/logging"
"gitea.com/gitea/runner/act/container"
"gitea.com/gitea/runner/act/runner"
"gitea.com/gitea/runner/internal/pkg/client"
@@ -109,7 +110,7 @@ func NewRunner(cfg *config.Config, reg *config.Registration, cli client.Client)
Upstream: cfg.Cache.ExternalServer,
S3: cacheS3(cfg),
Policy: CachePolicy(cfg),
Logger: log.StandardLogger().WithField("module", "cache_request"),
Logger: logging.Default().With("module", "cache_request"),
})
if err != nil {
log.Errorf("cannot init cache server, it will be disabled: %v", err)
@@ -645,7 +646,7 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
reporter.Logf("workflow prepared")
// add logger recorders
ctx = common.WithLoggerHook(ctx, reporter)
ctx = common.WithLoggerHandler(ctx, reporter)
if !log.IsLevelEnabled(log.DebugLevel) {
ctx = runner.WithJobLoggerFactory(ctx, NullLogger{})
+4 -3
View File
@@ -18,6 +18,7 @@ import (
"time"
"gitea.com/gitea/runner/act/common"
"gitea.com/gitea/runner/act/common/logging"
"gitea.com/gitea/runner/act/runner"
clientmocks "gitea.com/gitea/runner/internal/pkg/client/mocks"
"gitea.com/gitea/runner/internal/pkg/config"
@@ -79,9 +80,9 @@ func TestRunnerRunningCountAndNullLogger(t *testing.T) {
r.runningCount.Add(2)
require.Equal(t, int64(2), r.RunningCount())
logger := NullLogger{}.WithJobLogger()
require.NotNil(t, logger)
require.NotNil(t, logger.Out)
handler := NullLogger{}.WithJobLogger()
require.NotNil(t, handler)
require.False(t, handler.Enabled(t.Context(), logging.LevelError))
}
func TestRunnerReclaimsVolumesAfterReporting(t *testing.T) {