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.
| Level | Raw value | When to use |
|---|---|---|
.verbose | 0 | Fine-grained trace output — every SDK step |
.debug | 1 | Developer diagnostics useful during development |
.info | 2 | Normal SDK lifecycle milestones |
.warning | 3 | Unexpected but recoverable situations |
.error | 4 | Failures that allow the SDK to continue |
.none | 5 | Disables all output |
Default levels
| Build configuration | Default 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).
| Value | Behavior |
|---|---|
.private | Message content is redacted as <private> in all captures. Default. |
.public | Message 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
.publicin 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
- Open Console.app on macOS.
- Select your device from the sidebar.
- Filter by Subsystem using your app's bundle identifier (for example,
com.example.myapp). - 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.
| Before | After |
|---|---|
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) |
