Skip to content

fix(logging): default production log level to info with an opt-in debug toggle (#609)#620

Merged
niklam merged 2 commits into
masterfrom
fix/default-log-level-info-609
May 31, 2026
Merged

fix(logging): default production log level to info with an opt-in debug toggle (#609)#620
niklam merged 2 commits into
masterfrom
fix/default-log-level-info-609

Conversation

@niklam
Copy link
Copy Markdown
Owner

@niklam niklam commented May 31, 2026

Summary

Every production install of the Elgato plugin wrote full DEBUG-level logs (one real user's log was 2,870 DEBUG lines vs 637 INFO over two sessions). Debug logging should be opt-in for troubleshooting, not the default — it bloats the log, leaks internal detail, and buries real signal during support. This defaults production logging to info and adds an "Enable debug logging" global setting that re-enables DEBUG at runtime, with no rebuild or reinstall.

Related Issue

Closes #609

Changes

  • deck-core — add debugLogging boolean to GlobalSettingsSchema (default false, standard string/boolean coercion).
  • loggercreateConsoleLogger accepts a live level resolver (LogLevelSource = LogLevel | (() => LogLevel)) so a logger's level can change at runtime; child scopes share the resolver.
  • Elgato (iracing-plugin-stream-deck) — default streamDeck.logger.setLevel("info"); apply debugLogging ? "debug" : "info" after init and on every onGlobalSettingsChange. Gating stays at the single streamDeck.logger file-writer; the createSDLogger wrapper keeps forwarding debug so a runtime flip surfaces scoped debug logs without recreating loggers.
  • Mirabox (deck-adapter-mirabox + iracing-plugin-mirabox) — adapter holds a runtime-mutable logLevel (setLogLevel) its loggers read live. Because the Stream Dock host discards plugin stdout, the adapter also tees every logger to <plugin>/log/<YYYY.M.D>.log (FileSink + withFileSink, matching the host's own log/ convention) so the toggle produces an attachable support log.
  • Property Inspector — shared "Enable debug logging" checkbox under Common Settings → Diagnostics (global-common-settings.ejs), so both plugins expose it.
  • Docslogging.md, plugin-structure.md, global-settings.md, deck-adapter-mirabox/CLAUDE.md, and website troubleshooting.md (per-platform log locations).

Testing

  • pnpm build, pnpm test (145 files, 4533 tests), pnpm lint:fix, pnpm format:fix — all green.
  • New/updated tests: schema default + coercion, console-logger live resolver + child-scope sharing, Mirabox adapter live toggle, and file-logger (unpadded per-day filename, append, dir creation, error-swallowing, tee + level gating + scope chaining).
  • Verified on a real machine that the Stream Dock host does not capture our plugin's stdout (no log/ folder for our plugin; 0 iRaceDeck lines in the host debug.log) — this motivated the Mirabox file-logging addition.
  • Manual in-sim verification of the runtime toggle on Elgato and the file output on Mirabox.

Screenshots (if applicable)

N/A — the PI adds a single checkbox under Common Settings → Diagnostics.

Checklist

  • Tests added/updated and passing (pnpm test)
  • Build succeeds (pnpm build)
  • Lint/format clean (pnpm lint:fix && pnpm format:fix)
  • Documentation updated (docs/, README, skills, rules as needed)
  • Affected plugins/website updated (if applicable)

Summary by CodeRabbit

  • New Features

    • Added a runtime "Debug Logging" global setting (checkbox) to enable verbose output immediately.
    • Logging now defaults to info-level on startup and can be toggled at runtime.
    • Optional automatic per-day log file output (date-named) when file logging is enabled.
  • Documentation

    • Added troubleshooting instructions on enabling debug logging and locating/attaching log files for support.

…ug toggle (#609)

Production installs logged at DEBUG unconditionally, flooding the .log and
leaking internal detail. Default to info; add a `debugLogging` global setting
(PI: Common Settings -> Diagnostics -> "Enable debug logging") that re-enables
DEBUG at runtime without a rebuild or reinstall.

- deck-core: add `debugLogging` to GlobalSettingsSchema (default false)
- logger: createConsoleLogger accepts a live level resolver (LogLevelSource)
- Elgato: setLevel("info") default, re-applied from debugLogging on every
  global-settings change (single streamDeck.logger file-writer gate; the
  scoped wrapper keeps forwarding debug so a runtime flip surfaces it)
- Mirabox: adapter holds a runtime-mutable level its loggers read live; the
  Stream Dock host discards plugin stdout, so loggers also tee to
  <plugin>/log/<YYYY.M.D>.log (FileSink + withFileSink) - that file is what
  the toggle captures for support
- PI: shared "Enable debug logging" checkbox in global-common-settings
- tests: schema defaults/coercion, console-logger live resolver, mirabox
  adapter live toggle, file-logger
- docs: logging.md, plugin-structure.md, global-settings.md,
  deck-adapter-mirabox CLAUDE.md, website troubleshooting

Closes #609
@github-actions github-actions Bot added the type: bug Bug fix label May 31, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 31, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f0cf06e7-3213-48a8-a421-75659520775a

📥 Commits

Reviewing files that changed from the base of the PR and between 60478b5 and 3f2b090.

📒 Files selected for processing (1)
  • .claude/rules/global-settings.md
✅ Files skipped from review due to trivial changes (1)
  • .claude/rules/global-settings.md

📝 Walkthrough

Walkthrough

Adds an opt-in debugLogging global setting, makes console loggers accept a live level resolver, implements per-day file logging for Mirabox, makes the Mirabox adapter runtime-configurable, wires both plugins and the PI to the toggle, and updates tests and docs.

Changes

Runtime-configurable debug logging with opt-in toggle

Layer / File(s) Summary
Logger infrastructure for live log-level resolution
packages/logger/src/index.ts, packages/logger/src/index.test.ts
New LogLevelSource type allows fixed or resolver-function log levels. createConsoleLogger accepts this source and re-evaluates level on each log call. Child scopes preserve the resolver reference so level updates propagate across the logger tree.
Global settings schema with debugLogging field
packages/deck-core/src/global-settings.ts, packages/deck-core/src/global-settings.test.ts, packages/deck-core/src/simhub-service.test.ts
GlobalSettingsSchema adds debugLogging boolean field with string/boolean coercion and default(false). Tests verify parsing behavior and mock fixtures are updated for downstream consumers.
Mirabox file-logging infrastructure
packages/deck-adapter-mirabox/src/file-logger.ts, packages/deck-adapter-mirabox/src/file-logger.test.ts
FileSink writes timestamped log lines to per-day files (<YYYY.M.D>.log) with lazy directory creation and error swallowing. withFileSink wraps a logger to tee calls to the file based on level thresholds, preserving scope chaining and withLevel transitions. Tests validate naming, appending, gating, and error handling.
Mirabox adapter runtime-configurable logging
packages/deck-adapter-mirabox/src/adapter.ts, packages/deck-adapter-mirabox/src/adapter.log-level.test.ts
Adapter now accepts optional logDir and maintains a mutable logLevel. New buildLogger(scope) method returns loggers that read from a shared level resolver and optionally tee to FileSink. New setLogLevel method updates the adapter-wide level, affecting all previously-created loggers.
Plugin debug toggle wiring
packages/iracing-plugin-stream-deck/src/plugin.ts, packages/iracing-plugin-mirabox/src/plugin.ts
Stream Deck defaults streamDeck.logger to "info" and applies debugLogging on startup and on changes. Mirabox constructs VSDPlatformAdapter with <plugin>/log and wires debugLogging to adapter.setLogLevel at startup and on changes.
Property Inspector debug logging checkbox
packages/pi-components/partials/global-common-settings.ejs
Adds "Diagnostics" section with debugLogging checkbox and supporting text explaining that debug logging is opt-in and takes effect immediately.
Documentation and rule updates
.claude/rules/global-settings.md, .claude/rules/logging.md, .claude/rules/plugin-structure.md, packages/deck-adapter-mirabox/CLAUDE.md, packages/website/src/content/docs/docs/getting-started/troubleshooting.md
Rule docs and website updated to document the debugLogging setting, default info behavior, platform-specific gating, Mirabox file logging, and user-facing troubleshooting steps for capturing logs with debug enabled.

Sequence Diagram

sequenceDiagram
  participant PI as PropertyInspector
  participant Plugin as PluginStartup
  participant Adapter as VSDPlatformAdapter
  participant Logger as createConsoleLogger
  participant File as FileSink
  PI->>Plugin: toggle debugLogging
  Plugin->>Adapter: setLogLevel(debug ? Debug : Info)
  Plugin->>Logger: create logger(scope) via shared resolver
  Logger->>Adapter: call level() resolver on each log
  Adapter->>File: write if level permits (withFileSink)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

type: improvement

Poem

🐇 A tiny toggle, quiet and bright,
Switch on the traces when chasing the night.
Live-levels that shift without a rebuild,
Files that collect what your logs have revealed.
Info by default — clean fields in the light.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: default production log level to info with an opt-in debug toggle, directly addressing issue #609.
Description check ✅ Passed The description comprehensively covers all required sections: related issue, detailed changes across all affected packages, testing verification, checklist, and includes code implementation details.
Linked Issues check ✅ Passed The code changes fully implement the acceptance criteria: global settings schema includes debugLogging with correct coercion [#609], Elgato defaults to info with runtime toggle [#609], Mirabox adapter supports setLogLevel with file logging [#609], PI checkbox added [#609], tests cover new behavior [#609], and docs updated [#609].
Out of Scope Changes check ✅ Passed All changes directly support issue #609: logging defaults, global settings schema, logger runtime resolution, adapter mutable levels, PI checkbox, file logging, and documentation are all within scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/default-log-level-info-609

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.claude/rules/global-settings.md:
- Line 127: The documentation line for the global setting uses
z.boolean().default(false) but the intended contract accepts both boolean and
string inputs; update the doc to reflect the coercing schema (e.g., use Zod's
boolean coercion such as z.coerce.boolean() or a z.preprocess that converts
string "true"/"false" to booleans) and show the default(false) behavior,
referencing the debugLogging schema name and the existing
z.boolean().default(false) snippet so readers know to replace that exact token
with the coercing variant.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 14649f69-9f8b-4716-91fe-388d1ff50eb4

📥 Commits

Reviewing files that changed from the base of the PR and between 6f0b10e and 60478b5.

📒 Files selected for processing (17)
  • .claude/rules/global-settings.md
  • .claude/rules/logging.md
  • .claude/rules/plugin-structure.md
  • packages/deck-adapter-mirabox/CLAUDE.md
  • packages/deck-adapter-mirabox/src/adapter.log-level.test.ts
  • packages/deck-adapter-mirabox/src/adapter.ts
  • packages/deck-adapter-mirabox/src/file-logger.test.ts
  • packages/deck-adapter-mirabox/src/file-logger.ts
  • packages/deck-core/src/global-settings.test.ts
  • packages/deck-core/src/global-settings.ts
  • packages/deck-core/src/simhub-service.test.ts
  • packages/iracing-plugin-mirabox/src/plugin.ts
  • packages/iracing-plugin-stream-deck/src/plugin.ts
  • packages/logger/src/index.test.ts
  • packages/logger/src/index.ts
  • packages/pi-components/partials/global-common-settings.ejs
  • packages/website/src/content/docs/docs/getting-started/troubleshooting.md

Comment thread .claude/rules/global-settings.md Outdated
CodeRabbit (#620): the global-settings.md schema snippet showed debugLogging as z.boolean().default(false), but the field coerces the "true"/"false" strings the Property Inspector sends. Align the doc with the real coercing union so future edits don't regress parsing.
@niklam niklam merged commit 35750ed into master May 31, 2026
5 checks passed
@niklam niklam deleted the fix/default-log-level-info-609 branch May 31, 2026 11:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(logging): default production log level to info with an opt-in debug toggle

1 participant