feat(client): 桌面端日志加本地时间戳前缀 [HH:MM:SS.mmm]
ci-pangolin / Lint — shellcheck (push) Has been cancelled
ci-pangolin / OpenAPI Sync Check (push) Has been cancelled
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Has been cancelled
ci-pangolin / Flutter — analyze + test (push) Has been cancelled

新增 log_time.dart(共享 logTime() helper),DesktopKernel / DesktopVpnBridge
所有日志行首打 [时:分:秒.毫秒],便于排查连接时序。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-18 21:56:38 +08:00
parent 52edb377e4
commit df75d3a135
3 changed files with 22 additions and 12 deletions
+12 -11
View File
@@ -25,6 +25,7 @@ import 'dart:convert';
import 'dart:io';
import 'kernel_process.dart';
import 'log_time.dart';
import 'vpn_bridge.dart';
/// 桌面端 VPN 桥接实现(macOS / Linux / Windows PoC)。
@@ -100,9 +101,9 @@ class DesktopVpnBridge implements VpnBridge {
// 3. 写 config 到应用支持目录(0600 权限)
final configPath = await writeConfig(enrichedJson);
print('[DesktopVpnBridge] config written: $configPath');
print('[DesktopVpnBridge] clash_api port=$port secret_len=${secret.length}');
print('[DesktopVpnBridge] killSwitch=$_killSwitchEnabled');
print('${logTime()}[DesktopVpnBridge] config written: $configPath');
print('${logTime()}[DesktopVpnBridge] clash_api port=$port secret_len=${secret.length}');
print('${logTime()}[DesktopVpnBridge] killSwitch=$_killSwitchEnabled');
// 4. 启动内核子进程(blocking until Clash API ready or error
await _kernel.spawn(configPath);
@@ -141,7 +142,7 @@ class DesktopVpnBridge implements VpnBridge {
try {
await _kernel.clashApiClient.selectProxy('proxy', tag);
} catch (e) {
print('[DesktopVpnBridge] selectOutbound(tag=$tag) error: $e');
print('${logTime()}[DesktopVpnBridge] selectOutbound(tag=$tag) error: $e');
rethrow;
}
}
@@ -177,11 +178,11 @@ class DesktopVpnBridge implements VpnBridge {
Future<void> setKillSwitch({required bool on}) async {
if (_killSwitchEnabled == on) return;
_killSwitchEnabled = on;
print('[DesktopVpnBridge] setKillSwitch=$on');
print('${logTime()}[DesktopVpnBridge] setKillSwitch=$on');
// 若内核正在运行,用新设置重载(会有约 1~2s 重连)
if (_kernel.isRunning && _lastUserConfigJson != null) {
print('[DesktopVpnBridge] reloading kernel for killSwitch change');
print('${logTime()}[DesktopVpnBridge] reloading kernel for killSwitch change');
// 暂停自动重连,避免 kill 触发重连定时器
final wasAutoReconnect = _shouldAutoReconnect;
_shouldAutoReconnect = false;
@@ -230,17 +231,17 @@ class DesktopVpnBridge implements VpnBridge {
_reconnectAttempt++;
print(
'[DesktopVpnBridge] auto-reconnect in ${delaySec}s (attempt $_reconnectAttempt)');
'${logTime()}[DesktopVpnBridge] auto-reconnect in ${delaySec}s (attempt $_reconnectAttempt)');
_reconnectTimer = Timer(Duration(seconds: delaySec), () async {
if (!_shouldAutoReconnect || _lastUserConfigJson == null) return;
try {
print('[DesktopVpnBridge] auto-reconnect: attempting start...');
print('${logTime()}[DesktopVpnBridge] auto-reconnect: attempting start...');
await start(_lastUserConfigJson!);
_reconnectAttempt = 0; // 成功后重置退避计数
print('[DesktopVpnBridge] auto-reconnect: success');
print('${logTime()}[DesktopVpnBridge] auto-reconnect: success');
} catch (e) {
print('[DesktopVpnBridge] auto-reconnect: start failed: $e');
print('${logTime()}[DesktopVpnBridge] auto-reconnect: start failed: $e');
// start() 失败(内核未能启动)→ 手动调度下一次重试
if (_shouldAutoReconnect) _scheduleReconnect();
}
@@ -341,7 +342,7 @@ class DesktopVpnBridge implements VpnBridge {
try {
await Process.run('chmod', ['600', file.path]);
} catch (_) {
print('[DesktopVpnBridge] warning: chmod 600 failed for ${file.path}');
print('${logTime()}[DesktopVpnBridge] warning: chmod 600 failed for ${file.path}');
}
}
return file.path;
+2 -1
View File
@@ -30,6 +30,7 @@ import 'dart:math' as math;
import 'package:http/http.dart' as http;
import 'log_time.dart';
import 'vpn_bridge.dart';
// ══════════════════════════════════════════════════════════════════
@@ -481,7 +482,7 @@ class DesktopKernelProcess implements KernelProcess {
}
void _log(String msg) {
print('[DesktopKernel] $msg');
print('${logTime()}[DesktopKernel] $msg');
if (!_logCtrl.isClosed) _logCtrl.add(msg);
}
+8
View File
@@ -0,0 +1,8 @@
// log_time.dart — 桌面端日志统一时间戳前缀。
// 返回本地时间 "[HH:MM:SS.mmm] ",拼在日志行首便于排查时序。
String logTime() {
final n = DateTime.now();
String p(int v, [int w = 2]) => v.toString().padLeft(w, '0');
return '[${p(n.hour)}:${p(n.minute)}:${p(n.second)}.${p(n.millisecond, 3)}] ';
}