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
+15 -6
View File
@@ -471,10 +471,13 @@ fn table_effect(result: &Result<()>) -> TableEffect<'_> {
}
}
#[tracing::instrument(skip_all, level = "info", fields(route = tracing::field::Empty))]
pub async fn apply() -> Result<()> {
let running_mode = CoreManager::global().get_running_mode();
let verge = Config::verge().await.latest_arc();
let result = match proxy_backend_route(cfg!(target_os = "macos"), &running_mode) {
let route = proxy_backend_route(cfg!(target_os = "macos"), &running_mode);
tracing::Span::current().record("route", tracing::field::debug(&route));
let result = match route {
ProxyBackendRoute::Local => match Sysopt::global().update_sysproxy().await {
Ok(()) => Ok(()),
Err(error) => Err(classify_local_apply_failure(error).await),
@@ -520,7 +523,7 @@ pub async fn clear() -> Result<()> {
/// A failed system call is usually a transient RPC hiccup, so give it a few tries.
async fn clear_with_retry() -> Result<()> {
for _ in 1..CLEAR_ATTEMPTS {
for attempt in 1..CLEAR_ATTEMPTS {
match clear_inner().await {
Err(error)
if matches!(
@@ -531,7 +534,7 @@ async fn clear_with_retry() -> Result<()> {
logging!(
warn,
Type::Core,
"clearing the system proxy failed; retrying: {error:#}"
"clearing the system proxy failed (attempt {attempt}/{CLEAR_ATTEMPTS}); retrying: {error:#}"
);
tokio::time::sleep(CLEAR_RETRY_DELAY).await;
}
@@ -541,9 +544,12 @@ async fn clear_with_retry() -> Result<()> {
clear_inner().await
}
#[tracing::instrument(skip_all, level = "info", fields(route = tracing::field::Empty))]
async fn clear_inner() -> Result<()> {
let running_mode = CoreManager::global().get_running_mode();
match proxy_backend_route(cfg!(target_os = "macos"), &running_mode) {
let route = proxy_backend_route(cfg!(target_os = "macos"), &running_mode);
tracing::Span::current().record("route", tracing::field::debug(&route));
match route {
ProxyBackendRoute::Local => Sysopt::global().reset_sysproxy().await.map_err(classify_local_failure),
ProxyBackendRoute::Service => {
SERVICE_PROXY_OPERATIONS
@@ -599,13 +605,16 @@ pub async fn refresh_guard() -> Result<()> {
.await
{
Ok(true) => consecutive_failures = 0,
Ok(false) => break,
Ok(false) => {
logging!(debug, Type::Core, "proxy guard superseded (generation {generation})");
break;
}
Err(error) => {
consecutive_failures += 1;
logging!(
warn,
Type::Core,
"failed to refresh system proxy through Service ({}/{}): {:#}",
"failed to refresh system proxy through Service (generation {generation}, {}/{}): {:#}",
consecutive_failures,
GUARD_FAILURES_BEFORE_STOPPING,
error