Supports exporting OSLogs from ErrorLogViewController

This commit is contained in:
Riley Testut
2023-10-18 14:26:37 -05:00
parent a092c99b84
commit 22d204be6b
2 changed files with 98 additions and 7 deletions

View File

@@ -33,6 +33,9 @@ class ErrorLogViewController: UITableViewController
return dateFormatter
}()
@IBOutlet private var exportLogButton: UIBarButtonItem!
@IBOutlet private var clearLogButton: UIBarButtonItem!
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
@@ -43,6 +46,14 @@ class ErrorLogViewController: UITableViewController
self.tableView.dataSource = self.dataSource
self.tableView.prefetchDataSource = self.dataSource
self.exportLogButton.activityIndicatorView.color = .white
if #unavailable(iOS 15)
{
// Assign just clearLogButton to hide export button.
self.navigationItem.rightBarButtonItems = [self.clearLogButton]
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
@@ -260,6 +271,77 @@ private extension ErrorLogViewController
{
self.performSegue(withIdentifier: "showErrorDetails", sender: loggedError)
}
@available(iOS 15, *)
@IBAction func exportDetailedLog(_ sender: UIBarButtonItem)
{
self.exportLogButton.isIndicatingActivity = true
Task<Void, Never>.detached(priority: .userInitiated) {
do
{
let store = try OSLogStore(scope: .currentProcessIdentifier)
// All logs since the app launched.
let position = store.position(timeIntervalSinceLatestBoot: 0)
let entries = try store.getEntries(at: position)
.compactMap { $0 as? OSLogEntryLog }
.filter { $0.subsystem.contains(Logger.altstoreSubsystem) }
.map { "[\($0.date.formatted())] [\($0.category)] [\($0.level.localizedName)] \($0.composedMessage)" }
let outputText = entries.joined(separator: "\n")
let outputDirectory = FileManager.default.uniqueTemporaryURL()
try FileManager.default.createDirectory(at: outputDirectory, withIntermediateDirectories: true)
defer {
do
{
try FileManager.default.removeItem(at: outputDirectory)
}
catch
{
Logger.main.error("Failed to remove temporary log directory \(outputDirectory.lastPathComponent, privacy: .public). \(error.localizedDescription, privacy: .public)")
}
}
let outputURL = outputDirectory.appendingPathComponent("altlog.txt")
try outputText.write(to: outputURL, atomically: true, encoding: .utf8)
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
Task<Void, Never> { @MainActor in
let activityViewController = UIActivityViewController(activityItems: [outputURL], applicationActivities: nil)
activityViewController.completionWithItemsHandler = { (activityType, completed, _, error) in
if let error
{
continuation.resume(throwing: error)
}
else
{
continuation.resume()
}
}
self.present(activityViewController, animated: true)
}
}
}
catch
{
Logger.main.error("Failed to export OSLog entries. \(error.localizedDescription, privacy: .public)")
await MainActor.run {
let alertController = UIAlertController(title: NSLocalizedString("Unable to Export Detailed Log", comment: ""), message: error.localizedDescription, preferredStyle: .alert)
alertController.addAction(.ok)
self.present(alertController, animated: true)
}
}
await MainActor.run {
self.exportLogButton.isIndicatingActivity = false
}
}
}
}
extension ErrorLogViewController

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="5Rz-4h-jJ8">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22155" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="5Rz-4h-jJ8">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22131"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
@@ -1095,13 +1095,22 @@ Settings by i cons from the Noun Project</string>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Error Log" largeTitleDisplayMode="never" id="a1p-3W-bSi">
<barButtonItem key="rightBarButtonItem" systemItem="trash" id="BnQ-Eh-1gC">
<connections>
<action selector="clearLoggedErrors:" destination="g8a-Rf-zWa" id="faq-89-H5j"/>
</connections>
</barButtonItem>
<rightBarButtonItems>
<barButtonItem systemItem="trash" id="BnQ-Eh-1gC">
<connections>
<action selector="clearLoggedErrors:" destination="g8a-Rf-zWa" id="faq-89-H5j"/>
</connections>
</barButtonItem>
<barButtonItem systemItem="action" id="BNj-HE-KHr">
<connections>
<action selector="exportDetailedLog:" destination="g8a-Rf-zWa" id="Kbw-Q5-9WO"/>
</connections>
</barButtonItem>
</rightBarButtonItems>
</navigationItem>
<connections>
<outlet property="clearLogButton" destination="BnQ-Eh-1gC" id="MHl-Kh-ick"/>
<outlet property="exportLogButton" destination="BNj-HE-KHr" id="w9g-yA-0Yx"/>
<segue destination="7gm-d1-zWK" kind="presentation" identifier="showErrorDetails" id="9vz-y6-evp"/>
</connections>
</tableViewController>