{"id":34387,"date":"2021-12-10T14:36:32","date_gmt":"2021-12-10T19:36:32","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=34387"},"modified":"2023-12-06T14:23:11","modified_gmt":"2023-12-06T19:23:11","slug":"oslogstore-on-monterey","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2021\/12\/10\/oslogstore-on-monterey\/","title":{"rendered":"OSLogStore on Monterey"},"content":{"rendered":"<p><a href=\"https:\/\/developer.apple.com\/forums\/thread\/650843?answerId=668567022#668567022\">Quinn the Eskimo<\/a>:<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/forums\/thread\/650843?answerId=668567022#668567022\"><p>So, let&rsquo;s start with some history:<\/p><ul><li><p> macOS programs have been able to read log messages since the introduction of <code>OSLogStore<\/code> on macOS 10.15.<\/p><\/li><li><p> This API is not available on iOS-based platforms.<\/p><\/li><li><p> In iOS 14 beta we added the OSLog framework to the iOS SDK, along with a new initialiser to <code>OSLogStore<\/code> that allowed iOS apps to read their own log messages.<\/p><\/li><li><p> Unfortunately this feature didn&rsquo;t work properly )-: and so it was removed very late in the iOS 14 beta cycle.<\/p><\/li><li><p> It&rsquo;s now several months later and the feature has not returned (up to and including iOS 14.5b5).<\/p><\/li><\/ul><p>I have no concrete info to share about when this feature will return; in fact, I can&rsquo;t even confirm that it <em>will<\/em> return.  What I can say is that the OSLog team are well aware of the demand for this feature from third-party developers.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/oslog\/oslogstore\/3366102-local\">Apple<\/a>:<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/documentation\/oslog\/oslogstore\/3366102-local\">\n<p>Gaining access to the local unified logging system requires permission from the system. The caller must be run by an admin account and have the <code>com.apple.logging.local-store<\/code> entitlement.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/developer.apple.com\/forums\/thread\/666679\">Quinn the Eskimo<\/a>:<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/forums\/thread\/666679\"><p>This is good news \/ bad news story:<\/p><ul><li><p>The bad news is that there&rsquo;s no way for a third-party developer to get the <code>com.apple.logging.local-store<\/code> entitlement.<\/p><\/li><li><p> The good news is that it&rsquo;s not necessary: As long as you&rsquo;re running as an admin user, you don&rsquo;t need the entitlement.<\/p><\/li><li><p> The bad news is that this won&rsquo;t work from within the App Sandox.  AFAICT there&rsquo;s no way for a third-party sandboxed app to access the log store.<\/p><\/li><\/ul><\/blockquote>\n\n<p><a href=\"https:\/\/steipete.com\/posts\/logging-in-swift\/\">Peter Steinberger<\/a>:<\/p>\n<blockquote cite=\"https:\/\/steipete.com\/posts\/logging-in-swift\/\"><p>As of iOS 15 and macOS Monterey, <code>OSLogStore<\/code> works just as expected. No entitlements or hacks needed. It works in the Simulator, on device, on macOS and macOS Catalyst. <a href=\"https:\/\/github.com\/steipete\/OSLogTest\">Try out the OSLogTest project here<\/a>.<\/p><\/blockquote>\n\n<p>The <a href=\"https:\/\/developer.apple.com\/documentation\/oslog\/oslogstore\/3366102-local\"><code>local()<\/code><\/a> log store and <a href=\"https:\/\/developer.apple.com\/documentation\/oslog\/oslogstore\/scope\/system\"><code>.system<\/code><\/a> scope still don&rsquo;t work in the sandbox. You&rsquo;ll just get an error like:<\/p>\n<blockquote><p>Error Domain=OSLogErrorDomain Code=10 \"Connection to logd failed\" UserInfo={NSLocalizedDescription=Connection to logd failed, _OSLogErrorInternalCode=15}<\/p><\/blockquote>\n\n<p>From a sandboxed app, you can only use the <a href=\"https:\/\/developer.apple.com\/documentation\/oslog\/oslogstore\/scope\/currentprocessidentifier\"><code>.currentProcessIdentifier<\/code><\/a> scope. Not having access to the entire system log does make some sense for privacy reasons, but it really reduces the usefulness of <code>OSLogStore<\/code>:<\/p>\n<ul>\n<li><p>You can&rsquo;t read log entries from other apps and system processes, which might relate to your app, for example if the two are interoperating.<\/p><\/li>\n<li><p>You can&rsquo;t read log entries from your app&rsquo;s own helper processes.<\/p><\/li>\n<li><p>You can&rsquo;t even read log entries from a previous instance of your own app. So, if you detect that your app crashed the last time it ran, you can&rsquo;t look up information in the log to try to figure out why. The pid has changed, so it&rsquo;s already too late.<\/p><\/li>\n<\/ul>\n\n<p>So, <code>OSLogStore<\/code> offers a nicer API than <code>\/usr\/bin\/log<\/code>, but it is still very limited. In practice, I find that I still need to implement my own log persistence, which is too bad because in theory <code>os_log<\/code> has already solved hard problems like:<\/p>\n<ul>\n<li><p>Concurrency<\/p><\/li>\n<li><p>Performance<\/p><\/li>\n<li><p>Automatic expiration of older or less important log entries (rolling)<\/p><\/li>\n<li><p>Storage of individual fields (not just a giant blob of plain text)<\/p><\/li>\n<li><p>A portable archive format and tooling to go with it<\/p><\/li>\n<\/ul>\n\n<p>And, since <code>os_log<\/code> doesn&rsquo;t have a pluggable backend, it needs to be isolated behind another layer in your app if you ever want to be able to access your own logs. Apple even has an open-source project for doing this.<\/p>\n\n<p><a href=\"https:\/\/github.com\/apple\/swift-log\">SwiftLog<\/a> (via <a href=\"https:\/\/nshipster.com\/swift-log\/\">Mattt Thompson<\/a>):<\/p>\n<blockquote cite=\"https:\/\/github.com\/apple\/swift-log\"><p>This package only provides the logging API itself and therefore <code>SwiftLog<\/code> is a &lsquo;logging API package&rsquo;. <code>SwiftLog<\/code> (using <code>LoggingSystem.bootstrap<\/code>) can be configured to choose any compatible logging backend implementation. This way packages can adopt the API and the <em>application<\/em> can choose any compatible logging backend implementation without requiring any changes from any of the libraries.<\/p><\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2021\/11\/02\/dangerous-nslog-calls-in-swift\/\">Dangerous NSLog() Calls in Swift<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2020\/09\/15\/ios-14-shipping-tomorrow\/\">iOS 14 Shipping Tomorrow, Xcode 12 GM<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2020\/06\/26\/console-the-vital-tool-that-apple-abandoned\/\">Console, the Vital Tool That Apple Abandoned<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2019\/03\/06\/problems-with-os_log\/\">Problems With os_log<\/a><\/li>\n<\/ul>\n\n<p id=\"oslogstore-on-monterey-update-2021-12-16\">Update (2021-12-16): <a href=\"https:\/\/twitter.com\/_saagarjha\/status\/1470401880547225605\">Saagar Jha<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/_saagarjha\/status\/1470401880547225605\">\n<p>It&rsquo;s kind of weird that NSLog really hasn&rsquo;t gotten a replacement at all for print debugging on Apple&rsquo;s platforms. It just packs in so many of the right choices for this use case that everyone (myself included) finds themselves reaching for it all the time. Even from Swift!<\/p>\n<p>[&#8230;]<\/p>\n<p>Nobody is going to pull in a third party library or write a wrapper around something just for a debugging session, so the alternatives are what, print(f) and os_log? I use the former a bunch and the latter occasionally, but they often just aren&rsquo;t what I need&#8230;<\/p>\n<p>os_log is&#8230;cool, but cumbersome. You have to import a thing, then set up a logger, then you give it a static string, plus a category or whatever. And after all that work, it doesn&rsquo;t even show up in Xcode! And in Console it&rsquo;s redacted or at a low level so you don&rsquo;t see it&#8230;<\/p>\n<\/blockquote>\n\n<p>See also: <a href=\"https:\/\/saagarjha.com\/blog\/2019\/09\/29\/making-os-log-public-on-macos-catalina\/\">Making os_log Public on macOS Catalina<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Quinn the Eskimo: So, let&rsquo;s start with some history: macOS programs have been able to read log messages since the introduction of OSLogStore on macOS 10.15. This API is not available on iOS-based platforms. In iOS 14 beta we added the OSLog framework to the iOS SDK, along with a new initialiser to OSLogStore that [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2021-12-10T19:36:35Z","apple_news_api_id":"3ce1cbee-4a98-40d7-83ef-bbdf3564034e","apple_news_api_modified_at":"2023-12-06T19:23:14Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAg==","apple_news_api_share_url":"https:\/\/apple.news\/APOHL7kqYQNeD77vfNWQDTg","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[2518,31,1837,2078,30,2077,74,1504,71,53,901],"class_list":["post-34387","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-entitlements","tag-ios","tag-ios-14","tag-ios-15","tag-mac","tag-macos-12","tag-opensource","tag-os_log","tag-programming","tag-sandboxing","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/34387","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=34387"}],"version-history":[{"count":3,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/34387\/revisions"}],"predecessor-version":[{"id":34448,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/34387\/revisions\/34448"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=34387"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=34387"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=34387"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}