Simple debug log

This commit is contained in:
Garth Vander Houwen 2024-06-04 22:41:45 -07:00
parent 7f33422db6
commit ef6068321d
5 changed files with 102 additions and 2 deletions

View file

@ -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 */,

View file

@ -89,6 +89,7 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"
askForAppToLaunch = "Yes"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View file

@ -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"
}
}
}

View 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
}
}
}

View file

@ -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")
}