mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Simple debug log
This commit is contained in:
parent
7f33422db6
commit
ef6068321d
5 changed files with 102 additions and 2 deletions
|
|
@ -207,6 +207,7 @@
|
|||
DDF45C342BC1A48E005ED5F2 /* MQTTIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF45C332BC1A48E005ED5F2 /* MQTTIcon.swift */; };
|
||||
DDF45C372BC46A5A005ED5F2 /* TimeZone.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF45C362BC46A5A005ED5F2 /* TimeZone.swift */; };
|
||||
DDF6B2482A9AEBF500BA6931 /* StoreForwardConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF6B2472A9AEBF500BA6931 /* StoreForwardConfig.swift */; };
|
||||
DDF8E1F42C10125B0019C87E /* AppLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF8E1F32C10125B0019C87E /* AppLog.swift */; };
|
||||
DDF924CA26FBB953009FE055 /* ConnectedDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF924C926FBB953009FE055 /* ConnectedDevice.swift */; };
|
||||
DDFEB3BB29900C1200EE7472 /* CurrentConditionsCompact.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFEB3BA29900C1200EE7472 /* CurrentConditionsCompact.swift */; };
|
||||
DDFFA7472B3A7F3C004730DB /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFFA7462B3A7F3C004730DB /* Bundle.swift */; };
|
||||
|
|
@ -481,6 +482,7 @@
|
|||
DDF6B2462A9AEB9E00BA6931 /* MeshtasticDataModelV17.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV17.xcdatamodel; sourceTree = "<group>"; };
|
||||
DDF6B2472A9AEBF500BA6931 /* StoreForwardConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreForwardConfig.swift; sourceTree = "<group>"; };
|
||||
DDF6B24B2A9C2FC800BA6931 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
DDF8E1F32C10125B0019C87E /* AppLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLog.swift; sourceTree = "<group>"; };
|
||||
DDF924C926FBB953009FE055 /* ConnectedDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectedDevice.swift; sourceTree = "<group>"; };
|
||||
DDFEB3BA29900C1200EE7472 /* CurrentConditionsCompact.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentConditionsCompact.swift; sourceTree = "<group>"; };
|
||||
DDFFA7462B3A7F3C004730DB /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -590,6 +592,7 @@
|
|||
DD93800C2BA74CE3008BEC06 /* Channels */,
|
||||
DD97E96728EFE9A00056DDA4 /* About.swift */,
|
||||
DD0F791A28713C8A00A6FDAD /* AdminMessageList.swift */,
|
||||
DDF8E1F32C10125B0019C87E /* AppLog.swift */,
|
||||
DD4A911D2708C65400501B7E /* AppSettings.swift */,
|
||||
DDAB580C2B0DAA9E00147258 /* Routes.swift */,
|
||||
DDE9659B2B1C3B6A00531070 /* RouteRecorder.swift */,
|
||||
|
|
@ -1237,6 +1240,7 @@
|
|||
DD8ED9C8289CE4B900B3B0AB /* RoutingError.swift in Sources */,
|
||||
DD5E5202298EE33B00D21B61 /* admin.pb.swift in Sources */,
|
||||
DDC1B81A2AB5377B00C71E39 /* MessagesTips.swift in Sources */,
|
||||
DDF8E1F42C10125B0019C87E /* AppLog.swift in Sources */,
|
||||
DD964FC62975DBFD007C176F /* QueryCoreData.swift in Sources */,
|
||||
DDB75A112A059258006ED576 /* Url.swift in Sources */,
|
||||
DDAD49ED2AFB39DC00B4425D /* MeshMap.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@
|
|||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
askForAppToLaunch = "Yes"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
|
|
|
|||
|
|
@ -23,4 +23,45 @@ extension Logger {
|
|||
|
||||
/// All logs related to tracking and analytics.
|
||||
static let statistics = Logger(subsystem: subsystem, category: "📈 Stats")
|
||||
|
||||
/// Fetch from the logstore
|
||||
static public func fetch(since date: Date, predicateFormat: String) async throws -> [String] {
|
||||
|
||||
let store = try OSLogStore(scope: .currentProcessIdentifier)
|
||||
let position = store.position(date: date)
|
||||
let predicate = NSPredicate(format: predicateFormat)
|
||||
let entries = try store.getEntries(at: position, matching: predicate)
|
||||
|
||||
var logs: [String] = []
|
||||
for entry in entries {
|
||||
|
||||
try Task.checkCancellation()
|
||||
|
||||
if let log = entry as? OSLogEntryLog {
|
||||
logs.append("""
|
||||
\(entry.date.formatted(.dateTime.hour(.twoDigits(amPM: .omitted)).minute().second().secondFraction(.fractional(3)))) \(log.level.description) \
|
||||
\(log.category) \(entry.composedMessage)\n
|
||||
""")
|
||||
} else {
|
||||
logs.append("\(entry.date): \(entry.composedMessage)\n")
|
||||
}
|
||||
}
|
||||
|
||||
if logs.isEmpty { logs = ["Nothing found"] }
|
||||
return logs
|
||||
}
|
||||
}
|
||||
|
||||
extension OSLogEntryLog.Level {
|
||||
fileprivate var description: String {
|
||||
switch self {
|
||||
case .undefined: "undefined"
|
||||
case .debug: "Debug"
|
||||
case .info: "Info"
|
||||
case .notice: "Notice"
|
||||
case .error: "Error"
|
||||
case .fault: "Fault"
|
||||
@unknown default: "default"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
54
Meshtastic/Views/Settings/AppLog.swift
Normal file
54
Meshtastic/Views/Settings/AppLog.swift
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// AppLog.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Created by Garth Vander Houwen on 6/4/24.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import OSLog
|
||||
|
||||
struct AppLog: View {
|
||||
@State private var text = "Loading..."
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
Text(text)
|
||||
.textSelection(.enabled)
|
||||
.fontDesign(.monospaced)
|
||||
.font(.caption2)
|
||||
.padding()
|
||||
}
|
||||
.task {
|
||||
text = await fetchLogs()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AppLog {
|
||||
static private let template = NSPredicate(format:
|
||||
"(subsystem BEGINSWITH $PREFIX) || ((subsystem IN $SYSTEM) && ((messageType == error) || (messageType == fault)))")
|
||||
|
||||
@MainActor
|
||||
private func fetchLogs() async -> String {
|
||||
let calendar = Calendar.current
|
||||
guard let dayAgo = calendar.date(byAdding: .day,
|
||||
value: -1, to: Date.now) else {
|
||||
return "Invalid calendar"
|
||||
}
|
||||
|
||||
do {
|
||||
let predicate = AppLog.template.withSubstitutionVariables(
|
||||
[
|
||||
"PREFIX": "gvh.MeshtasticClient",
|
||||
"SYSTEM": ["com.apple.coredata"]
|
||||
])
|
||||
|
||||
let logs = try await Logger.fetch(since: dayAgo,
|
||||
predicateFormat: predicate.predicateFormat)
|
||||
return logs.joined()
|
||||
} catch {
|
||||
return error.localizedDescription
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -426,10 +426,10 @@ struct Settings: View {
|
|||
.tag(SettingsSidebar.adminMessageLog)
|
||||
#if DEBUG
|
||||
NavigationLink {
|
||||
// AppLogs()
|
||||
AppLog()
|
||||
} label: {
|
||||
Label {
|
||||
Text("app.log")
|
||||
Text("Debug Logs")
|
||||
} icon: {
|
||||
Image(systemName: "building.columns")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue