Skip to content

feat(logging): rotate embedded core + shell logs to ~/.openhuman/logs#1278

Merged
senamakel merged 4 commits intotinyhumansai:mainfrom
senamakel:feat/embedded-file-logging
May 6, 2026
Merged

feat(logging): rotate embedded core + shell logs to ~/.openhuman/logs#1278
senamakel merged 4 commits intotinyhumansai:mainfrom
senamakel:feat/embedded-file-logging

Conversation

@senamakel
Copy link
Copy Markdown
Member

@senamakel senamakel commented May 6, 2026

Summary

  • Embedded core now installs a tracing subscriber on Tauri startup (previously only the CLI did), so packaged GUI builds finally produce diagnostics.
  • Logs roll daily to <data_dir>/logs/openhuman-YYYY-MM-DD.log (7-day retention) via tracing-appender, with the same CleanCliFormat used by openhuman run.
  • The Tauri shell's log::* calls are bridged into the same subscriber via tracing_log::LogTracer — replaces the prior stderr-only env_logger. Sentry tracing layer + RUST_LOG env filter preserved.
  • Adds logs_folder_path / reveal_logs_folder Tauri commands and a "Open logs folder" row in Settings → Developer Options so users can grab today's log file when reporting issues like "stuck on Initializing OpenHuman...".
  • Refactors src/core/logging.rs so init_for_cli_run and the new init_for_embedded share seed_rust_log / build_env_filter / sentry_tracing_layer — single source of truth for formatter + filter.

Problem

When the Tauri shell hits a startup issue (RPC bootstrap failure, CEF cache lock, sidecar crash) we have no log file to point users at. The shell's env_logger writes to stderr — invisible in a packaged .app / .exe. The embedded core's tracing subscriber (init_for_cli_run in src/core/logging.rs) was only invoked from CLI paths, so every tracing::info! in the core was a no-op when running inside the Tauri shell. Result: support has nothing concrete to ask the user for.

Solution

  • src/core/logging.rs — extract seed_rust_log / build_env_filter / sentry_tracing_layer and add init_for_embedded(data_dir, verbose). The new entry point installs a non-blocking, daily-rotated file appender (tracing-appender) at <data_dir>/logs/openhuman-YYYY-MM-DD.log plus the existing stderr layer (still useful under tauri dev). Both share CleanCliFormat. Once-guarded; first caller wins. The non-blocking writer's WorkerGuard and the resolved log dir are stashed in OnceLocks so they live for the entire process and the UI can resolve the path on demand.
  • app/src-tauri/src/file_logging.rs — small shell-side wrapper that resolves the data dir the same way the core does (OPENHUMAN_WORKSPACE override, then default_root_openhuman_dir, with std::env::temp_dir().join("openhuman") as the absolute-path fallback if home-dir lookup fails). Exposes two Tauri commands: logs_folder_path (returns the absolute path for display) and reveal_logs_folder (open / explorer / xdg-open per platform).
  • app/src-tauri/src/lib.rs — calls file_logging::init() early in run() (before CEF preflight, before the Sentry smoke trigger), drops the env_logger::Builder::try_init path, and registers the new commands in invoke_handler. Sentry init still runs first since that just builds a client guard.
  • app/src/components/settings/panels/DeveloperOptionsPanel.tsx — adds a "App logs" row that shows the resolved path (logs_folder_path) and a button that calls reveal_logs_folder. Hidden in non-Tauri builds via isTauri().
  • app/src-tauri/permissions/allow-core-process.toml — capability allowlist entries for the two new commands.
  • Testssrc/core/logging.rs and app/src-tauri/src/file_logging.rs ship #[cfg(test)] mod tests covering: seed_rust_log defaults + RUST_LOG respect, level_tag / short_target, parse_log_file_constraints, build_env_filter smoke, resolve_data_dir workspace override + empty-string fallthrough + temp-dir fallback, and the pre-init guards on logs_folder_path / reveal_logs_folder. Env-mutating tests share a Mutex to keep the parallel runner stable.

