Skip to content

dfabulich/skip-oslogstore

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SkipOSLogStore

This module provides a compatibility API corresponding to Apple's OSLogStore API, allowing app developers to read the OSLog messages from their own app.

On iOS, SkipOSLogStore simply re-exports OSLog. On Android, SkipOSLogStore executes logcat directly on the device, and parses the logs using protobuf-javalite.

Usage

Using OSLogStore API

import SkipOSLogStore

func loadEntries() -> [OSLogEntryLog] throws {
    let store = try OSLogStore(scope: .currentProcessIdentifier)
    return try Array(store.getEntries().compactMap { $0 as? OSLogEntryLog })
}

for entry in loadEntries() {
    print(entry.date)
    print(entry.level) // OSLogEntryLog.Level
    print(entry.subsystem)
    print(entry.category)
    print(entry.composedMessage)
    #if os(Android)
    print(entry.androidLevel) // AndroidLogLevel
    #endif
}

This returns log entries from the current process. (That's the only supported way to use it, on iOS with Apple's implementation and on Android with SkipOSLogStore.)

It can be quite slow, especially on iOS, so it's best to run it off the main thread, which can be a bit tricky, because OSLogEntryLog is not declared Sendable.

import SkipOSLogStore

extension OSLogEntryLog: @retroactive @unchecked Sendable {}
extension OSLogEntryLog.Level: @retroactive @unchecked Sendable {}

func loadEntries() -> [OSLogEntryLog] async throws {
    try await Task.detached(priority: .userInitiated) { @concurrent
        let store = try OSLogStore(scope: .currentProcessIdentifier)
        return try Array(store.getEntries().compactMap { $0 as? OSLogEntryLog })
    }.value
}

Filtering log entries: Use SkipOSLogStore.getEntries()

For your convenience, SkipOSLogStore provides:

public struct SkipOSLogStore {
    public static func getEntries(
        reversed: Bool = true,
        after: Date? = nil,
        minimumLevel: OSLogEntryLog.Level? = .notice,
        inSubsystem: String? = nil,
        inCategory: String? = nil
    ) async throws -> [SkipOSLogStoreEntry] { /* ... */ }
}

public struct SkipOSLogStoreEntry: Sendable {
    private let entry: OSLogEntryLog
    public var date: Date { entry.date }
    public var level: OSLogEntryLog.Level { entry.level }
    public var category: String { entry.category }
    public var subsystem: String { entry.subsystem }
    public var composedMessage: String { entry.composedMessage }
    #if os(Android)
    public var androidLevel: AndroidLogLevel? { entry.androidLevel }
    #endif

    init(entry: OSLogEntryLog) {
        self.entry = entry
    }
}

Use it like this:

try await SkipOSLogStore.getEntries(
    reversed: true,
    after: Date.now.addingTimeInterval(TimeInterval(-5 * 60)),
    minimumLevel: .error,
    inCategory: "MyCategory"
)

The OSLogStore getEntries(with:at:matching:) function is supposed to support a bunch of sorting/filtering features:

  • Reverse chronological sorting
  • Returning log entries after a certain date
  • Filtering with an NSPredicate

… but none of that works, either in Apple's implementation on iOS or in SkipOSLogStore. getEntries() always just returns all of the log entries for the current process; we have to sort/filter them in the client, which is what SkipOSLogStore.getEntries(reversed:after:minimumLevel:inCategory:) does for you.

Building

This project is a Swift Package Manager module that uses the Skip plugin to build the package for both iOS and Android.

Testing

The module can be tested using the standard swift test command or by running the test target for the macOS destination in Xcode, which will run the Swift tests as well as the transpiled Kotlin JUnit tests in the Robolectric Android simulation environment.

Parity testing can be performed with skip test, which will output a table of the test results for both platforms.

License

This software is licensed under the Mozilla Public License 2.0.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages