Files
ICCery-CPU/Sources/Logging.swift
T
Local Admin 43bff18101
Build macOS Packages / Build macOS (Intel) (push) Failing after 10s
Build macOS Packages / Build macOS (Apple Silicon) (push) Failing after 10s
Build macOS Packages / Build macOS (Universal) (push) Skipped
removed cruft and restructured.
2026-09-07 05:21:44 -07:00

86 lines
3.1 KiB
Swift

import Foundation
import os.log
/// SPEC §13: os_log subsystem `com.iccery.TargetPrint`, optional rotating file under
/// `~/Library/Logs/TargetPrint/` when launched with `--verbose`.
enum TPLog {
static let subsystem = "com.iccery.TargetPrint"
static let os = OSLog(subsystem: subsystem, category: "engine")
private static var verbose = false
private static var fileHandle: FileHandle?
private static let queue = DispatchQueue(label: "com.iccery.TargetPrint.log")
static func setVerbose(_ on: Bool) {
verbose = on
if on { openFileIfNeeded() }
}
static var isVerbose: Bool { verbose }
static func debug(_ message: String) {
os_log("%{public}@", log: os, type: .debug, message)
writeFile("DEBUG", message)
}
static func info(_ message: String) {
os_log("%{public}@", log: os, type: .info, message)
writeFile("INFO", message)
}
static func error(_ message: String) {
os_log("%{public}@", log: os, type: .error, message)
writeFile("ERROR", message)
}
static func fault(_ message: String) {
os_log("%{public}@", log: os, type: .fault, message)
writeFile("FAULT", message)
}
private static func openFileIfNeeded() {
queue.sync {
guard fileHandle == nil else { return }
let dir = FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent("Library/Logs/TargetPrint", isDirectory: true)
try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true)
let url = dir.appendingPathComponent("TargetPrint.log")
if !FileManager.default.fileExists(atPath: url.path) {
FileManager.default.createFile(atPath: url.path, contents: nil)
}
rotateIfNeeded(url)
fileHandle = try? FileHandle(forWritingTo: url)
fileHandle?.seekToEndOfFile()
}
}
private static func rotateIfNeeded(_ url: URL) {
let maxBytes: UInt64 = 2 * 1024 * 1024
guard let attrs = try? FileManager.default.attributesOfItem(atPath: url.path),
let size = attrs[.size] as? UInt64,
size > maxBytes else { return }
let bak = url.deletingPathExtension().appendingPathExtension("log.1")
try? FileManager.default.removeItem(at: bak)
try? FileManager.default.moveItem(at: url, to: bak)
FileManager.default.createFile(atPath: url.path, contents: nil)
}
private static func writeFile(_ level: String, _ message: String) {
guard verbose else { return }
queue.async {
let line = "\(isoNow()) [\(level)] \(message)\n"
if let data = line.data(using: .utf8) {
fileHandle?.write(data)
}
}
}
private static func isoNow() -> String {
let f = DateFormatter()
f.locale = Locale(identifier: "en_US_POSIX")
f.timeZone = TimeZone(secondsFromGMT: 0)
f.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
return f.string(from: Date())
}
}