How to collect logs from OSLog with swift?

Hi, I am trying to collect OSLog's logs using the OSLog framework, but I am not being able to access them. I've seen some examples that use something like this:

Code Block swift
import OSLog
let myLogStore =try OSLogStore(scope: .currentProcessIdentifier)


but when I try to run it throws:

Code Block bash
main.swift:5:20: error: argument labels '(scope:)' do not match any available overloads
main.swift:5:20: note: overloads for 'OSLogStore' exist with these partially matching parameter lists: (URL: URL), (url: URL)

I couldn't find any solution on google so far...

I am running it on a Mac OS X's 10.15 with Darwin Kernel Version 19 and Swift version 5.2.2

Any guidance on how to collect logs by using this framework will be highly appreciated

Post not yet marked as solved Up vote post of nmkoremblum Down vote post of nmkoremblum
6.2k views

Replies

The droid you’re looking for is:

Code Block
let store = try OSLogStore.local()


This connects you to the +[OSLogStore localStoreAndReturnError:] Objective-C method.

ps Log store scopes are part of the almost-but-not-quite-there-yet iOS support. See this post for the full backstory.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Hi Eskimo! Thanks for answering.

I was able to execute that command but every step I do I get lost again.

e.g:
Code Block swift
vagrants-iMac:~ root# swift
Welcome to Apple Swift version 5.2.2 (swiftlang-1103.0.32.6 clang-1103.0.32.51).
Type :help for assistance.
1> import OSLog
2> let store = try OSLogStore.local()
store: OSLogStore = {
baseNSObject@0 = {
isa = OSLogStore
}
_source = {
NSObject = {
isa = OSLogEventSource
}
_fileRefs = 89 elements
_lcr =
_lesm =
_oldestTimeRef =
_tsdb =
}
}
3> let myDate = Date().addingTimeInterval(-3600) /* time in secs (one hour) */
myDate: Date = {}
4> let oneHourAgo = store.position(date: myDate)
oneHourAgo: OSLogPosition = <uninitialized>
5> let myEntries = store.getEntries(at: oneHourAgo)
myEntries: AnySequence<OSLogEntry> = {
_box = <extracting data from value failed>
}
error: Couldn't lookup symbols:
(extension in OSLog):__C.OSLogStore.getEntries(with: __C.OSLogEnumeratorOptions, at: Swift.Optional<__C.OSLogPosition>, matching: Swift.Optional<__C.NSPredicate>) throws -> Swift.AnySequence<__C.OSLogEntry>
(extension in OSLog):__C.OSLogStore.getEntries(with: __C.OSLogEnumeratorOptions, at: Swift.Optional<__C.OSLogPosition>, matching: Swift.Optional<__C.NSPredicate>) throws -> Swift.AnySequence<__C.OSLogEntry>


Is there any developer guide to get log entries? I couldn't find it...

In any case, if you can provide us with a very simple code to get a log it would be a great starting point for me and the rest of the community since I couldn't find any working example, and we all will be very grateful :) thanks in advance for any guidance you can provide me ^^

In any case, if you can provide us with a very simple code to get a
log it would be a great starting point

The following code, when pasted into a new command-line tool project, will print the last 60 seconds worth of log entries:

Code Block
import OSLog
func main() throws {
let store = try OSLogStore.local()
let oneMinuteAgo = store.position(timeIntervalSinceEnd: -60.0)
let entries = try store.getEntries(with: [], at: oneMinuteAgo, matching: nil)
for e in entries {
print(e.date, e.composedMessage)
}
}
try! main()


I tested this on macOS 11.2.3 with Xcode 12.4.

IMPORTANT This assumes you’re an admin user. Non-admin users don’t have access to the log store.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
  • Hi, sorry to interrupt, but for me - this doesn't run even on a Mac (Ventura 13.6.6 + Xcode 14.0 (14A309)) It runs - but yields no log entries (empty 'entries').

    I also tried an Obj-C form of this - with same results. I choose to "run as root" in the debug scheme of Xcode. It's a "command line tool" simple project, signed "Mac Development".

Add a Comment
Hi Eskimo, your help is much appreciated :)

I tried running the example code but I get segmentation faults and I am not sure why or how to solve it. Just copy-pasted it into a plain text file named "example.swift" and this is the command line output when I try to run it:

Code Block bash
vagrants-iMac:~ root# swift example.swift
Stack dump:
0. Program arguments: /Library/Developer/CommandLineTools/usr/bin/swift -frontend -interpret example.swift -enable-objc-interop -stack-check -sdk /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -color-diagnostics -module-name example
1. Apple Swift version 5.2.2 (swiftlang-1103.0.32.6 clang-1103.0.32.51)
2. While running user code "example.swift"
0 swift 0x0000000106de54ea PrintStackTraceSignalHandler(void*) + 42
1 swift 0x0000000106de4cc0 SignalHandler(int) + 352
2 libsystem_platform.dylib 0x00007fff66536b1d _sigtramp + 29
3 libsystem_platform.dylib 0x00000001085c3000 _sigtramp + 2718483712
4 libsystem_platform.dylib 0x000000010ad8e013 _sigtramp + 2760209683
5 swift 0x0000000102b6848a llvm::MCJIT::runFunction(llvm::Function*, llvm::ArrayRef<llvm::GenericValue>) + 458
6 swift 0x0000000102b6f4fb llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, char const* const*) + 2011
7 swift 0x0000000102b445ba performCompileStepsPostSILGen(swift::CompilerInstance&, swift::CompilerInvocation&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> >, bool, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, swift::PrimarySpecificPaths const&, bool, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 14362
8 swift 0x0000000102b38f75 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 55813
9 swift 0x0000000102aaef53 main + 1283
10 libdyld.dylib 0x00007fff66331c49 start + 1
Segmentation fault: 11


Do you have any clue on what can be causing trouble?

thanks in advance for your valuable help :)

I get segmentation faults

That’s not the code failing, but rather the Swift compiler failing as it tries to compile the code. I’ve no idea why it would do that; I tried the same test here (again, macOS 11.2.3 with Xcode 12.4) and it didn’t happen.

What happens if you create an Xcode command-line tool project and put the code in there?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Yes its working but only for ios 15. does any one have solution to fetch that log for iOS 10, 11, 12, 13 ,14 ?

Thanks in advance

Yes its working but only for iOS 15.

I’m not 100% clear what you mean by “its” here, but I’m presuming that you’re talking about reading log entries using OSLogStore. If so, it’s only expected to work an iOS 15 beta. There’s no supported way to programmatically read system log entries on older versions of iOS.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • Now that OSLogStore store works on iOS what is the recommended way of getting the logs off the device? My current approach is iterating over earth log and grabbing the information I need. I can then turn this into a CSV file if need be. However is there another approach I should be taking? Is there a Log file with the log entries I can just grab?

Add a Comment

Is there a Log file with the log entries I can just grab?

No. The native log format is not a log file but rather a .logarchive package. Run log collect on your Mac to generate an example. And the OSLog framework does not give you access to such a package, nor does it let you create one (although you can read one using +[OSLogStore storeWithURL:error:], but that’s not terribly useful on iOS).

what is the recommended way of getting the logs off the device?

I don’t think we have a recommended way. The folks who’ve been asking for this feature generally have an existing log infrastructure and they want to integrate system log entries with that. If you don’t have existing infrastructure, you’ll have to create that first, and how you do that is very much up to you.

If I were in your shoes I’d look at the various log styles supported by the --style argument in the log show command on the Mac. Using one of those formats seems like a good way to foster commonality between your in-the-field logging and your day-to-day debug logging. For more info on this, see the log man page.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"