Tradeoffs

  • Where to write. <data_dir>/logs/ (i.e. ~/.openhuman/logs/ by default, or under OPENHUMAN_WORKSPACE) keeps logs next to active_user.toml, the per-user users/ tree, and the CEF caches a support engineer would also need. OS-conventional paths (~/Library/Logs/OpenHuman, %LOCALAPPDATA%\OpenHuman\Logs) are what Console.app / Event Viewer expect but split logs per user and need per-platform code; the OPENHUMAN_WORKSPACE test override would also stop working.
  • Retention. 7 days at info (or debug if OPENHUMAN_VERBOSE=1 / RUST_LOG=debug). Bumpable later if a debug session needs deeper history.
  • Cold-start gap. init_for_embedded runs after sentry::init but before everything else (CEF preflight included). Anything that fails before run() enters our init still hits stderr only — that's currently main.rs argv parsing and tauri::cef_entry_point, neither of which has user-actionable failures today.
  • Redaction. Per CLAUDE.md, no tokens or full PII. Nothing in this PR newly logs sensitive data; the bridge just exposes existing log calls.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) per docs/TESTING-STRATEGY.md
  • Diff coverage ≥ 80% — new #[cfg(test)] mod tests blocks in src/core/logging.rs and app/src-tauri/src/file_logging.rs cover the added lines.
  • N/A: behaviour-only change (no new product feature → no row to add to docs/TEST-COVERAGE-MATRIX.md).
  • N/A: no feature IDs from the matrix are touched by this PR.
  • No new external network dependencies introduced (tracing-appender is local-only).
  • N/A: no release-cut surface change, so the manual smoke checklist is unaffected.
  • N/A: no tracking issue — this is a support-tooling improvement surfaced from a chat thread.

Impact

  • Desktop only: the embedded path is desktop-only by design; mobile/web are unaffected.
  • Performance: file writes go through tracing_appender::non_blocking, so the UI thread never blocks on disk I/O. Background thread is owned by a process-lifetime OnceLock<WorkerGuard>.
  • Disk: at info, daily logs are typically <1 MB. 7-day cap keeps total footprint bounded.
  • Security: no new PII surfaces; file lives under the user's existing ~/.openhuman/ data dir, same TCC/permission scope as today's storage.
  • Migration: none. First launch after merge creates the logs/ subdir.

Related

  • Closes:
  • Follow-up PR(s)/TODOs: optional — surface "Reveal today's log file" (vs the folder) once we add a clearer support flow.

AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: feat/embedded-file-logging
  • Commit SHA: 0b18002

Validation Run

  • pnpm --filter openhuman-app format:check
  • pnpm typecheck
  • Focused tests: cargo test --lib core::logging (9 pass), cargo test --lib file_logging (4 pass)
  • Rust fmt/check (if changed): cargo check --manifest-path Cargo.toml --lib
  • Tauri fmt/check (if changed): cargo check --manifest-path app/src-tauri/Cargo.toml

Validation Blocked

  • command: N/A
  • error: N/A
  • impact: N/A

Behavior Changes

  • Intended behavior change: embedded core + Tauri shell now write logs to a daily-rotated file under <data_dir>/logs/ instead of stderr only.
  • User-visible effect: new "Open logs folder" row in Settings → Developer Options. No change to the visible UI flow elsewhere.

Parity Contract

  • Legacy behavior preserved: init_for_cli_run (used by openhuman run / CLI subcommands) keeps the same stderr output and EnvFilter defaults.
  • Guard/fallback/dispatch parity checks: Once-guarded subscriber init; non-blocking writer guard pinned for the process lifetime; reveal_logs_folder returns a typed error if logging hasn't been initialized.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): none
  • Canonical PR: this one
  • Resolution: N/A

Summary by CodeRabbit

  • New Features

    • Added a "Logs Folder" option in Developer Options to view and open the on-disk log directory.
    • UI can reveal the logs folder for easier troubleshooting.
  • Chores

    • Unified application logging across modes; logs now written to daily-rotating files.
    • Read-only exposure of the log directory for developer/support workflows.
    • Added a logging dependency to support file-based rotation.
  • Tests

    • Extended developer options tests to cover the new logs folder behavior.

