-
Notifications
You must be signed in to change notification settings - Fork 0
feat(daemon): capture stdout+stderr to a log file, add daemon logs #424
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
15ae0bd
f0adb3f
e32e130
5c2abf4
b093519
a7d681a
8d929be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,16 @@ pub fn daemon_pid_path() -> PathBuf { | |
| .unwrap_or_else(|| std::env::temp_dir().join("agentflare-daemon.pid")) | ||
| } | ||
|
|
||
| /// stdout+stderr of the current daemon session — truncated fresh on every | ||
| /// `start`/`restart` (see `spawn_detached`), same lifetime as the runtime | ||
| /// dir it lives in. Not a rotated history: `agentflare daemon logs` is for | ||
| /// seeing what THIS run of the daemon is doing, not an audit trail. | ||
| pub fn daemon_log_path() -> PathBuf { | ||
| dirs::runtime_dir() | ||
| .map(|d| d.join("agentflare").join("daemon.log")) | ||
| .unwrap_or_else(|| std::env::temp_dir().join("agentflare-daemon.log")) | ||
|
Comment on lines
+17
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- candidate files ---'
git ls-files 'src/daemon.rs' 'src/ipc/process.rs' 'Cargo.toml' 'src/*' | sed -n '1,120p'
printf '%s\n' '--- daemon.rs outline ---'
if command -v ast-grep >/dev/null 2>&1; then
ast-grep outline src/daemon.rs
else
echo 'ast-grep unavailable'
fi
printf '%s\n' '--- daemon.rs relevant lines ---'
nl -ba src/daemon.rs | sed -n '1,100p'
printf '%s\n' '--- process.rs relevant symbols and lines ---'
if command -v ast-grep >/dev/null 2>&1; then
ast-grep outline src/ipc/process.rs
else
echo 'ast-grep unavailable'
fi
nl -ba src/ipc/process.rs | sed -n '1,180p'
printf '%s\n' '--- log-path and file-creation references ---'
rg -n -C 4 'daemon_log_path|File::create|daemon\.log|agentflare-daemon\.log|cmd_logs|runtime_dir|temp_dir' src Cargo.tomlRepository: getappz/agentflare Length of output: 36248 🏁 Script executed: #!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
for name in ("src/daemon.rs", "src/ipc/process.rs"):
path = Path(name)
print(f"--- {name}: {path.stat().st_size} bytes ---")
text = path.read_text()
for i, line in enumerate(text.splitlines(), 1):
if any(token in line for token in (
"daemon_log_path", "File::create", "OpenOptions", "cmd_logs",
"Command", "runtime_dir", "temp_dir", "logs",
)):
start = max(1, i - 8)
end = min(len(text.splitlines()), i + 12)
lines = text.splitlines()
print(f"[lines {start}-{end}]")
for j in range(start, end + 1):
print(f"{j:4}: {lines[j-1]}")
PY
printf '%s\n' '--- callers of daemon_log_path ---'
rg -n -C 6 'daemon_log_path\s*\(' .Repository: getappz/agentflare Length of output: 24592 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- all relevant source references ---'
rg -n -C 8 'daemon_log_path|File::create|OpenOptions|create_new|symlink|cmd_logs|runtime_dir|temp_dir' --glob '*.rs' .
printf '%s\n' '--- daemon and logs command definitions ---'
rg -n -C 12 'fn (daemon|logs|cmd_logs)|struct .*Args|enum .*Command|logs' src --glob '*.rs'
printf '%s\n' '--- dependency and platform context ---'
rg -n -C 3 '^\[dependencies\]|^dirs\s*=|^tempfile\s*=|^rustix\s*=|^nix\s*=|^target|cfg\(unix\)|cfg\(windows\)' Cargo.toml Cargo.lock src --glob '*.rs' --glob '*.toml'Repository: getappz/agentflare Length of output: 50375 Use a private fallback log location. When Use a per-user directory with restrictive permissions, or create the log file with symlink-safe semantics. 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| pub fn daemon_start_lock_path() -> PathBuf { | ||
| dirs::runtime_dir() | ||
| .map(|d| d.join("agentflare").join("daemon.start.lock")) | ||
|
|
@@ -122,12 +132,17 @@ pub fn start_daemon() -> Result<u32, String> { | |
| } | ||
|
|
||
| let binary = std::env::current_exe().map_err(|e| format!("current_exe: {e}"))?; | ||
| let log_path = daemon_log_path(); | ||
| if let Some(parent) = log_path.parent() { | ||
| std::fs::create_dir_all(parent).map_err(|e| format!("create log dir {parent:?}: {e}"))?; | ||
| } | ||
| // Must match the `ExecStart`/`ProgramArguments` invocation the installed | ||
| // systemd/launchd units use (see `daemon_autostart.rs`) — both spawn | ||
| // `serve --_foreground-daemon`, not just the bare flag. | ||
| let _pid = process::spawn_detached( | ||
| &binary.to_string_lossy(), | ||
| &["serve", "--_foreground-daemon"], | ||
| Some(&log_path), | ||
| )?; | ||
|
|
||
| for _ in 0..20 { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: getappz/agentflare
Length of output: 7033
🏁 Script executed:
Repository: getappz/agentflare
Length of output: 6023
🏁 Script executed:
Repository: getappz/agentflare
Length of output: 2415
🏁 Script executed:
Repository: getappz/agentflare
Length of output: 513
Reset the cursor after log truncation.
A daemon restart truncates
daemon.logthroughFile::create. The open follower handle keeps its previous offset. If the new log is shorter than that offset,--followmisses new output until the file grows beyond the old offset.Before each follow read, compare
file.stream_position()withfile.metadata()?.len(). If the file shrank, seek to offset zero before reading.🤖 Prompt for AI Agents