Debug log updates

This commit is contained in:
Garth Vander Houwen 2024-06-05 20:46:24 -07:00
parent 2b9a4bcdbc
commit 544bbd3621
8 changed files with 174 additions and 29 deletions

View file

@ -208,6 +208,7 @@
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 */; };
DDF8E1F92C115CCE0019C87E /* LogDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF8E1F82C115CCE0019C87E /* LogDetail.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 */; };
@ -483,6 +484,7 @@
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>"; };
DDF8E1F82C115CCE0019C87E /* LogDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogDetail.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>"; };
@ -894,6 +896,7 @@
DDB75A1D2A0B0CD0006ED576 /* LoRaSignalStrengthIndicator.swift */,
DDB75A202A12B954006ED576 /* LoRaSignalStrength.swift */,
DDB75A222A13CDA9006ED576 /* BatteryLevelCompact.swift */,
DDF8E1F82C115CCE0019C87E /* LogDetail.swift */,
);
path = Helpers;
sourceTree = "<group>";
@ -1197,6 +1200,7 @@
DD5E5208298EE33B00D21B61 /* rtttl.pb.swift in Sources */,
DD6193792863875F00E59241 /* SerialConfig.swift in Sources */,
DDDB263F2AABEE20003AFCB7 /* NodeList.swift in Sources */,
DDF8E1F92C115CCE0019C87E /* LogDetail.swift in Sources */,
DDA0B6B2294CDC55001356EC /* Channels.swift in Sources */,
DDE9659C2B1C3B6A00531070 /* RouteRecorder.swift in Sources */,
B399E8A42B6F486400E4488E /* RetryButton.swift in Sources */,

View file

