ios – OSLogStore func `getEntries(with:, at:, matching: predicate)` fails for “messageType IN %@” predicate sorts

ios – OSLogStore func `getEntries(with:, at:, matching: predicate)` fails for “messageType IN %@” predicate sorts


For some fields aside from messageType “IN” situation works tremendous.
Additionally .reverse choice doesn’t appear to make any distinction at the least on iOS.
Right here is fast pattern to verify:

public extension Logger {
    static let appSubsystem = Bundle.most important.bundleIdentifier!
    static func fetch(since date: Date) async throws -> [String] {
        let retailer = strive OSLogStore(scope: .currentProcessIdentifier)
        let place = retailer.place(date: date)
        
        // This does NOT work.
        // let predicate = NSPredicate(format: "(subsystem == %@) && (messageType IN %@)", Logger.appSubsystem, ["error", "fault"])
        // This, nonetheless, works.
        let predicate = NSPredicate(format: "(subsystem IN %@) && (messageType == %@)", [Logger.appSubsystem], "error")
        
        let entries = strive retailer.getEntries(/* with: [.reverse], */ at: place,
                                           matching: predicate)
        var logs: [String] = []
        for entry in entries {
            strive Job.checkCancellation()
            if let log = entry as? OSLogEntryLog {
                logs.append("""
          (entry.date):(log.subsystem):
          (log.class):(log.stage): 
          (entry.composedMessage)n
          """)
            } else {
                logs.append("(entry.date): (entry.composedMessage)n")
            }
        }
        
        if logs.isEmpty { logs = ["Nothing found"] }
        return logs
    }
}

// This extension  is for pattern functions solely
extension OSLogEntryLog.Degree: @retroactive CustomStringConvertible {
    public var description: String {
        change self {
        case .undefined: "undefined"
        case .debug: "debug"
        case .information: "information"
        case .discover: "discover"
        case .error: "error"
        case .fault: "fault"
        @unknown default: "default"
        }
    }
}

extension OSLogEntryLog.Degree: @retroactive Identifiable {
    public var id: Int {
        rawValue
    }
}

Right here is small SwiftUI display screen to help in reproducing the problem

import SwiftUI
import OSLog

struct LogView: View {
    @State personal var textual content = "Loading..."
    @State personal var process: Job<(), Error>?
    @State personal var isLoading = false
    @State personal var selectedLogLevel: OSLogEntryLog.Degree = .undefined
    personal let logLevels: [OSLogEntryLog.Level] = [.undefined, .debug, .info, .notice, .error, .fault]
    let logger = Logger(subsystem: Logger.appSubsystem, class: "most important")
    
    var physique: some View {
        VStack {
            HStack {
                Button(isLoading ? "Cancel" : "Refresh") {
                    if isLoading {
                        process?.cancel()
                    } else {
                        process = Job {
                            textual content = await fetchLogs()
                            isLoading = false
                        }
                    }
                }
                ProgressView()
                    .opacity(isLoading ? 1 : 0)
                Picker(choice: $selectedLogLevel, label: Textual content("Select Log Degree")) {
                    ForEach(logLevels) { logLevel in
                        Textual content(logLevel.description)
                            .tag(logLevel)
                    }
                }
                Button("Log") {
                    logMessage(selectedLogLevel: selectedLogLevel)
                }
            }
            
            ScrollView {
                Textual content(textual content)
                    .textSelection(.enabled)
                    .fontDesign(.monospaced)
                    .padding()
            }
        }
        .onAppear {
            isLoading = true
            process = Job {
                textual content = await fetchLogs()
                isLoading = false
            }
        }
    }
}

personal extension LogView {
    @MainActor
    func fetchLogs() async -> String {
        let calendar = Calendar.present
        guard let hourAgo = calendar.date(byAdding: .hour,
                                          worth: -1, to: Date.now) else {
            return "Invalid calendar"
        }
        
        do {
            let logs = strive await Logger.fetch(since: hourAgo)
            return logs.joined()
        } catch {
            return error.localizedDescription
        }
    }
    
    func logMessage(selectedLogLevel: OSLogEntryLog.Degree) {
        change(selectedLogLevel) {
        case .undefined:
            logger.log("Default log message")
        case .debug:
            logger.debug("Debug log message")
        case .information:
            logger.information("Data log message")
            //                case .warning:
            //                    logger.warning("Warning log message")
        case .discover:
            logger.discover("Discover log message")
        case .error:
            logger.error("Error log message")
        case .fault:
            logger.fault("Fault log message")
            
        @unknown default:
            logger.log("Default log message")
        }
    }
}

author avatar
roosho Senior Engineer (Technical Services)
I am Rakib Raihan RooSho, Jack of all IT Trades. You got it right. Good for nothing. I try a lot of things and fail more than that. That's how I learn. Whenever I succeed, I note that in my cookbook. Eventually, that became my blog. 
rooshohttps://www.roosho.com
I am Rakib Raihan RooSho, Jack of all IT Trades. You got it right. Good for nothing. I try a lot of things and fail more than that. That's how I learn. Whenever I succeed, I note that in my cookbook. Eventually, that became my blog. 

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here


Latest Articles

author avatar
roosho Senior Engineer (Technical Services)
I am Rakib Raihan RooSho, Jack of all IT Trades. You got it right. Good for nothing. I try a lot of things and fail more than that. That's how I learn. Whenever I succeed, I note that in my cookbook. Eventually, that became my blog.