The Tauri shell previously initialized `env_logger` to stderr and the
embedded core never installed a tracing subscriber at all (only the CLI
path called `init_for_cli_run`). Packaged GUI builds therefore had no
visible diagnostics when users hit issues like "stuck on Initializing
OpenHuman..." — there was nothing for support to ask them to share.

Add `core::logging::init_for_embedded(data_dir, verbose)` which:

  * installs the existing `CleanCliFormat` against both stderr (ANSI when
    attached to a TTY) and a non-blocking, daily-rotated file appender at
    `<data_dir>/logs/openhuman-YYYY-MM-DD.log` (7-day retention),
  * keeps the Sentry tracing layer + `EnvFilter` honoring `RUST_LOG`,
  * bridges the shell's `log::*` calls via `tracing_log::LogTracer` so
    every shell + core event lands in one file.

Wire it from `app/src-tauri/src/file_logging.rs` (called early in
`run()`, before CEF preflight) and surface the folder in Settings →
Developer Options via two new commands `logs_folder_path` /
`reveal_logs_folder` so users can grab today's log and send it.

Refactor `init_for_cli_run` to share `seed_rust_log`,
`build_env_filter`, and `sentry_tracing_layer` with the embedded path —
single source of truth for the formatter + filter.
@senamakel senamakel requested a review from a team May 6, 2026 08:20
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

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: 00cc9c7f-e560-4831-8967-b554f791cb91

📥 Commits

Reviewing files that changed from the base of the PR and between bb5fcba and 61e196f.

📒 Files selected for processing (1)
  • app/src/components/settings/panels/__tests__/DeveloperOptionsPanel.test.tsx

📝 Walkthrough

Walkthrough

Adds daily-rotated file logging for embedded (Tauri) and CLI contexts, exposes the active log directory and a reveal action to the Tauri frontend, initializes the logger early in startup, updates Tauri permissions for those commands, and adds a Developer Options UI row to view/open the logs folder. (34 words)

Changes

File-Based Logging with Tauri Integration

Layer / File(s) Summary
Dependencies
Cargo.toml
Add tracing-appender = "0.2".
Core Logging Infrastructure
src/core/logging.rs
Refactor logging to unify CLI and embedded modes; add static guards (FILE_GUARD, LOG_DIR), constraint-based filtering, Sentry tracing layer, rotating file appender setup in init_for_embedded, and pub fn log_directory() -> Option<&'static Path>. Tests added for log_directory() pre-init behavior.
Embedded init / wiring
app/src-tauri/src/lib.rs
Declare mod file_logging;, call file_logging::init() early in startup (replacing prior env_logger init), and register new Tauri commands file_logging::reveal_logs_folder, file_logging::logs_folder_path (also added mascot_window_hide).
Tauri file-logging module
app/src-tauri/src/file_logging.rs
New module providing init(), Tauri commands logs_folder_path() -> Option<String> and reveal_logs_folder() -> Result<(), String>, data-dir resolution (OPENHUMAN_WORKSPACE fallback), platform-specific folder reveal logic, and tests for pre-init behavior and error cases.
Permissions
app/src-tauri/permissions/allow-core-process.toml
Add logs_folder_path and reveal_logs_folder to [permission.commands] allow with documentation.
Frontend / Developer UI
app/src/components/settings/panels/DeveloperOptionsPanel.tsx
Add LogsFolderRow component (uses isTauri, useEffect, TAURI invoke) to fetch/display log path and a button to call reveal_logs_folder; insert row into Developer Options panel.
Tests / Wiring
app/src/components/settings/panels/__tests__/DeveloperOptionsPanel.test.tsx, app/src-tauri/src/file_logging.rs
Extend tests/mocks to include tauri invoke and isTauri; add tests covering rendering, path resolution, reveal action, and error handling.

Sequence Diagram

