iOS Logs installation
The PostHog iOS SDK has built-in support for capturing structured Logs from iOS, macOS, tvOS, watchOS, and visionOS apps. The SDK handles OTLP encoding, batching, on-disk persistence across app restarts, and lifecycle integration. You just call PostHogSDK.shared.captureLog(...) or PostHogSDK.shared.logger?.{trace,debug,info,warn,error,fatal}(...).
Manual capture only. Logs are emitted by your code. The SDK does not autocapture system log streams (
os_log,Logger,
Minimum version:
posthog-ios@3.58.0or later. Runpod update PostHog(CocoaPods) or update the package version in Xcode (Swift Package Manager).
- 1
Install posthog-ios
RequiredIf you haven't installed
posthog-iosyet, follow the steps below. For full details, see the iOS SDK guide.PostHog is available through CocoaPods or you can add it as a Swift Package Manager based dependency.
CocoaPods
PodfileSwift Package Manager
Add PostHog as a dependency in your Xcode project "Package Dependencies" and select the project target for your app, as appropriate.
For a Swift Package Manager based project, add PostHog as a dependency in your
Package.swiftfile's Package dependencies section:Package.swiftand then as a dependency for the Package target utilizing PostHog:
Package.swiftConfiguration
Configuration is done through the
PostHogConfigobject. Here's a basic configuration example to get you started.You can find more advanced configuration options in the configuration page.
SwiftSwift - 2
Configure logs in your PostHogConfig
RequiredConfigure Logs through
config.logsbefore callingsetup(_:). All fields are optional; defaults are tuned for mobile (cellular bandwidth, battery, OS lifecycle).SwiftThese resource attributes are captured at
setup(_:)and apply to every batch. Mutatingconfig.logsaftersetuphas no effect. - 3
Capture logs
RequiredUse
PostHogSDK.shared.loggerfor the per-level convenience API, orPostHogSDK.shared.captureLogfor full control over level, attributes, and trace context.SwiftAvailable severity levels:
.trace,.debug,.info,.warn,.error,.fatal.Records are buffered, batched, persisted to disk, and flushed automatically – every 30 seconds, when the buffer hits the threshold, when the app moves to the background, or on
PostHogSDK.shared.flush().flush()drains events, Session Replay, and Logs together.Each record is automatically tagged with the current distinct ID, session ID, current screen, app foreground/background state, and active Feature Flags at the moment of capture.
- 4
Test your setup
Recommended- Capture a test log from your app:Swift
- Open the PostHog Logs UI.
- Filter by
service.name = 'my-app'(or whatever value you set above).
You should see your record arrive within a few seconds.
- Capture a test log from your app:
- 5
Tune buffering, rate cap, and resource attributes
OptionalThe
logsconfig has knobs for high-volume apps:SwiftFull configuration reference:
Field Default What it does serviceNamebundle identifier OTLP service.nameresource attributeserviceVersionCFBundleShortVersionStringOTLP service.versionresource attributeenvironmentnilOTLP deployment.environmentresource attributeresourceAttributes[:]Extra OTLP resource attributes (SDK keys win on collision) flushIntervalSeconds30Periodic flush interval flushAt20Buffer threshold that triggers an automatic flush maxBatchSize50Max records per outbound POST (halved on 413) maxBufferSize1000Max records held on disk before FIFO eviction rateCapMaxLogs500Max records per rateCapWindowSecondswindow. Set to0to disable.rateCapWindowSeconds10Rate-cap tumbling window length All of the above are captured at
setup(_:); mutating them later has no effect. Defaults are tuned for cellular-aware mobile apps. RaiserateCapMaxLogsandmaxBufferSizefor high-volume scenarios. - 6
Filter or redact with beforeSend
OptionalbeforeSendruns synchronously before the rate cap, so dropped records don't consume the per-window budget. Use it for redaction, sampling, or filtering by level. Each block receives a mutablePostHogLogRecordand returns either the (possibly mutated) record ornilto drop it.SwiftPass an array (or a comma-separated list) of blocks to compose a chain – evaluated left-to-right. Returning
nilfrom any block short-circuits and drops the record. Settingrecord.bodyto an empty string also drops the record.From Objective-C, wrap each closure in a
BoxedBeforeSendLogBlock:objc Next steps
CheckpointWhat you can do with your logsAction Description Why you need logs What logs show you that nothing else does Search logs Use the search interface to find specific log entries Filter by level Filter by INFO,WARN,ERROR, etc.Link session replay Connect logs to users and session replays by passing posthogDistinctIdandsessionIdLogging best practices Learn what to log, how to structure logs, and patterns that make logs useful in production