@ -37,14 +37,8 @@ extension Logger {
try Task.checkCancellation()
if let log = entry as? OSLogEntryLog {
logs.append(log)
// 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 let log = entry as? OSLogEntryLog {
logs.append(log)
}
}
@ -54,14 +48,14 @@ extension Logger {
}
extension OSLogEntryLog.Level {
fileprivate var description: String {
var description: String {
switch self {
case .undefined: "undefined"
case .debug: "Debug"
case .info: "Info"
case .notice: "Notice"
case .error: "Error"
case .fault: "Fault"
case .debug: "🐛 Debug"
case .info: " Info"
case .notice: "⚠️ Notice"
case .error: "🚨 Error"
case .fault: "💥 Fault"
@unknown default: "default"
}
}

View file

@ -130,7 +130,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
let context = ["name": "\(peripheral.name ?? "Unknown")"]
timeoutTimer = Timer.scheduledTimer(timeInterval: 1.5, target: self, selector: #selector(timeoutTimerFired), userInfo: context, repeats: true)
RunLoop.current.add(timeoutTimer!, forMode: .common)
Logger.services.info(" BLE Connecting: \(peripheral.name ?? "Unknown")")
Logger.services.info(" BLE Connecting: \(peripheral.name ?? "Unknown", privacy: .public)")
}
// Disconnect Connected Peripheral
@ -259,12 +259,12 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
manager.schedule()
}
lastConnectionError = "🚨 \(e.localizedDescription)"
Logger.services.error("🚨 BLE Disconnected: \(peripheral.name ?? "Unknown") Error Code: \(errorCode) Error: \(e.localizedDescription)")
Logger.services.error("🚫 BLE Disconnected: \(peripheral.name ?? "Unknown") Error Code: \(errorCode) Error: \(e.localizedDescription)")
}
} else {
// Disconnected without error which indicates user intent to disconnect
// Happens when swiping to disconnect
Logger.services.info(" BLE Disconnected: \(peripheral.name ?? "Unknown"): User Initiated Disconnect")
Logger.services.info("🚫 BLE Disconnected: \(peripheral.name ?? "Unknown"): User Initiated Disconnect")
}
// Start a scan so the disconnected peripheral is moved to the peripherals[] if it is awake
self.startScanning()
@ -3021,7 +3021,7 @@ extension BLEManager: CBCentralManagerDelegate {
if self.automaticallyReconnect && peripheral.identifier.uuidString == UserDefaults.standard.object(forKey: "preferredPeripheralId") as? String ?? "" {
self.connectTo(peripheral: peripheral)
Logger.services.info("BLE Reconnecting to prefered peripheral: \(peripheral.name ?? "Unknown")")
Logger.services.info("🔄 BLE Reconnecting to prefered peripheral: \(peripheral.name ?? "Unknown")")
}
let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String
let device = Peripheral(id: peripheral.identifier.uuidString, num: 0, name: name ?? "Unknown", shortName: "?", longName: name ?? "Unknown", firmwareVersion: "Unknown", rssi: RSSI.intValue, lastUpdate: Date(), peripheral: peripheral)

View file

@ -10,7 +10,7 @@ import OSLog
class MeshtasticAppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, ObservableObject {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
Logger.services.info("🚀 Meshtstic Apple App launched!")
Logger.services.info("🚀 Meshtastic Apple App launched!")
// Default User Default Values
UserDefaults.standard.register(defaults: ["meshMapRecentering": true])
UserDefaults.standard.register(defaults: ["meshMapShowNodeHistory": true])

View file

@ -0,0 +1,129 @@
//
// LogDetail.swift
// Meshtastic
//
// Copyright(c) Garth Vander Houwen 6/5/24.
//
import SwiftUI
import MapKit
import OSLog
@available(iOS 17.0, macOS 14.0, *)
struct LogDetail: View {
@Environment(\.dismiss) private var dismiss
var log: OSLogEntryLog
var body: some View {
VStack {
HStack {
Text("OS Log Entry Details")
.font(.largeTitle)
}
Divider()
HStack(alignment: .top) {
VStack(alignment: .leading) {
List {
/// Time
Label {
Text("time".localized + ":")
.font(.title)
LastHeardText(lastHeard: log.date)
.font(.title)
} icon: {
Image(systemName: "timer")
.symbolRenderingMode(.hierarchical)
.font(.title)
.frame(width: 35)
}
.padding(.bottom, 5)
/// Subsystem
Label {
Text("subsystem".localized + ":")
.font(.title)
Text(log.subsystem)
.font(.title)
} icon: {
Image(systemName: "gear")
.symbolRenderingMode(.hierarchical)
.font(.title)
.frame(width: 35)
}
.padding(.bottom, 5)
/// Process
Label {
Text("process".localized + ":")
.font(.title)
Text(log.process)
.font(.title)
} icon: {
Image(systemName: "tag")
.symbolRenderingMode(.hierarchical)
.font(.title)
.frame(width: 35)
}
.padding(.bottom, 5)
/// Category
Label {
Text("category".localized + ":")
.font(.title)
Text(log.category)
.font(.title)
} icon: {
Image(systemName: "rectangle.3.group")
.symbolRenderingMode(.hierarchical)
.font(.title)
.frame(width: 35)
}
.padding(.bottom, 5)
/// Level
Label {
Text("level".localized + ":")
.font(.title)
Text(log.level.description)
.font(.title)
} icon: {
Image(systemName: "shield")
.symbolRenderingMode(.hierarchical)
.font(.title)
.frame(width: 35)
}
.padding(.bottom, 5)
/// message
Label {
Text("message".localized + ":")
.font(.title)
Text(log.composedMessage)
.font(.title)
} icon: {
Image(systemName: "text.bubble")
.symbolRenderingMode(.hierarchical)
.font(.title)
.frame(width: 35)
}
.padding(.bottom, 5)
}
.listStyle(.plain)
}
Spacer()
}
.padding(.top)
#if targetEnvironment(macCatalyst)
Spacer()
Button {
dismiss()
} label: {
Label("close", systemImage: "xmark")
}
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)
.controlSize(.large)
.padding(.bottom)
#endif
}
.presentationDetents([.fraction(0.65), .fraction(0.75), .fraction(0.85)])
.presentationDragIndicator(.visible)
}
}

View file

@ -18,6 +18,7 @@ struct PositionPopover: View {
var popover: Bool = true
let distanceFormatter = MKDistanceFormatter()
var delay: Double = 0
@State private var scale: CGFloat = 0.5
var body: some View {
// Node Color from node.num

View file

@ -13,12 +13,11 @@ struct AppLog: View {
@State private var logs: [OSLogEntryLog] = []
@State private var sortOrder = [KeyPathComparator(\OSLogEntryLog.date)]
@State private var selection = Set<OSLogEntryLog.ID>()
@State private var selection: OSLogEntry.ID?
@State private var selectedLog: OSLogEntryLog?
@State private var presentingErrorDetails: Bool = false
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
let dateFormatStyle = Date.FormatStyle()
.year(.twoDigits)
.month(.defaultDigits)
.day(.defaultDigits)
private let dateFormatStyle = Date.FormatStyle()
.hour(.twoDigits(amPM: .omitted))
.minute()
.second()
@ -28,23 +27,41 @@ struct AppLog: View {
Table(logs, selection: $selection, sortOrder: $sortOrder) {
if idiom != .phone {
TableColumn("Date", value: \.date) { value in
TableColumn("Time", value: \.date) { value in
Text(value.date.formatted(dateFormatStyle))
}
.width(min: 150, max: 200)
.width(min: 100, max: 125)
TableColumn("Category", value: \.category)
.width(min: 100, max: 125)
TableColumn("Level") { value in
Text(value.level.description)
}
.width(min: 50, max: 100)
}
TableColumn("Message", value: \.composedMessage)
.width(ideal: 200, max: .infinity)
}
.onChange(of: sortOrder) { _, sortOrder in
logs.sort(using: sortOrder)
withAnimation {
logs.sort(using: sortOrder)
}
}
.onChange(of: selection) { newSelection in
presentingErrorDetails = true
let log = logs.first {
$0.id == newSelection
}
selectedLog = log
}
.sheet(item: $selectedLog) { log in
LogDetail(log: log)
.padding()
}
.task {
logs = await fetchLogs()
}
.navigationTitle("Debug Logs")
.navigationBarTitle("Debug Logs", displayMode: .inline)
}
}

View file

@ -432,7 +432,7 @@ struct Settings: View {
Label {
Text("Debug Logs")
} icon: {
Image(systemName: "building.columns")
Image(systemName: "ladybug")
}
}
.tag(SettingsSidebar.appLog)