sequenceDiagram
    participant Frontend as Developer Panel
    participant Tauri as Tauri Shell
    participant Core as Embedded Core
    participant FS as File System

    rect rgba(100, 200, 100, 0.5)
    note over Frontend,FS: Fetch Logs Folder Path
    Frontend->>Tauri: invoke("logs_folder_path")
    Tauri->>Core: core::log_directory() query
    Core->>FS: resolve active logs directory
    FS-->>Core: path
    Core-->>Tauri: path string
    Tauri-->>Frontend: path
    end

    rect rgba(100, 150, 200, 0.5)
    note over Frontend,FS: Open Logs Folder
    Frontend->>Tauri: invoke("reveal_logs_folder")
    Tauri->>FS: spawn platform command (open/explorer/xdg-open)
    FS-->>Tauri: success/failure
    Tauri-->>Frontend: result
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • graycyrus

Poem

🐰
I hop where logs in folders hide,
Daily-rolled and kept inside.
Tauri opens, paths I trace,
Devs can peek and find the trace.
Hop, reveal — support's embrace.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and concisely describes the main feature: implementing daily log rotation for both embedded core and shell logs to a specific directory. It accurately summarizes the primary change across all modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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

Copy link
Copy Markdown
Contributor

@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

🧹 Nitpick comments (1)
src/core/logging.rs (1)

241-241: 💤 Low value

Minor: duplicate constraint parsing.

parse_log_file_constraints() is called twice (lines 241 and 264), each creating a separate Vec<String>. Since this runs once at startup, the overhead is negligible. If you want to tighten it, parse once and clone for the second filter closure.

♻️ Optional: parse constraints once
         appender.map(|appender| {
             let (writer, guard) = tracing_appender::non_blocking(appender);
             let _ = FILE_GUARD.set(guard);
             let _ = LOG_DIR.set(logs_dir.clone());
-            let constraints = parse_log_file_constraints();
+            let file_constraints = constraints.clone();
             tracing_subscriber::fmt::layer()
                 .with_ansi(false)
                 .event_format(CleanCliFormat)
                 .with_writer(writer)
                 .with_filter(tracing_subscriber::filter::filter_fn(move |meta| {
-                    event_matches_file_constraints(meta, &constraints)
+                    event_matches_file_constraints(meta, &file_constraints)
                 }))
         })
     }
     // ... earlier in the function, before the match:
+    let constraints = parse_log_file_constraints();

Also applies to: 264-264

🤖 Prompt for 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.

In `@src/core/logging.rs` at line 241, parse_log_file_constraints() is being
called twice producing two Vec<String>; call it once, store the result in a
local variable (e.g. let constraints = parse_log_file_constraints()), then reuse
it by cloning when needed for the second filter/closure (e.g. let
constraints_for_other = constraints.clone()) so both closures use the same
parsed data; update the two places that currently call
parse_log_file_constraints() to use the stored variable and its clone instead.
🤖 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 `@app/src-tauri/src/file_logging.rs`:
- Around line 39-41: The fallback to PathBuf::from(".openhuman") in the call to
default_root_openhuman_dir() can put logs in a relative, unpredictable location;
change the fallback to a robust absolute location (for example use
std::env::temp_dir().join("openhuman") or another absolute directory) and emit a
warning when default_root_openhuman_dir() fails so the user/maintainer is aware;
update the call site that uses default_root_openhuman_dir() and the surrounding
error handling to construct an absolute fallback path and call the logger (or
e.g., warn!()) with context including that the home-dir lookup failed and which
fallback was chosen.

---

Nitpick comments:
In `@src/core/logging.rs`:
- Line 241: parse_log_file_constraints() is being called twice producing two
Vec<String>; call it once, store the result in a local variable (e.g. let
constraints = parse_log_file_constraints()), then reuse it by cloning when
needed for the second filter/closure (e.g. let constraints_for_other =
constraints.clone()) so both closures use the same parsed data; update the two
places that currently call parse_log_file_constraints() to use the stored
variable and its clone instead.
🪄 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: f71d657a-3409-4e6a-b44c-77d3c5ee323e

