Files
felhom-controller/controller/internal/logx/logx.go
T
admin 26a43708b7 v0.116.0: observability pass — always-on debug ring + leveled sweep + agent tab + self-log pull — MinAgent: 0.81.0
Capture layer: LogBuffer always exists; logger = MultiWriter(LevelFilterWriter
(stdout, logging.level), ring) so DEBUG detail exists remotely without a config
flip while docker logs keep respecting the level. New internal/logx leveled
helpers. Report ACK gains controller_log_requested (additive); next report
ships controller_log_tail (128KB, consume-once, app-tail wire byte-compatible).
Debug page: Vezérlő|Ügynök tabs; agent tab proxies agent /debug/logs with the
pre-0.83 notice on typed 404. Sweep: netstorage_job phases, netprobe, handler
validation refusals + orphan WARN, SupportsWithSource gate line, agentapi
per-call DEBUG, migrate phase lines, tier2/offbox unswallowed persists.
Red-proofs: filter-disabled, drain-removed, dropped-phase-line all FAIL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 16:45:57 +02:00

38 lines
1.6 KiB
Go

// Package logx is the leveled log helper of the v0.116.0 observability pass. It
// prefixes the standard [LEVEL] tag and writes through log.Logger.Output so the
// Lshortfile source (debug mode) attributes to the CALLER, not this file.
//
// Routing is the WRITER's job, not this package's: main.go builds the logger as
// MultiWriter(LevelFilterWriter(stdout, logging.level), LogBuffer) — so a
// logx.Debugf line ALWAYS reaches the debug ring (remote diagnostics) while
// stdout keeps respecting logging.level. Legacy `isDebug()`-gated Printf call
// sites are left as-is (they gate emission entirely); ALL NEW leveled lines use
// these helpers. Conventions (levels, English, no secrets):
// felhom.eu/documentation/runbooks/logging-conventions.md.
package logx
import (
"fmt"
"log"
)
// Debugf logs flow detail (phase steps, per-call traces, parsed values).
func Debugf(l *log.Logger, format string, args ...any) { output(l, "DEBUG", format, args...) }
// Infof logs state changes and operations with durations ("X done in Yms").
func Infof(l *log.Logger, format string, args ...any) { output(l, "INFO", format, args...) }
// Warnf logs degraded-but-continuing conditions.
func Warnf(l *log.Logger, format string, args ...any) { output(l, "WARN", format, args...) }
// Errorf logs a failed operation — always include the underlying error.
func Errorf(l *log.Logger, format string, args ...any) { output(l, "ERROR", format, args...) }
func output(l *log.Logger, tag, format string, args ...any) {
if l == nil {
return
}
// calldepth 3: Output ← output ← Debugf/… ← the caller we want attributed.
_ = l.Output(3, "["+tag+"] "+fmt.Sprintf(format, args...))
}