Log
Named log channels and multi-output logging
log is based on the standard library slog. It provides named log channels and multi-output logging. Common channels are registered by default, and missing channels fall back to the default logger.
Install
go get github.com/duxweb/runa/log
Connect to an application
package main
import (
"context"
"log/slog"
"github.com/duxweb/runa"
runalog "github.com/duxweb/runa/log"
)
func main() {
app := runa.New()
app.Install(runalog.Provider(
runalog.Register("default", runalog.Console(runalog.Pretty(), runalog.Level(slog.LevelInfo))),
runalog.Register("queue", runalog.File("data/logs/queue.log", runalog.JSON())),
))
if err := app.Freeze(context.Background()); err != nil {
panic(err)
}
runalog.Default().Get("queue").Info("queued")
}
Standalone New usage
registry := runalog.New()
registry.Set("default", runalog.Console(runalog.Text()))
registry.Get("default").Info("hello")
Config
log currently does not read TOML config. Log outputs are usually tied to deployment environments, so register them in the application entry or a business Provider.
app.Install(runalog.Provider(
runalog.Register("default", runalog.Console(runalog.JSON(), runalog.Source(true))),
))
Output types
runalog.Console(runalog.Pretty())
runalog.File("data/logs/app.log", runalog.JSON())
runalog.Writer(os.Stdout, runalog.Text())
runalog.Discard()
runalog.Handler(slog.NewTextHandler(os.Stdout, nil))
Text, JSON, and Pretty outputs created by Runa convert log time to the application timezone. When you pass runalog.Handler(...), time formatting is controlled by your own slog.Handler.
One channel can register multiple outputs. Internally, a fanout handler is used.
runalog.Register("http",
runalog.Console(runalog.Pretty()),
runalog.File("data/logs/http.log", runalog.JSON()),
)
Common channels
Built-in channel names include default, http, error, queue, schedule, task, orm, and redis.
logger := runalog.Default().Get(runalog.HTTP)
logger.Info("request", "method", "GET")
Write logs in business code
logger := log.Default().Channel("default")
logger.Info("user created", "id", userID)
Use stable channel names so logs can be filtered and routed consistently.
Common mistakes
Scattering channel names
Do not invent channel names in random files. Keep a short list such as default, http, error, queue, schedule, task, orm, and redis.
Production logs only go to console or only to file
Production often needs both stdout for the platform and durable or aggregated logs. Configure outputs intentionally for your deployment model.
API quick reference
log.New()creates a standalone registry.log.Provider(...)connects to the framework lifecycle.log.Default()reads*log.Registryfrom default DI.log.Register(name, outputs...)registers Provider outputs.registry.Set(name, outputs...)sets a channel manually.registry.Get(name)gets*slog.Logger.log.Console,log.File,log.Writer,log.Handlercreate outputs.