📥 Commits

Reviewing files that changed from the base of the PR and between a3a1843 and bb8d1ca.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • app/src-tauri/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • Cargo.toml
  • app/src-tauri/permissions/allow-core-process.toml
  • app/src-tauri/src/file_logging.rs
  • app/src-tauri/src/lib.rs
  • app/src/components/settings/panels/DeveloperOptionsPanel.tsx
  • src/core/logging.rs

Comment thread app/src-tauri/src/file_logging.rs Outdated
Adds unit tests for diff-coverage:

  * core/logging.rs — `seed_rust_log` defaults (info / debug / autocomplete
    scoping), respect for an existing `RUST_LOG`, `level_tag`,
    `short_target`, `parse_log_file_constraints`, smoke `build_env_filter`,
    and `log_directory()`-pre-init.
  * app/src-tauri file_logging.rs — `resolve_data_dir` honors
    `OPENHUMAN_WORKSPACE`, falls through on empty value, and the new
    `temp_dir()` fallback (replacing the relative `.openhuman` path
    flagged by CodeRabbit). Also asserts `logs_folder_path` /
    `reveal_logs_folder` behave correctly pre-init.

Env-mutating tests share a `Mutex` so the parallel test runner can't race
on `RUST_LOG` / `OPENHUMAN_WORKSPACE` / `OPENHUMAN_LOG_FILE_CONSTRAINTS`.
Copy link
Copy Markdown
Contributor

@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: 2

🧹 Nitpick comments (1)
app/src-tauri/src/file_logging.rs (1)

124-139: ⚡ Quick win

Add backend diagnostics around the folder-reveal command.

This new Tauri command launches an external process and returns user-visible errors, but the shell leaves no trace of which directory it tried to open or why it failed. A small [file_logging] debug/warn pair here would make support reports much easier to correlate.

Suggested fix
 pub fn reveal_logs_folder() -> Result<(), String> {
     let dir = log_directory().ok_or_else(|| "log directory not initialized".to_string())?;
+    log::debug!("[file_logging] reveal_logs_folder dir={}", dir.display());

     #[cfg(target_os = "macos")]
     let result = std::process::Command::new("open").arg(dir).spawn();

     #[cfg(target_os = "windows")]
@@
-    result
-        .map(|_| ())
-        .map_err(|e| format!("failed to open log directory {}: {e}", dir.display()))
+    result.map(|_| ()).map_err(|e| {
+        log::warn!(
+            "[file_logging] reveal_logs_folder failed dir={} err={e}",
+            dir.display()
+        );
+        format!("failed to open log directory {}: {e}", dir.display())
+    })
 }

As per coding guidelines, "Default to verbose diagnostics on new/changed flows with entry/exit logging, branches, external calls, retries/timeouts, state transitions, and errors; use stable grep-friendly prefixes and correlation fields."

🤖 Prompt for 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.

