Logging

ZetaKit routes all diagnostic output through Apple's Unified Logging System (os.Logger). Log output is visible in Xcode's console during a debug session and in Console.app on macOS when connected to a device.

Available since: iOS SDK 1.0.0.

All logging APIs live on the ZTLogger type. No SDK initialization is required before calling them.

On this page

Enable logging

By default, logging is disabled in production builds. Enable it as early as possible in your app lifecycle — typically before calling ZetaClient.shared.initialize(config:):

// AppDelegate.swift
import ZetaCore

func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    ZTLogger.setLogLevel(.verbose) // enable before initialize
    ZetaClient.shared.initialize(config: config)
    return true
}
@import ZetaCore;

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [ZTLogger setLogLevel:ZTLogLevelVerbose]; // enable before initialize
    [[ZetaClient shared] initializeWithConfig:config completionBlock:^{}];
    return YES;
}

To silence all SDK output:

ZTLogger.setLogLevel(.none)
[ZTLogger setLogLevel:ZTLogLevelNone];

setLogLevel(_:) is thread-safe and can be called at any time — before or after initialization.

Log levels

ZTLogLevel controls which messages are emitted. Only messages at or above the configured level reach the system log.

LevelRaw valueWhen to use
.verbose0Fine-grained trace output — every SDK step
.debug1Developer diagnostics useful during development
.info2Normal SDK lifecycle milestones
.warning3Unexpected but recoverable situations
.error4Failures that allow the SDK to continue
.none5Disables all output

Default levels

Build configurationDefault level
Debug (#if DEBUG).error
Production / release.none

Recommended setup for development

Use .verbose for maximum detail or .debug for less noise:

ZTLogger.setLogLevel(.verbose)
// or
ZTLogger.setLogLevel(.debug)
[ZTLogger setLogLevel:ZTLogLevelVerbose];
// or
[ZTLogger setLogLevel:ZTLogLevelDebug];

Log privacy

ZTLogPrivacy controls whether message content is visible outside a direct Xcode debug session (for example, in Console.app or a sysdiagnose capture).

ValueBehavior
.privateMessage content is redacted as <private> in all captures. Default.
.publicMessage content is fully visible in Console.app and system log captures.

For a deeper understanding of how Apple's logging system handles privacy, see OSLogPrivacy in the Apple Developer Documentation.

Global override — SDK-internal messages

ZTLogger.setLogPrivacy(.public) makes all SDK-internal diagnostic messages fully visible. This is useful when capturing a Console.app trace to share with the ZetaKit team.

ZTLogger.setLogPrivacy(.public)
[ZTLogger setLogPrivacy:ZTLogPrivacyPublic];
[ZTLogger setLogPrivacy:ZTLogPrivacyPrivate]; // restore default

Important: Only enable .public in development or diagnostic builds. SDK-internal messages may contain session identifiers or internal state that should not be visible in production logs.

Consumer logging

Route your own app messages through the SDK's logging pipeline using ZTLogger.log(_:level:privacy:category:errorCode:). Messages appear alongside SDK diagnostic output in Console.app under the same subsystem, making it easier to correlate app and SDK activity.

ZTLogger.log("checkout initiated")
ZTLogger.log("cart loaded", level: .debug)
ZTLogger.log("user id: \(userId)", level: .info, privacy: .public) // only if no PII risk
ZTLogger.log("payment failed", level: .error, category: "Payment", errorCode: "PAY-001")
[ZTLogger log:@"checkout initiated" level:ZTLogLevelInfo privacy:ZTLogPrivacyPrivate category:nil errorCode:nil];
[ZTLogger log:@"payment failed" level:ZTLogLevelError privacy:ZTLogPrivacyPrivate category:@"Payment" errorCode:@"PAY-001"];

The category parameter groups related entries under a named label in Console.app, and errorCode prepends a short code to the message to aid filtering and triage. Both default to nil.

Privacy on consumer messages

The privacy: argument on log(_:level:privacy:category:errorCode:) is always honored — it is not overridden by setLogPrivacy(_:). This means a consumer can set global privacy to .public for SDK internals while keeping their own messages .private:

ZTLogger.setLogPrivacy(.public)                    // SDK internals become visible
ZTLogger.log("sensitive data", privacy: .private)  // this message stays redacted
[ZTLogger setLogPrivacy:ZTLogPrivacyPublic];
[ZTLogger log:@"sensitive data"
        level:ZTLogLevelInfo
      privacy:ZTLogPrivacyPrivate
     category:nil
    errorCode:nil];

Debugging tips

Recommended setup for investigating an issue

ZTLogger.setLogLevel(.verbose)
ZTLogger.setLogPrivacy(.public) // only in a diagnostic build
[ZTLogger setLogLevel:ZTLogLevelVerbose];
[ZTLogger setLogPrivacy:ZTLogPrivacyPublic]; // only in a diagnostic build

This combination shows all SDK messages with their full content in Console.app.

Reading logs in Console.app

  1. Open Console.app on macOS.
  2. Select your device from the sidebar.
  3. Filter by Subsystem using your app's bundle identifier (for example, com.example.myapp).
  4. Use the search bar to filter by Category to narrow output to a specific SDK area.

Deprecated API

The following call sites from earlier SDK versions are still supported but will produce a deprecation warning. Migrate to the new static ZTLogger API.

BeforeAfter
ZetaClient.shared.log(log: "msg")ZTLogger.log("msg")
ZetaClient.shared.log("msg")ZTLogger.log("msg")
ZetaClient.setLogLevel(.verbose)ZTLogger.setLogLevel(.verbose)
ZetaClient.setLogPrivacy(.public)ZTLogger.setLogPrivacy(.public)

See also