Introduction: Why is logging needed in Swift?
Logging is a fundamental developer tool that allows you to track the application state, identify errors, and analyze user behavior. In the Swift ecosystem (iOS/macOS), properly configured logging can save hours of debugging and help avoid problems in production versions.
In this article, we will cover the best practices for logging in Swift: from Apple's built-in solutions to popular third-party libraries. You will learn how not to overload the application, how to protect sensitive data, and how to make logs useful for the entire team.
1. Built-in tools: OSLog and print
1.1 Why print() is bad
The simplest logging method is the print() command. However, it is not recommended for use in production versions:
- No severity levels (info, warning, error).
- Impossible to filter logs in the Xcode console.
- Text is output even in release builds (if not manually removed).
- No data structuring.
1.2 OSLog — the standard from Apple
Starting with iOS 10 and macOS 10.12, Apple recommends using os_log from the os.log framework. This is a built-in mechanism that is fast and secure.
import os.log
let logger = Logger(subsystem: "com.example.myapp", category: "network")
func fetchData() { logger.info("Start of data loading") // ... loading code logger.warning("Server responded with a delay") // ... error handling logger.error("Failed to connect to server: \\(error.localizedDescription)")}Advantages of OSLog:
- Automatic disabling in release builds (except for errors).
- Support for categories and subsystems for filtering.
- Integration with Console.app and Xcode.
- Security: private data is automatically hidden (marker
private).
2. SwiftLog — a universal API
2.1 What is SwiftLog?
SwiftLog is an open-source library from Apple that provides a unified interface for logging. It is platform-independent and allows connecting different backends (OSLog, files, servers).
2.2 Integration and setup
Add SwiftLog via Swift Package Manager:
// Package.swiftdependencies: [ .package(url: "https://github.com/apple/swift-log.git", from: "1.5.0")]Usage example:
import Logging
let logger = Logger(label: "com.example.app")
logger.info("Application launched")logger.warning("Low battery: \\(batteryLevel)%")logger.error("Critical error: \\(error)")
// Configuring the log levelLoggingSystem.bootstrap { label in var handler = StreamLogHandler.standardOutput(label: label) handler.logLevel = .debug return handler}Key features:
- Levels: trace, debug, info, notice, warning, error, critical.
- Metadata (any additional fields).
- Easily replaceable backend (e.g., for sending to Crashlytics).
- Zero cost when the level is disabled (faster than
print).
3. Third-party libraries: CocoaLumberjack and Pulse
3.1 CocoaLumberjack — flexibility and power
One of the most popular libraries for Objective-C and Swift. It allows writing logs to files, console, remote server, and even a database.
import CocoaLumberjack
// SetupDDLog.add(DDOSLogger.sharedInstance) // Consolelet fileLogger = DDFileLogger()fileLogger.rollingFrequency = 60 * 60 * 24 // 24 hoursDDLog.add(fileLogger)
// UsageDDLogInfo("User authorized")DDLogWarn("Network timeout")DDLogError("