Exporting from OSLogStore doesn't respect privacy.

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?

Replies

Great question, I will make some assumptions about the configuration here but let me know if some of these are wrong and I will state them below.

When Xcode launches a process it will unredact the logging for that single process if it is for an application that you are privileged to view. (One that is able to be attached with a debugger) This is done by default for all processes and has been done since the release of unified logging however there are ways to disable this behavior if you need for testing like in your case. I will list a few options that you have based on possible configurations.

  1. Any Config: Launch the application without the use of Xcode though the target device and stream logging through Console. (This will preserver the privacy behavior that the app will have in production)
  2. Xcode 15+ with (iOS 17+, watchOS 10+, tvOS 17+, macOS 14+): You can add these two env vars to your scheme to launch the process with no logging collection. (This means the console will not show any logging and only stdio output) IDELogRedirectionPolicy=disabled & IDE_DISABLED_OS_ACTIVITY_DT_MODE=1
  3. Xcode 14- or (iOS 16-, watchOS 9-, tvOS 16-, macOS 13-): You can add this one env var to your shceme to launch the process with no logging collection. (This again means the console will not show any logging and only stdio output) IDE_DISABLED_OS_ACTIVITY_DT_MODE=1

Notes:

  • IDELogRedirectionPolicy=disabled: This env var will tell Xcode to disable structured logging collection and to fallback to the legacy unstructured log echoing.
  • IDE_DISABLED_OS_ACTIVITY_DT_MODE=1: This env var will tell Xcode to disable the legacy unstructured log echoing method.

Please follow up with whether this solved your issue and if you have further questions or observations.

When Xcode launches a process it will unredact the logging for that single process if it is for an application that you are privileged to view. (One that is able to be attached with a debugger)

Oh! So because I’m running the debug build of the app, from Xcode, I’m able to see unredacted logs, just like I would in the console, even though I’m exporting them.

Testing this exact same code with a TestFlight build confirms the private data is correctly redacted, so this absolutely solves my problem.

Thank you so much!