Skip to content

Logging: slog foundation with component, device and transport attributes - #32018

Draft
andig wants to merge 19 commits into
masterfrom
feat/slog-logger
Draft

Logging: slog foundation with component, device and transport attributes#32018
andig wants to merge 19 commits into
masterfrom
feat/slog-logger

Conversation

@andig

@andig andig commented Jul 21, 2026

Copy link
Copy Markdown
Member

Refactors logging onto log/slog, stepwise (core first, then devices, then the log API):

  • util.Logger now embeds *slog.Logger; the printf-style TRACEFATAL level loggers are provided via slog.NewLogLogger, so all existing call sites remain unchanged. Log levels are kept, with trace and fatal as custom slog levels.
  • The custom slog.Handler applies redaction centrally (now also covering the ui log feed, previously unredacted) and fans out structured entries to stdout (classic line format, gated by per-area level), the logstash ring buffer and the ui.
  • The logstash ring stores structured entries instead of formatted strings — log line parsing is gone entirely (logstash regex and the ui level matcher). /api/system/log returns structured entries (time, area, level, message, attrs); format=txt renders the classic line format server-side. Log and issue views render entries client-side.
  • Log entries carry structured attributes: component with subtype (site, loadpoint incl. id, charger/abb, vehicle/tesla, …) — class attached by setup, subtype appended by the device constructor via the new util.LoggerFromContext; plugin for plugins including transports (http, mqtt, modbus, oauth, …); title where configured. Attribute keys are constants in util.
  • util.LoggerFromContext(ctx, subtype) and util.PluginLoggerFromContext(ctx, area) replace the ContextLoggerWithDefault(ctx, util.NewLogger(…)) idiom; device constructors with context now log under the per-device logger (instance name as area, component/title attributes), falling back to the classic type area when used standalone.
  • modbus.Connection.Logger takes a *util.Logger and tags traces itself, aligned with http and mqtt.
  • All device and plugin constructors are converted to context form (registry.AddCtx), so every constructor logs under the per-device logger with full attribution; tests pass t.Context().
  • SLOG=1 environment variable opts the console output into the slog default text format (time=… level=… msg=… area=… component=…); the classic line format remains the default, and the log api, ring buffer and ui are unaffected.
  • The device configuration modal shows the log of that device alone, refreshed every two seconds while the modal is open. The device log area (db:<id> plus title) moves into config.Config.LogArea, shared by the logger setup and the new /api/config/devices/{class}/{id}/log endpoint.
  • jwalterweatherman dependency removed.

🤖 Generated with Claude Code

@andig andig added enhancement New feature or request infrastructure Basic functionality labels Jul 21, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • In handler.Handle, the UI message path re-applies redaction to text.String() even though the full line was already redacted, which adds unnecessary work and could be simplified by reusing the redacted text or avoiding the second redacted call.
  • The new Logger.With/handler.with API is quite loosely typed; consider documenting or constraining expected argument patterns (e.g. key/value pairs vs slog.Attr) to make misuse less likely and to avoid silently generating !BADKEY attributes.
  • The levelString helper derives textual levels from numeric comparisons against LevelTrace/LevelFatal; it may be clearer and less fragile to explicitly map the defined custom levels (LevelTrace, LevelFatal) and standard slog levels to their string representations rather than relying on ranges.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `handler.Handle`, the UI message path re-applies redaction to `text.String()` even though the full line was already redacted, which adds unnecessary work and could be simplified by reusing the redacted text or avoiding the second `redacted` call.
- The new `Logger.With`/`handler.with` API is quite loosely typed; consider documenting or constraining expected argument patterns (e.g. key/value pairs vs `slog.Attr`) to make misuse less likely and to avoid silently generating `!BADKEY` attributes.
- The `levelString` helper derives textual levels from numeric comparisons against `LevelTrace`/`LevelFatal`; it may be clearer and less fragile to explicitly map the defined custom levels (`LevelTrace`, `LevelFatal`) and standard slog levels to their string representations rather than relying on ranges.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@andig
andig marked this pull request as draft July 21, 2026 17:19
andig added 3 commits July 26, 2026 14:40
# Conflicts:
#	charger/daheimladen.go
#	charger/em2go-duo.go
#	charger/em2go.go
#	charger/evsedin.go
#	charger/homeassistant.go
#	charger/openwb-native_linux.go
#	meter/mbmd.go
#	tariff/proxy_cache.go
Adds a log panel to the device configuration modal that shows the log entries of
that device only, refreshed every two seconds while the modal is open.

The device logger area (db:<id> plus title) moves into config.Config.LogArea so
both the logger setup and the new /api/config/devices/{class}/{id}/log endpoint
derive it from the same place.
Shares the log level/count query parsing between the system and device log
handlers, moves the per-level log styles into app.css instead of repeating them
per view, and drops the unused reactive level and per-line keys from the device
log component.

The device log endpoint now verifies that the requested class matches the stored
device instead of ignoring the path segment.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request infrastructure Basic functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant