Logger on Xcode console

Overview:

  • I am logging some messages using Logger
  • I would like these messages to be printed on to Xcode without the timestamp and other details
  • I want only the message to be displayed

Questions:

  1. How can I display only the message on the Xcode console (see preferred output)?
  2. Is there a setting in Xcode to remove the timestamp prefix?
  3. Is there an alternate approach?

Note:

  • I need to use Logger because this app would be released, so print is not an option.

Example Code

import SwiftUI
import os
struct ContentView: View {
    
    let logger = Logger(subsystem: "MyApp", category: "MyCategory")
    
    var body: some View {
        Text("Hello, world!")
            .onAppear {
                logger.debug("content view displayed")
            }
    }
}

Actual Output:

2022-11-25 18:41:10.116408+0800 Demo[36175:5518724] [MyCategory] content view displayed

Preferred Output:

One of the following would be ideal:

content view displayed
Demo[36175:5518724] [MyCategory] content view displayed

My Failed Attempt

I event tried to use print in debug mode, but couldn't make it compile:

Following is my failed attempt:

import os

#if DEBUG
struct Logger {
    
    let subsystem: String
    let category: String
    
    func debug(_ message: String) {
        print(message)
    }
    
    //This will not help:
//    func debug(_ message: OSLogMessage) {
//        print(message)
//    }
}
#endif

Accepted Reply

For general advice on this subject, see Your Friend the System Log. The limitation mentioned there (r. 32863680) means you have to choose between using the system log and getting the exact output you want in the Xcode console pane. IMO it’s better to choose the system log, and use Console app to get your nice output, but there are differences in opinion.

Share and Enjoy

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

  • @eskimo Thanks a lot! well written article and I like the reference to friendship. Definitely the advantages to using Logger far outweigh the my small preferences. So I will stick with the logger. My wish list is Xcode some day provides a way to customise how these messages are being displayed (more around timestamp being wrapped). It is definitely a priority .... a nice to have. Definitely console app does a good job in the meantime. Thanks once again

  • @eskimo I am so thrilled Xcode 15 (beta) has this feature, so for users who want can turn on timestamp, viewing and filtering logs is awesome to Xcode 15. Thanks a lot filing the radar and for all the folks involved in the development of the feature. I love it!!

  • I couldn't get past the claims that the System log is "powerful" and "full-featured". I can show you 20+ year logging frameworks with far more power. The Apple Logging system is anemic at best.

Add a Comment

Replies

Non-sensitive logging (Public)

This doesn't work in my following case:

import SwiftUI
import os

struct ContentView: View {
    
    let logger = Logger(subsystem: "MyApp", category: "MyCategory")
    let itemName = "something non-sensitive"
    
    var body: some View {
        Text("Hello, world!")
            .onAppear {
                logger.debug("content view displayed")
                logger.debug("Item name = \(itemName, privacy: .public)")
            }
    }
}
Add a Comment

If you put the #if DEBUG ... #endif around the struct Logger { ... } you're telling the compiler to only include that code if the app is being built for DEBUG, not RELEASE, so it will fail if you try to build for RELEASE.

Regardless of how the app is going to be built if you're calling a function that function has to exist.

You simply need to move the #if DEBUG ... #endif to the bit that should only be printed when you're in DEBUG mode, i.e.:

struct Logger {
	let subsystem: String
	let category: String

	func debug(_ message: String) {
#if DEBUG
		print(message)
#endif
	}
}

So, the code will compile and the message will only be printed if you're in DEBUG.

  • @darkpaw sorry I should have mentioned earlier, it wouldn't work in the following logger.debug("Item name = \(itemName, privacy: .public)"), see my updated "Non-sensitive logging (Public)"

Add a Comment

Well of course it doesn't work. Even though you've got import os at the top of the file, by creating struct Logger further down you've ignored the os Logger entirely and used the one you've just created in your file, so it doesn't know how to interpolate \(itemName, privacy: .public).

If you want to use the os Logger, you need to remove your struct Logger.

I can't understand why you'd want to remove the timestamps, and if you do seriously need to do this, you'll have to use an extension and override the message, which might be difficult to do and gain you very little.

  •  @darkpaw Thanks a lot, I feel it clutters the Xcode debugger output and I find it a bit cluttered hard to read. Is there a way in Xcod to color different for different logger messages (some way ti differentiate: debug / log / error)

  • No. It's written to a plain text file.

    If you seriously don't want the timestamps you'll have to use your own Logger (the struct that was overriding the os version, with the #if debug in the right place), but you'll lose any of the niceties of os:Logger.

  • @darkpaw Thanks a lot! I will stick with Apple's Logger, there is no way I can build anything remotely as efficient or robust. They do a lot of good things, thanks

For general advice on this subject, see Your Friend the System Log. The limitation mentioned there (r. 32863680) means you have to choose between using the system log and getting the exact output you want in the Xcode console pane. IMO it’s better to choose the system log, and use Console app to get your nice output, but there are differences in opinion.

Share and Enjoy

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

  • @eskimo Thanks a lot! well written article and I like the reference to friendship. Definitely the advantages to using Logger far outweigh the my small preferences. So I will stick with the logger. My wish list is Xcode some day provides a way to customise how these messages are being displayed (more around timestamp being wrapped). It is definitely a priority .... a nice to have. Definitely console app does a good job in the meantime. Thanks once again

  • @eskimo I am so thrilled Xcode 15 (beta) has this feature, so for users who want can turn on timestamp, viewing and filtering logs is awesome to Xcode 15. Thanks a lot filing the radar and for all the folks involved in the development of the feature. I love it!!

  • I couldn't get past the claims that the System log is "powerful" and "full-featured". I can show you 20+ year logging frameworks with far more power. The Apple Logging system is anemic at best.

Add a Comment