logger
View on GitHublogs
The canonical Corti logger. New returns a *log/slog.Logger configured from
environment variables — there is no wrapper type and no re-exported Level.
The standard library is the API; this package is a thin, opinionated
constructor so every service starts with the same level, format, and output.
Installation
go get github.com/corticph/gocomo/logger
Quick start
package main
import "github.com/corticph/gocomo/logger"
func main() {
l := logger.New()
l.Info("started", "service", "transcription")
}
New returns *slog.Logger, so handlers accept *slog.Logger (or a narrower
interface they declare consumer-side) and call the stdlib methods directly.
Configuration
New reads two environment variables, set by the container at runtime. There
are no functional options for level/format by design — one configuration path,
twelve-factor style.
| Env var | Values | Default | Effect |
|---|---|---|---|
LOG_LEVEL |
debug info warn error |
info |
Minimum level emitted. Case-insensitive. |
LOG_FORMAT |
json text |
json |
Handler format. Case-insensitive. |
Unknown values fall back to the defaults and a warning is logged to the
configured writer; output goes to os.Stdout by default.
// Defaults: INFO level, JSON to stdout.
l := logger.New()
// LOG_LEVEL=warn, LOG_FORMAT=text (set in the environment) -> same call.
Output destination: WithWriter
WithWriter overrides the destination (the only functional option). It is
the intended seam for tests: point it at a buffer to assert output, or at
io.Discard to silence it.
// Capture output in a test.
var buf bytes.Buffer
l := logger.New(logger.WithWriter(&buf))
l.Info("handled")
// buf holds the JSON record.
// Silence a logger entirely (e.g. a test that only exercises behavior,
// not content).
l := logger.New(logger.WithWriter(io.Discard))
Bad env values are reported to the same writer as the real logger, so a test
capturing via WithWriter(&buf) can assert them and a silenced logger
(WithWriter(io.Discard)) stays quiet.
Usage
args are alternating key/value pairs, exactly as in log/slog:
l.With("tenant", "acme", "request_id", "r-1").Info("handled")
// {"time":"...","level":"INFO","msg":"handled","tenant":"acme","request_id":"r-1"}
For level values, import log/slog and use slog.LevelDebug etc. directly —
this package does not re-export them.
Testing
Tests build a logger through New with WithWriter so they don't touch
os.Stdout:
var buf bytes.Buffer
l := logger.New(logger.WithWriter(&buf))
l.Info("handled")
// assert on buf.String()
Set LOG_LEVEL/LOG_FORMAT with t.Setenv to test env-var behavior; clear
them first if you need the default to be deterministic:
t.Setenv("LOG_LEVEL", "")
t.Setenv("LOG_FORMAT", "")
l := logger.New(logger.WithWriter(&buf))