fix: limit idevice log file size

This commit is contained in:
CelloSerenity 2026-09-27 13:46:33 -06:00
parent f50353c643
commit 2d09a405de
4 changed files with 71 additions and 8 deletions

View file

@ -9,6 +9,7 @@ import UIKit
enum AppBootstrapper {
static func configure() {
IdeviceLogFileManager.shared.prepareForLogging()
registerDefaultSettings()
startConfiguredKeepAliveServices()
applyDocumentPickerCopyWorkaround()

View file

@ -82,11 +82,7 @@ final class JITEnableContext {
var handshakeHandle: OpaquePointer? { handshake }
private init() {
let logURL = FileManager.default
.urls(for: .documentDirectory, in: .userDomainMask)[0]
.appendingPathComponent("idevice_log.txt")
var path = Array(logURL.path.utf8CString)
var path = Array(IdeviceLogFileManager.logURL.path.utf8CString)
path.withUnsafeMutableBufferPointer { buffer in
_ = idevice_init_logger(Info, Debug, buffer.baseAddress)
}

View file

@ -0,0 +1,66 @@
//
// IdeviceLogFileManager.swift
// StikDebug
//
import Foundation
final class IdeviceLogFileManager {
static let shared = IdeviceLogFileManager()
static let logURL = URL.documentsDirectory.appendingPathComponent("idevice_log.txt")
private static let maximumSize: UInt64 = 20 * 1024 * 1024
private static let retainedSize: UInt64 = 10 * 1024 * 1024
private static let checkInterval: TimeInterval = 5
private let queue = DispatchQueue(label: "com.stik.ideviceLogFile", qos: .utility)
private var timer: DispatchSourceTimer?
private init() {}
func prepareForLogging() {
compactIfNeeded()
queue.async {
guard self.timer == nil else { return }
let timer = DispatchSource.makeTimerSource(queue: self.queue)
timer.schedule(deadline: .now() + Self.checkInterval, repeating: Self.checkInterval)
timer.setEventHandler { [weak self] in
self?.compactIfNeeded()
}
self.timer = timer
timer.resume()
}
}
private func compactIfNeeded() {
let fileManager = FileManager.default
guard let attributes = try? fileManager.attributesOfItem(atPath: Self.logURL.path),
let fileSize = attributes[.size] as? NSNumber,
fileSize.uint64Value > Self.maximumSize,
let handle = try? FileHandle(forUpdating: Self.logURL) else {
return
}
defer { try? handle.close() }
do {
let endOffset = try handle.seekToEnd()
let startOffset = endOffset > Self.retainedSize ? endOffset - Self.retainedSize : 0
try handle.seek(toOffset: startOffset)
var recentData = try handle.readToEnd() ?? Data()
if startOffset > 0, let newlineIndex = recentData.firstIndex(of: 0x0A) {
recentData.removeSubrange(recentData.startIndex...newlineIndex)
}
try handle.truncate(atOffset: 0)
try handle.seek(toOffset: 0)
try handle.write(contentsOf: recentData)
try handle.synchronize()
} catch {
return
}
}
}

View file

@ -266,7 +266,7 @@ struct ConsoleLogsView: View {
@ViewBuilder
private var exportMenuOption: some View {
let logURL: URL = URL.documentsDirectory.appendingPathComponent("idevice_log.txt")
let logURL = IdeviceLogFileManager.logURL
if FileManager.default.fileExists(atPath: logURL.path) {
ShareLink(
item: logURL,
@ -309,7 +309,7 @@ struct ConsoleLogsView: View {
guard !isLoadingLogs else { return }
isLoadingLogs = true
let logPath = URL.documentsDirectory.appendingPathComponent("idevice_log.txt").path
let logPath = IdeviceLogFileManager.logURL.path
guard FileManager.default.fileExists(atPath: logPath) else {
await MainActor.run {
@ -368,7 +368,7 @@ struct ConsoleLogsView: View {
guard !isLoadingLogs else { return }
isLoadingLogs = true
let logPath = URL.documentsDirectory.appendingPathComponent("idevice_log.txt").path
let logPath = IdeviceLogFileManager.logURL.path
let previousCount = lastProcessedLineCount
guard FileManager.default.fileExists(atPath: logPath) else {