forked from shadowfacts/Tusker
Include log data in issue/crash reports
This commit is contained in:
parent
afa1a733f4
commit
d661870401
|
@ -2,6 +2,22 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>OSLogPreferences</key>
|
||||
<dict>
|
||||
<key>$(PRODUCT_BUNDLE_IDENTIFIER)</key>
|
||||
<dict>
|
||||
<key>DEFAULT-OPTIONS</key>
|
||||
<dict>
|
||||
<key>Level</key>
|
||||
<dict>
|
||||
<key>Persist</key>
|
||||
<string>Debug</string>
|
||||
<key>Enable</key>
|
||||
<string>Debug</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
|
@ -16,19 +32,6 @@
|
|||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>net.shadowfacts.Tusker</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>tusker</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
|
@ -56,7 +59,7 @@
|
|||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Post videos from the camera.</string>
|
||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||
<string>Save photos directly from other people's posts.</string>
|
||||
<string>Save photos directly from other people's posts.</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Post photos from the photo library.</string>
|
||||
<key>NSUserActivityTypes</key>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
import UIKit
|
||||
import CrashReporter
|
||||
import MessageUI
|
||||
import OSLog
|
||||
|
||||
class IssueReporterViewController: UIViewController {
|
||||
|
||||
|
@ -34,6 +35,8 @@ class IssueReporterViewController: UIViewController {
|
|||
"Tusker Error Report"
|
||||
}
|
||||
|
||||
private let logDataTask: Task<Data?, Never>
|
||||
|
||||
@IBOutlet weak var crashReportTextView: UITextView!
|
||||
@IBOutlet weak var sendReportButton: UIButton!
|
||||
|
||||
|
@ -41,6 +44,15 @@ class IssueReporterViewController: UIViewController {
|
|||
self.reportText = reportText
|
||||
self.reportFilename = reportFilename
|
||||
self.dismiss = dismiss
|
||||
|
||||
self.logDataTask = Task(priority: .userInitiated) {
|
||||
return await withCheckedContinuation({ continuation in
|
||||
DispatchQueue.global().async {
|
||||
continuation.resume(returning: getLogData())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
super.init(nibName: "IssueReporterViewController", bundle: .main)
|
||||
}
|
||||
|
||||
|
@ -107,6 +119,7 @@ class IssueReporterViewController: UIViewController {
|
|||
@IBAction func sendReportTouchUpInside(_ sender: Any) {
|
||||
updateSendReportButtonColor(lightened: false, animate: true)
|
||||
|
||||
Task {
|
||||
let composeVC = MFMailComposeViewController()
|
||||
composeVC.mailComposeDelegate = self
|
||||
composeVC.setToRecipients(["me@shadowfacts.net"])
|
||||
|
@ -115,8 +128,14 @@ class IssueReporterViewController: UIViewController {
|
|||
let data = reportText.data(using: .utf8)!
|
||||
composeVC.addAttachmentData(data, mimeType: "text/plain", fileName: reportFilename)
|
||||
|
||||
if let logData = await logDataTask.value {
|
||||
let timestamp = ISO8601DateFormatter().string(from: Date())
|
||||
composeVC.addAttachmentData(logData, mimeType: "text/plain", fileName: "Tusker-\(timestamp).log")
|
||||
}
|
||||
|
||||
self.present(composeVC, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func sendReportButtonLongPressed() {
|
||||
let dir = FileManager.default.temporaryDirectory
|
||||
|
@ -139,3 +158,29 @@ extension IssueReporterViewController: MFMailComposeViewControllerDelegate {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func getLogData() -> Data? {
|
||||
do {
|
||||
let store = try OSLogStore(scope: .currentProcessIdentifier)
|
||||
// past hour
|
||||
let position = store.position(date: Date().addingTimeInterval(-60 * 60))
|
||||
let entries = try store.getEntries(at: position, matching: NSPredicate(format: "subsystem = %@", Bundle.main.bundleIdentifier!))
|
||||
var data = Data()
|
||||
for entry in entries {
|
||||
guard let entry = entry as? OSLogEntryLog else {
|
||||
continue
|
||||
}
|
||||
data.append(contentsOf: entry.date.formatted(.iso8601).utf8)
|
||||
data.append(32) // ' '
|
||||
data.append(91) // '['
|
||||
data.append(contentsOf: entry.category.utf8)
|
||||
data.append(93) // ']'
|
||||
data.append(32) // ' '
|
||||
data.append(contentsOf: entry.composedMessage.utf8)
|
||||
data.append(10) // '\n'
|
||||
}
|
||||
return data
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue