refactor(log): in-place writer lifecycle and span-based core observability (#7889)

* refactor(log): migrate logging to tracing-estuary pipeline

Swap flexi_logger + clash-verge-logger wiring for the tracing-estuary
crate: buffered file sink with explicit panic/exit drains, live level
switching, and tokio-trace/chrome-trace behind crate features.

AsyncLogger moves in-house (VecDeque ring); file format and rotation
stay unchanged.

* fix(log): reset sidecar writer in place and re-pin service-ipc v2.6.7

Rebuilding the sidecar FileLogWriter on config changes leaked flexi's
unstoppable flusher thread plus an fd each time; the writer is now flushed
and reset in place, matching what the service crate does.
get_clash_logs_by_service drops the CompactString conversion layer now that
service-ipc v2.6.7 returns plain Vec<String>, and AsyncLogger is renamed
LogRing to match.

* refactor(log): span-based observability and log noise cleanup

Instrument spans carry the structure flat lines never could: the core-start
spine (mode, readiness/owner generations, pid, config file), proxy apply and
clear routes with guard generations, service IPC sessions with refusal codes
and outcomes, profile-switch terminal outcomes, subscription fetch strategies,
core upgrades with per-proxy version probes, backup flows, timer tasks, config
generation uids, and the startup setup flow; running-mode changes emit one
guarded transition event each.
~90 hand-written noise lines are gone or demoted (entry+success pairs, polled
getter echoes, phase brackets, window sub-steps, platform install chatter);
errors keep their anyhow chain, operation name, and item id, and swallowed
retry results surface per attempt.
This commit is contained in:
Tunglies
2026-09-08 05:51:04 +08:00
committed by GitHub
parent f8b69b5d62
commit 2f370d6490
43 changed files with 807 additions and 797 deletions
+5 -11
View File
@@ -132,7 +132,7 @@ impl Timer {
if let Err(e) = self.refresh().await {
self.initialized.store(false, Ordering::SeqCst);
logging_error!(Type::Timer, "Failed to initialize timer: {}", e);
logging!(error, Type::Timer, "Failed to initialize timer: {e:#}");
return Err(e);
}
@@ -424,7 +424,7 @@ impl Timer {
}
fn spawn_update_task(uid: String, command_tx: mpsc::UnboundedSender<TimerCommand>) {
logging!(info, Type::Timer, "Starting timer task: uid={}", uid);
logging!(debug, Type::Timer, "Starting timer task: uid={}", uid);
AsyncHandler::spawn(move || async move {
Self::wait_until_resolve_done(Duration::from_millis(5000)).await;
Self::async_task(&uid).await;
@@ -466,8 +466,8 @@ impl Timer {
}
}
#[tracing::instrument(skip_all, level = "info", fields(uid = %uid))]
async fn async_task(uid: &String) {
let task_start = std::time::Instant::now();
logging!(debug, Type::Timer, "Running timer task for profile: {}", uid);
run_timer_profile_update_transition(
@@ -475,15 +475,9 @@ impl Timer {
|| feat::update_profile(uid, None, false),
|result| match result {
Ok(_) => {
logging!(
info,
Type::Timer,
"Timer task completed for uid: {} (took {}ms)",
uid,
task_start.elapsed().as_millis()
);
logging!(debug, Type::Timer, "timer task completed for uid: {}", uid);
}
Err(e) => logging_error!(Type::Timer, "Failed to update profile uid {}: {}", uid, e),
Err(e) => logging_error!(Type::Timer, "Failed to update profile uid {}: {e:#}", uid),
},
|| Self::emit_update_event(uid, false),
)