Files
ShadowsocksX-NG/ShadowsocksX-NG2/Domain/Runtime/RuntimeEventStore.swift
T
Qiu Yuzhou 1d85e86b8e feat(diagnostics): unify log lines into one filtered view
Collapse the four definitions of "one log line" into LogLine (timestamp,
level, source, text) with a single renderer and parser. agent.log lines
now carry the uniform prefix, absorbing the ssxng: event marker into the
source column; legacy lines degrade to raw display without rewriting.
Level detection moves into the row model with a classic three-level
taxonomy whose unified-log projection stays unchanged.

The diagnostics log view merges GUI events and the agent.log tail through
DiagnosticLogIntake into one time-ordered list with level and source
filters; the tail window logic moves into the intake and blank lines are
kept for raw fidelity. The report whitelist projection and unified-log
routing are unchanged.
2026-10-20 14:42:51 +08:00

59 lines
2.0 KiB
Swift

import Foundation
/// GUI 侧运行事件环形缓冲:收集 `RuntimeLog.emit`
/// 的事件供主窗口日志查看器实时呈现与诊断导出取用。事件文本来自封闭枚举的
/// 渲染,构造上不含敏感值;容量封顶只留最近事件(够诊断即可,不做复杂轮转)。
/// wrapper 进程不使用本存储(其 stderr 已收敛进 agent.log)。
final class RuntimeEventStore: RuntimeEventSink, @unchecked Sendable {
struct Entry: Equatable, Identifiable {
let id: Int
let timestamp: Date
/// 事件原值(封闭枚举):原始呈现与报告白名单投影共用同一事实。
let event: RuntimeLogEvent
/// 事件文本(查看器与原始行共用)。
var text: String { event.description }
/// 查看器共用的行格式;固定 POSIX locale 保证报障对照不随用户
/// 区域漂移。
var renderedLine: String {
renderedLine(eventText: text)
}
/// 指定事件文本的行格式;报告侧先经白名单清洗,再复用相同时间戳与间隔。
/// 时间戳格式与统一日志行(`LogLine`)共用同一 POSIX 格式器。
func renderedLine(eventText: String) -> String {
"\(LogLine.timestampFormatter.string(from: timestamp)) \(eventText)"
}
}
/// 进程级共享实例:GUI 启动时注册为 RuntimeLog 的接收缝。
static let shared = RuntimeEventStore()
private let lock = NSLock()
private var entries: [Entry] = []
private var nextID = 0
private let capacity: Int
init(capacity: Int = 500) {
self.capacity = max(1, capacity)
}
/// 当前缓冲快照(旧→新)。
var snapshot: [Entry] {
lock.lock()
defer { lock.unlock() }
return entries
}
func append(event: RuntimeLogEvent, timestamp: Date = Date()) {
lock.lock()
defer { lock.unlock() }
entries.append(Entry(id: nextID, timestamp: timestamp, event: event))
nextID += 1
if entries.count > capacity {
entries.removeFirst(entries.count - capacity)
}
}
}