In `@app/src-tauri/src/file_logging.rs` around lines 124 - 139, Add structured
backend diagnostics around reveal_logs_folder: before invoking the external
command in reveal_logs_folder (after resolving dir via log_directory()) emit a
debug log (e.g. "[file_logging] reveal_logs_folder: opening directory {dir}")
that records the exact dir and platform command being executed, and on failure
emit a warn/error log (e.g. "[file_logging] reveal_logs_folder failed to open
{dir}: {error}") inside the error mapping branch so the spawned command error
and the attempted directory are captured; also emit a debug/info success log
when spawn succeeds. Use the existing log/tracing macros consistent with the
crate.
🤖 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 `@src/core/logging.rs`:
- Around line 237-240: Currently FILE_GUARD and LOG_DIR are being set before the
subscriber is installed (before try_init()), so if try_init() fails the globals
are left set even though no file layer exists; change the code in the appender
handling (the block that creates tracing_appender::non_blocking and the later
similar block around lines 272-279) to keep the (writer, guard) and the computed
logs_dir in local variables and only call FILE_GUARD.set(guard) and
LOG_DIR.set(logs_dir.clone()) after try_init() returns Ok (or, alternatively,
propagate the init error and do not set LOG_DIR/FILE_GUARD on Err); also ensure
logs_folder_path() and reveal_logs_folder() read the globals only after
successful init.
- Around line 227-249: The file-appender creation currently swallows errors via
build(&logs_dir).ok(), so when
tracing_appender::rolling::Builder::new()...build(&logs_dir).ok() fails you lose
diagnostic info and the code silently falls back to stderr; change the match arm
where you call build(&logs_dir) to handle Result explicitly (e.g., match
build(&logs_dir) { Ok(appender) => { ... same path that calls
tracing_appender::non_blocking, sets FILE_GUARD and LOG_DIR, parses constraints,
returns the layer }, Err(e) => { emit a startup diagnostic log/error (include
the error e and stable/grep-friendly prefix), and continue without file_layer }
}), and ensure the error message uses the same style as the create_dir_all
diagnostic so failures to create the file appender are visible.

---

Nitpick comments:
In `@app/src-tauri/src/file_logging.rs`:
- Around line 124-139: Add structured backend diagnostics around
reveal_logs_folder: before invoking the external command in reveal_logs_folder
(after resolving dir via log_directory()) emit a debug log (e.g. "[file_logging]
reveal_logs_folder: opening directory {dir}") that records the exact dir and
platform command being executed, and on failure emit a warn/error log (e.g.
"[file_logging] reveal_logs_folder failed to open {dir}: {error}") inside the
error mapping branch so the spawned command error and the attempted directory
are captured; also emit a debug/info success log when spawn succeeds. Use the
existing log/tracing macros consistent with the crate.
🪄 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: bd9b2a7e-e52a-45ee-8c44-be66e7c348a7

📥 Commits

Reviewing files that changed from the base of the PR and between bb8d1ca and 0b18002.

📒 Files selected for processing (2)
  • app/src-tauri/src/file_logging.rs
  • src/core/logging.rs

Comment thread src/core/logging.rs Outdated
Comment thread src/core/logging.rs Outdated
…ucceeds

Two CodeRabbit findings on the embedded init path:

  1. `build(&logs_dir).ok()` silently dropped the file-appender error so a
     packaged build could degrade to stderr-only with no clue why
     `logs/openhuman-YYYY-MM-DD.log` never appears. Now matches on the
     `Result` and emits an `[logging]`-prefixed `eprintln!` on failure,
     matching the existing `create_dir_all` diagnostic style.

  2. `FILE_GUARD` and `LOG_DIR` were set inside the layer-builder closure,
     i.e. before `try_init()` could fail. If a competing global subscriber
     was already installed `try_init` returns `Err`, no file layer ends up
     attached, but `log_directory()` would still report a path — leading
     `reveal_logs_folder` / the UI to point at an empty directory. Hold
     the writer + guard + path in a local `Option` and commit them only
     after `try_init().is_ok()`. On failure log the init error and let
     the guard drop so the background flushing thread shuts down cleanly.
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 6, 2026
Diff-cover gate flagged DeveloperOptionsPanel.tsx at 38% on changed lines —
all of the missing lines were the new LogsFolderRow's `useEffect` /
`onClick` / non-Tauri short-circuit / live-region branches.

Adds five Vitest cases against the existing test file:

  * isTauri() === false → row is hidden
  * mounting calls `invoke('logs_folder_path')` and renders the path
  * clicking "Open logs folder" calls `invoke('reveal_logs_folder')`
  * reveal rejection surfaces in the role="status" live region
  * path-resolve rejection surfaces in the same live region

Also updates the existing Sentry-row beforeEach to reset and stub the
`@tauri-apps/api/core` mocks (the panel now always renders LogsFolderRow,
which fires an `invoke` on mount — without a stub the unhandled rejection
crashes the Sentry suite).
@senamakel senamakel merged commit abec992 into tinyhumansai:main May 6, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant