OSLog is a unified logging system for the reading of historical data.

OSLog Documentation

Pinned Posts

Posts under OSLog tag

63 Posts
Sort by:
Post marked as solved
5 Replies
2.9k Views
Using the latest Xcode 15 Beta 7: In an existing project, I can't get structured logging to work as described. For new projects, it works fine but I must have some setting or value in an existing project that prevents it from working. My simple text case: In an existing project file: @main struct LuarasBooksApp: App { var body: some Scene { WindowGroup { Text("hi") .onAppear { Logger(subsystem: "test", category: "test").error("help me") } } } } The debug console looks like this: That same code in a new project for the same Xcode 15 Beta 7 looks correct: Are there any settings, variables, etc... related to logging or the console that might cause this difference? In the existing project it makes no difference to toggle the various metadata options on and off. Thanks!
Posted
by
Post not yet marked as solved
2 Replies
1.2k Views
My problem is similar to this post but switching to an iOS 17 simulator does not fix the issue. As far as I know there should be no OS_ACTIVITY_DT_MODE set anywhere in my project but I'm not sure exactly where to check. I've tried in Beta 6 and 7 so far and I've set all of my minimums to iOS 17.
Posted
by
Post not yet marked as solved
3 Replies
1.2k Views
I have an iOS application which is developed with C++, and my physical iPhone is connected to my Mac. While running the app via Xcode, I can easily view the printouts within the Xcode console. However, upon manually executing the app on the iPhone and utilizing the command "idevicesyslog -d -p myAppName" on my Mac the terminal, I notice that only specific logs generated by the .mm files are visible. And I'm unable to access the remaining traces, macros, and other details from the .h or .cpp files. Is there a method to ensure that all the logs I observe in the Xcode console are also displayed in "idevicesyslog"? Alternatively, are there any technique to show all the printout from .cpp and .h files.
Posted
by
Post marked as solved
1 Replies
1.5k Views
Hi! I am getting all debug output in text only format, without structure or color. I only noticed now after watching the respective WWDC session in Xcode 15 beta 8, but I am pretty sure this was the case in the previous betas as well. Is the new structured debug console activated by some setting I am overlooking?
Posted
by
Post not yet marked as solved
3 Replies
502 Views
When the number of log outputs over a certain amount, the structure log output is suspended. The os_log_debug code runs without error, but the Xcode console has no output. When use OS_ACTIVITY_DT_MODE=1 turnoff structure log, the output is normal. Does structure log in Xcode 15 beta 6 has bugs, or the structure log has upper limit in Xcode console output ?
Posted
by
Post not yet marked as solved
1 Replies
570 Views
Hello folks, I would like to incrementally retrieve logs of my iOS App from the Unified Logging System using OSLogStore. First I initialize the store store = try OSLogStore(scope: .currentProcessIdentifier) Second I set a position from which I want the logs using either : position = store.position(timeIntervalSinceLatestBoot: 0) // to get the logs from the launch of the App position = store.position(date: Date().addingTimeInterval(-10)) // to get the logs of the last 10 seconds Third I get the entries in the store from the position store.getEntries(at: position) Issue Whatever the position I set using from OSLogStore: position(timeIntervalSinceLatestBoot:) position(date:) position(timeIntervalSinceEnd:) All the logs are retrieved. I cannot get only the subset requested by the timeframe I specified Sample A sample LogScreen that has 2 buttons is attached to the post 1 to fetch logs since the last time they have been fetched 1 to add a log The code has been simplified to ease the comprehension of the case, please be indulgent to the shortcuts that have been taken. LogScreen.swift References https://developer.apple.com/documentation/oslog/oslogstore https://developer.apple.com/forums/thread/705868 https://developer.apple.com/videos/play/wwdc2023/10226/ Environment XCode 15b7 iPhone 14 Pro / iOS 17
Posted
by
Post not yet marked as solved
4 Replies
491 Views
Howdy all, I'm in the process of eliminating some compiler warnings in a legacy project, and have come across a compiler warning for the usage of extern void DebugStr(ConstStr255Param debuggerMsg), defined in MacTypes.h as part of CarbonCore-769-1. I've looked through Apple's documentation for Cocoa and the MacOSX13.1 SDK but haven't found any leads on what I could/should replace it with. Can anyone point me in the right direction? Thanks!!
Posted
by
Post not yet marked as solved
2 Replies
592 Views
I'm trying to create a macro that adds the file and line to a string that I use with OSLog. However, I only get warnings that either the String is not in the format of OSLogMessage or not an interpolated string. The Macro looks like this at the moment: public struct LocMacro: ExpressionMacro { public static func expansion( of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext ) -> ExprSyntax { guard let argument = node.argumentList.first?.expression.as(StringLiteralExprSyntax.self)?.segments else { fatalError("compiler bug: the macro does not have any StringLiteralExprSyntax arguments.") } guard let file = context.location(of: node)?.file.as(StringLiteralExprSyntax.self)?.segments, let line = context.location(of: node)?.line.as(IntegerLiteralExprSyntax.self) else { fatalError("compiler bug: the macro is unable to retrieve file and line numbers") } return "\"\(argument) - \(file):\(line)\"" } } and here the exposed macro: @freestanding(expression) public macro loc(_ text: String) -> String = #externalMacro(module: "LxoMacrosMacros", type: "LocMacro") I want to use it like this: import LxoMacros import OSLog let logger = Logger() let someNumber = 17 logger.debug(#loc("Working with some number \(someNumber)")) which should expand to: logger.debug("Working with some number \(someNumber) - MyFile.swift:8") Is there a way to change the macro so that it returns the correct type? When expending the macro it does show the right string, which works with print() and so on, but assuming since the Logger uses some sort of compiler check as well, it doesn't seem to work together as expected.
Posted
by
Post not yet marked as solved
7 Replies
1k Views
Since this api requires &__dso_handle instead of the standard file/line/func, I had to modify my entire log system to pass this down from the macro call sites. I have many callbacks that typically just forward data from other C++ libraries that never supply a dso_handle. so it's great how this logging system breaks most logger systems and doesn't have a warning level to match fault/error. I have the forwarded threadName, timestamp, etc and no where to store that in os_log. syslog was more powerful and clear than os_log, but I'm sure it's now too late to head down a more reasonable path.. So I pass the &__dso_handle all the way to the log command and hand it into the macro #define my_os_log_with_type(dso, log, type, format, ...) __extension__({ \ os_log_t _log_tmp = (log); \ os_log_type_t _type_tmp = (type); \ if (os_log_type_enabled(_log_tmp, _type_tmp)) { \ OS_LOG_CALL_WITH_FORMAT(_os_log_impl, \ ((void*)dso, _log_tmp, _type_tmp), format, ##__VA_ARGS__); \ } \ }) Logger.mm // This doesn't work, logging the dso from the callsite. No file/line. my_os_log_with_type(entry.dso, os_log_create( "com.foo", entry.tag), logLevel(entry.level)), "%{public}s", text ); // This does work, but who wants to jump to the forwarding log implementation? os_log_with_type(os_log_create( "com.foo", entry.tag), logLevel(entry.level)), "%{public}s", text );
Posted
by
Post not yet marked as solved
5 Replies
802 Views
I need to log to OSLog and into a file in parallel (due to OSLogStore not being able to provide old logs (FB13191608)). In Objective-C I can accomplish this with a macro using __FILE__ and __LINE__ in the macro implementation which still reference the position in the original code. I tried to create a Swift macro to make this work from Swift. However, log() takes the file and line number of the macro definition file instead of the position in the calling code. So when I click on the metadata link, I'm taken to the macro instead of the calling location. Is there any solution to that? #file and #line are correctly set in the macro but there’s no way to specify file and line number to the log() function (FB13204310).
Posted
by
Post not yet marked as solved
5 Replies
1.2k Views
This is the opposite of https://developer.apple.com/forums/thread/726354 really, and I've read both of the Recording Private Data in the System Log and Your Friend, the System Log threads, but I still can't solve my problem. The structured log always seems to redact private values to If I set OS_ACTIVITY_DT_MODE=1 in my environment (it's not set anymore by Xcode, at least not for my projects) then the logs are unredacted as I would expect, but structured logging is turned off. Is there a way to have the unredacted strings in the log when the app is running under Xcode and still get the nice structured log output? I don't want the unredacted logs when the app runs normally, but I'd like them under Xcode. At the moment, I'm having to explicitly make everything public, which defeats the whole purpose of the system.
Posted
by
Post marked as solved
8 Replies
918 Views
Currently I have a setup which duplicates the stderr STDERR_FILENO pipe into a separate one. Then by setting up a readabilityHandler (on the new Pipe) I can capture the logged data and either store it inside a File, adjust/modify the data etc. Since iOS 17 this is not possible anymore (previous versions worked iOS 16)? I cannot find any documentation on why or what changed on the os_log side. private func setupPipes() { inputPipe.fileHandleForReading.readabilityHandler = { [weak self] handler in guard let strongSelf = self else { return } let data = handler.availableData strongSelf.queue.async(flags: .barrier) { guard let fileHandle = try? FileHandle(forWritingTo: strongSelf.filePath) else { return } fileHandle.seekToEndOfFile() fileHandle.write(data) try? fileHandle.close() } strongSelf.outputPipe.fileHandleForWriting.write(data) } dup2(STDERR_FILENO, outputPipe.fileHandleForWriting.fileDescriptor) dup2(inputPipe.fileHandleForWriting.fileDescriptor, STDERR_FILENO) }
Posted
by
Post not yet marked as solved
3 Replies
717 Views
minimum is to create an os_log once in the parent, then, after fork, use an existing os_log instance or create a new one. Here's my reproduction sample. It looks like an OS bug, So what is the workaround till its solved and releases. #include <os/log.h> #include <stdio.h> #include <errno.h> #define USE_SWIFT_LOGGER 0 // set to 1 to use Logger() instead of os_log() #define USE_SHARED_LOG 0 // set to 1 to use a shared os_log instance instead of allocating one for each os_log() call #if USE_SWIFT_LOGGER // log messages using Swift's Logger class instead of calling os_log_... directly #include "forktest-Swift.h" #define LOG(msg) log_using_logger([NSString stringWithUTF8String:msg]) const char * logMethod = "Swift's Logger"; #elif USE_SHARED_LOG // use a shared os_log instance for all log messages static os_log_t log = os_log_create("com.ivanti.forktest", "foo"); #define LOG(msg) os_log_debug(log, msg) const char * logMethod = "shared log"; #else // create a new os_log instance for each log message #define LOG(msg) os_log_debug(os_log_create("com.ivanti.forktest", "foo"), msg) const char * logMethod = "new log instance for each message"; #endif static void forkTest() { int pid = fork(); if (pid < 0) { fprintf(stderr, "fork failed: %s\n", strerror(errno)); exit(1); } else if (pid == 0) { printf("in child process...\n"); LOG("in child process..."); printf("child process done\n"); } else { printf("child process pid: %d\n", pid); } } int main(int arc, const char ** argv) { printf("Log method: %s\n", logMethod); LOG("entering main..."); forkTest(); LOG("leaving main..."); return 0; }
Posted
by
Post not yet marked as solved
0 Replies
1k Views
I regularly talk to developers debugging hard-to-reproduce problems. I have some general advice on that topic. I’ve posted this to DevForums before, and also sent similar info to folks who’ve opened a DTS incident, but I figured I should write it down properly. If you have questions or comments, put them in a new thread here on DevForums. Tag it with Debugging so that I see it. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Using a Sysdiagnose Log to Debug a Hard-to-Reproduce Problem Some problems are hard to reproduce in your office. These usually fall into one of two categories: Environment specific — This is where some of your users can easily reproduce the problem, but you can’t reproduce it in your environment. Intermittent — In this case the problem could affect any user, but it’s hard to predict when a given user will see the problem. A key tool in debugging such problems is the sysdiagnose log. This post explains how to make this technology work for you. IMPORTANT A sysdiagnose log might contain private information. If you ask a user to send you a log, make sure they understand the privacy impact of that. If you want to see how Apple handles this, run the sysdiagnose command on a fresh Mac and read through it’s initial prompt. Sysdiagnose Logs All Apple platforms can generate sysdiagnose logs. For instructions on how to do this, see our Bug Reporting > Profiles and Logs page. The resulting log is a .tar.gz file. Unpacking that reveals a bunch of files. The most critical of these is system_logs.logarchive, which is a snapshot of the system log. For more information about the system log, including links to the documentation, see Your Friend the System Log. This log snapshot includes many thousands of log entries (I just took a log snapshot on my Mac and it had 22.8 million log entries!). That can be rather daunting. To avoid chasing your tail, it pays to do some preparation. Preparation The goal here is to create a set of instructions that you can give to your user to capture an actionable sysdiagnose log. That takes some preparation. To help orient yourself in the log, add log points to your code to highlight the problem. For example, if you’re trying to track down a keychain problem where SecItemCopyMatching intermittently fails with errSecMissingEntitlement ( -34018 ), add a log point like this: import os.log let log = Logger(subsystem: "com.example.waffle-varnish", category: "keychain") func … { let err = SecItemCopyMatching(…) log.log("SecItemCopyMatching failed, err: \(err)") } When you look through a log, find this specific failure by searching for SecItemCopyMatching failed, err: -34018. You might also add log points at the start and end of an operation, which helps establish a time range of interest. Log points like this have a very low overhead and it’s fine to leave them enabled in your released product. However, in some cases you might want to make more extensive changes, creating a debug build specifically to help investigate your problem. Think about how you’re going to get that debug build to the affected users. You might, for example, set up a special TestFlight group for folks who’ve encountered this issue. Go to Bug Reporting > Profiles and Logs and look for debug profiles that might help your investigation. For example, if you’re investigating a Network Extension issue, the VPN (Network Extension) debug profile will enable useful debug logging. Now craft your instructions for your user. Include things like: Your take on the privacy impact on this Instructions on how to get the necessary build of your product If there’s a debug profile, instructions on how to install that Instructions on how to trigger the sysdiagnose log And on how to send it to you IMPORTANT Make sure to stress how important it is that the user triggers the sysdiagnose immediately after seeing the problem. Finally, test your steps. Do an initial test in your office, to make sure that the log captures the info you need. Then do an end-to-end test with someone who’s about as technically savvy as your users, to make sure that your instructions make sense to Real People™. Prompting for a Sysdiagnose Log In some cases it might not be obvious to the user when to trigger a sysdiagnose log. Imagine you’re hunting the above-mentioned errSecMissingEntitlement error and it only crops up when your product is performing some task in the background. The user doesn’t see that failure, they’re not even running your app!, so they don’t know that action is required. A good option here is to add code to actively monitor for the failure and post a local notification requesting that the user trigger a sysdiagnose log. Continuing the above example, you might write code like this: func … { let err = SecItemCopyMatching(…) log.log("SecItemCopyMatching failed, err: \(err)") if err == errSecMissingEntitlement { … post a local notification … } } Obviously this is quite intrusive so, depending on the market for your product, you might not want to deploy this to all users. Perhaps you can restrict it to your internal testers, or your external beta testers, or a particularly savvy set of customers. Looking at the System Log Once you have your sysdiagnose log, unpack it and open the system log snapshot (system_logs.logarchive) in Console. The hardest part is knowing where to start. That’s why adding your own log entries, as discussed in Preparation, is so important. A good general process is: Search for log entries from your subsystem. An easy way to initiate that search is to paste the text subsystem:SSS, where SSS is your subsystem, into the Search field. Continuing the above example, find that log entry by pasting in subsystem:com.example.waffle-varnish. Identify the log entry that indicates the problem and select it. Then remove your search and work backwards through the log looking for system log entries related to your issue. The relevant log entries might not be within the time range shown by Console. Customise that by selecting values from the Showing popup in the pane divider. Once you have a rough idea of the timeframe involved, select Custom from that popup to focus on that range. If the log is showing stuff that’s not relevant to your problem, Console has some great facilities for filtering those out. For the details, choose Help > Console Help. Talk to Apple A key benefit of this approach is that, if your investigation suggests that this is a system bug, you can file a bug report and attach this sysdiagnose log to it. The setup described above is exactly the sort of info needed to analyse the bug. Likewise, if you decide to seek formal code-level support by opening a DTS tech support incident, your friendly neighbourhood DTS engineer will find that sysdiagnose log very handy.
Posted
by
Post not yet marked as solved
1 Replies
473 Views
Environment Context: iOS 17.0 Simulator Xcode 15.0 In the above environment, I'm noticing in Instruments that the OS subsystem com.apple.VectorKit is emitting os_signpost events at a rate of ~2.8 events/ms. This large amount of data logging seems to be triggering warnings of: 'Data stream: 1 log/signpost messages lost due to high rates' ...when trying to capture other system logging data. (In the attached screenshot, notice the warning sign icons right outside the selected time series.) This is preventing me from being able to successfully log my own signpost data and profile my application. As well, this subsystem's data is unnecessary for my purposes and distracting. I have tried to disable logging for this subsystem in the Simulator by running the following from the macOS host: % xcrun simctl spawn booted log config --subsystem com.apple.VectorKit --mode level:off ...and confirmed it with: % xcrun simctl spawn booted log config --subsystem com.apple.VectorKit --status Mode for 'com.apple.VectorKit' OFF PERSIST_OFF ...however, when running Instruments after the above output, this data does not actually get disabled. How can I disable this subsystem's logging? Feedback Assistant report: FB13292000
Posted
by
Post not yet marked as solved
3 Replies
454 Views
I use a macro to do logging: #define LOG(fmt, ...) NSLog((fmt), ##VA_ARGS); which means I can write code like: LOG(@"radius=%.1f", fRadius) Up until Xcode 15 the %.1f would be respected and display fRadius to one decimal place. But since Xcode 15 it seems to ignore that and just display all decimal places regardless. Anyone know why, and how to fix that?
Posted
by
Post marked as solved
4 Replies
624 Views
Lately, I've switched from NSLog to the new os_log. My problem is, whatever I try, I can't see the private values in my 13.6 (22G120). My test line is trivial os_log(OS_LOG_DEFAULT,"private shown: %@", [NSString stringWithFormat:@"OK"]); and it prints (both in Xcode and in Console) private shown: <private> I did install in Settings the appropriate profile (as found here, copied down, changed just my company info) — in vain, it did not help, not even after restarting my computer. For the record, the profile is shown below. Can anybody see what am I doing wrong and why it does not work? Thanks! <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>ConsentText</key> <dict> <key>default</key> <string>This will enable showing private strings and data in Unified Logs.</string> </dict> <key>PayloadContent</key> <array> <dict> <key>PayloadDisplayName</key> <string>ManagedClient logging</string> <key>PayloadEnabled</key> <true/> <key>PayloadIdentifier</key> <string>com.apple.system.logging.89AE58D8-0A4A-448B-8AE0-761DEE2D007F</string> <key>PayloadType</key> <string>com.apple.system.logging</string> <key>PayloadUUID</key> <string>89AE58D8-0A4A-448B-8AE0-761DEE2D007F</string> <key>PayloadVersion</key> <integer>1</integer> <key>System</key> <dict> <key>Enable-Private-Data</key> <true/> </dict> </dict> </array> <key>PayloadDescription</key> <string>Allows showing private log messages.</string> <key>PayloadDisplayName</key> <string>Allow Private Logs</string> <key>PayloadIdentifier</key> <string>cz.ocs.enable.private.logs</string> <key>PayloadOrganization</key> <string>OCSoftware</string> <key>PayloadRemovalDisallowed</key> <false/> <key>PayloadType</key> <string>Configuration</string> <key>PayloadUUID</key> <string>529DF49A-6CB3-4DE9-A29F-4C41EC88BFDD</string> <key>PayloadVersion</key> <integer>1</integer> </dict> </plist>
Posted
by
Post marked as solved
2 Replies
465 Views
When exporting OSLog entries from OSLogStore, composedMessage doesn't seem to respect the given privacy marker. This feels like a bug to me, but it maybe a case of me holding it wrong. Here's an example: import UIKit import OSLog class ViewController: UIViewController { let logger = Logger(subsystem: "com.example.project", category: "ViewController") override func viewDidLoad() { super.viewDidLoad() logger.info("Top secret number \(42, privacy: .private)") do { let store = try OSLogStore(scope: .currentProcessIdentifier) let postion = store.position(timeIntervalSinceLatestBoot: 1) let logs = try store.getEntries(at: postion) .compactMap { $0 as? OSLogEntryLog } .filter { $0.subsystem == "com.example.project" } .map { $0.composedMessage } // Prints: // Logger: ["Top secret number 42"] print("Logger: \(logs)") } catch { print(error) } } } Is there a more appropriate way to format the text ready for sharing?
Posted
by
Post not yet marked as solved
3 Replies
432 Views
I have created an iOS .ipa file to run some tests, and all the test cases have os_log implemented for tracing. However, there is an issue; my tests take over 20 seconds to run, and the screen starts to dim. Consequently, the execution stops. Once I reactivate the screen, the tests resume. I added [UIApplication.sharedApplication setIdleTimerDisabled:YES]; to the code, but it doesn't resolve the problem. I've used os_log to trace all the test case results. I wonder if it's possible to display all the os_log messages from runTest on the app main screen as well. int main(int argc, char** argv) { //Separate thread to runTest, os_log implemented there std::thread thread_obj(runTests, argc, argv); int applicationReturn; @autoreleasepool { [UIApplication.sharedApplication setIdleTimerDisabled:YES]; applicationReturn = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } thread_obj.join(); [UIApplication.sharedApplication setIdleTimerDisabled:NO]; return applicationReturn; }
Posted
by
Post not yet marked as solved
6 Replies
1.3k Views
I'm finding that in Xcode 15, NSLog statements (from Objective-C, in this case) will sometimes appear in Xcode's Console and sometimes will not. This is making it difficult to debug using our existing logging, which for our REST API requests and responses has been working well for about ten years and is a tough thing to lose. Is there any way I can restore reliable handling of NSLog in Xcode 15's Console without having to rewrite all (over 200) of our uses of NSLog to use OSLog? Note: I am aware that Xcode 15's Console sometimes takes more than 30 seconds to start tracking app output, but it appears that in some cases the content of individual NSLog statements never will appear. (If this 30 second delay is news to anyone, it may be related to a spam of identical warnings that are okay which occur on launch of our app. I have suspected that Xcode 15 just gets a bit flustered with identical messages and gives up for a bit.) Thank you!
Posted
by