macsync/@packages/shared/Sources/MacSyncShared/Sync/TraceLog.swift
Natalie b104ee1b12 fix(@mac-sync): 🐛 add debug flag for send-queue tracing
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-05-21 19:39:09 -07:00

49 lines
2 KiB
Swift

import Foundation
/// Dead-simple append-only file tracer for diagnosing the send-queue
/// lifecycle when macOS unified logging is not reachable from the debugging
/// environment. Writes timestamped lines to:
///
/// ~/Library/Application Support/MacSync/sendqueue-trace.log
///
/// Intentionally minimal and dependency-free. Serialized on a private queue
/// so concurrent callers don't interleave partial lines.
public enum TraceLog {
/// Verbose send-queue file tracing. Disabled unless `debugSendQueue` is
/// set `true` in the app config (`config.json` UserDefaults). The trace
/// calls are intentionally kept in the code (not deleted) so the send
/// pipeline can be re-diagnosed by flipping this flag no rebuild needed.
public static var isEnabled: Bool {
UserDefaults.standard.bool(forKey: "debugSendQueue")
}
private static let url: URL = FileManager.default
.homeDirectoryForCurrentUser
.appendingPathComponent("Library/Application Support/MacSync", isDirectory: true)
.appendingPathComponent("sendqueue-trace.log")
private static let queue = DispatchQueue(label: "com.lilith.mac-sync.tracelog")
private static let formatter: ISO8601DateFormatter = {
let f = ISO8601DateFormatter()
f.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
return f
}()
public static func write(_ message: @autoclosure () -> String) {
guard isEnabled else { return }
let line = "\(formatter.string(from: Date())) \(message())\n"
queue.async {
guard let data = line.data(using: .utf8) else { return }
let fm = FileManager.default
if !fm.fileExists(atPath: url.path) {
fm.createFile(atPath: url.path, contents: data)
return
}
guard let handle = try? FileHandle(forWritingTo: url) else { return }
defer { try? handle.close() }
handle.seekToEndOfFile()
handle.write(data)
}
}
}