|
| 1 | +# SwiftLogOSLogHandler |
| 2 | + |
| 3 | +**SwiftLogOSLogHandler** is a logging backend for Apple’s [swift-log](https://github.com/apple/swift-log). It integrates with Apple’s [OSLog](https://developer.apple.com/documentation/os/logging) Unified Logging system and provides advanced string interpolation for flexible, compile-time-controlled logging. |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## Features |
| 8 | + |
| 9 | +- **Apple Unified Logging Integration**: Leverage OSLog for optimized, structured, and categorized logging. |
| 10 | +- **Advanced String Interpolation**: Customize log messages with options like privacy, formatting, alignment, and more. |
| 11 | + |
| 12 | +--- |
| 13 | + |
| 14 | +## Installation |
| 15 | + |
| 16 | +### Swift Package Manager |
| 17 | + |
| 18 | +To include **SwiftLogOSLogHandler** in your project, add it to your `Package.swift` file: |
| 19 | + |
| 20 | +```swift |
| 21 | +let package = Package( |
| 22 | + name: "YourProject", |
| 23 | + platforms: [ |
| 24 | + .iOS(.v14), |
| 25 | + .macOS(.v10_13) |
| 26 | + ], |
| 27 | + dependencies: [ |
| 28 | + .package( |
| 29 | + url: "git@github.com:TechArtists/ios-swift-log-os-log-handler.git", |
| 30 | + from: "1.0.0" |
| 31 | + ) |
| 32 | + ], |
| 33 | + targets: [ |
| 34 | + .target( |
| 35 | + name: "YourTarget", |
| 36 | + dependencies: [ |
| 37 | + .product(name: "SwiftLogOSLogHandler", package: "SwiftLogOSLogHandler") |
| 38 | + ] |
| 39 | + ) |
| 40 | + ] |
| 41 | +) |
| 42 | +``` |
| 43 | +Alternatively, to add the package using Xcode: |
| 44 | + |
| 45 | + 1. Navigate to File > Add Packages. |
| 46 | + 2. Enter the repository URL: `git@github.com:TechArtists/ios-swift-log-os-log-handler.git`. |
| 47 | + 3. Add the package to your target. |
| 48 | +## Usage |
| 49 | + |
| 50 | +To effectively utilize logging in your application, initialize and manage your loggers using the `init(label: String, factory: (String) -> any LogHandler)` method of the `Logger`. This method allows for versatile logging configurations, making it easy to combine `SwiftLogOSLogHandler` with other logging handlers, such as file-based handlers, using the `MultiplexLogHandler`. |
| 51 | + |
| 52 | +```swift |
| 53 | +import Logging |
| 54 | +import Foundation |
| 55 | +import SwiftLogFileLogHandler |
| 56 | +import SwiftLogOSLogHandler |
| 57 | + |
| 58 | +enum Loggers { |
| 59 | + static let main = Logging.Logger(label: "main") { label in |
| 60 | + MultiplexLogHandler([ |
| 61 | + SwiftLogOSLogHandler(label: label, shouldLogCallsiteMetadata: true), |
| 62 | + SwiftLogFileLogHandler(label: label) |
| 63 | + ]) |
| 64 | + } |
| 65 | + |
| 66 | + static let onboarding = Logging.Logger(label: "onboarding") { label in |
| 67 | + MultiplexLogHandler([ |
| 68 | + SwiftLogOSLogHandler(label: label), |
| 69 | + SwiftLogFileLogHandler(label: label) |
| 70 | + ]) |
| 71 | + } |
| 72 | +} |
| 73 | + |
| 74 | +Loggers.main.info("Welcome Main Logger") |
| 75 | +Loggers.onboarding.info("Welcome Onboarding logger") |
| 76 | + |
| 77 | +// Output |
| 78 | +// Main: Welcome Main Logger |
| 79 | +// Onboarding: Welcome Onboarding logger |
| 80 | + |
| 81 | +``` |
| 82 | + |
| 83 | +## Differences Between `SwiftLogOSLogHandler` and `OS_log` |
| 84 | + |
| 85 | +While `SwiftLogOSLogHandler` provides a convenient bridge to integrate Apple's OSLog system with the Swift logging API, there are some important distinctions to consider when choosing between using this library and using `OS_log` directly: |
| 86 | + |
| 87 | +### Performance |
| 88 | + |
| 89 | +- **OSlog Optimizations**: The native `OSlog` API is optimized for performance, offering efficient logging capabilities that are tailored specifically for Apple's operating systems. This includes direct support for various log levels, privacy controls, and more, with minimal overhead. |
| 90 | +- **SwiftLogOSLogHandler Efficiency**: Using `SwiftLogOSLogHandler` introduces some overhead compared to directly using `OSlog`, due to the additional layer that bridges Swift's logging system with `OSlog`. However, this trade-off is generally acceptable for many applications that benefit from the streamlined logging API provided by `swift-log`. |
| 91 | + |
| 92 | +### Call Site Accuracy |
| 93 | + |
| 94 | +- **OS_log Call Site**: The native `OSlog` accurately captures the call site information (file, function, line) and associates this metadata directly with each log entry. |
| 95 | +- **SwiftLogOSLogHandler Call Site**: Due to the way Swift’s logging system interacts with `OS_log`, the call site information will not reflect the actual source of the log message but rather the location within the handler itself. To compensate for this, `SwiftLogOSLogHandler` offers a `shouldLogCallsiteMetadata` parameter. When enabled, this option appends call site metadata directly into your log messages in the format: `[File: \(file), Function: \(function), Line: \(line)]`: |
| 96 | + |
| 97 | +```swift |
| 98 | +let main = SwiftLogOSLogHandler(label: "example", shouldLogCallsiteMetadata: true) |
| 99 | + |
| 100 | +// Example Log Message |
| 101 | +main.info("Important action performed") |
| 102 | + |
| 103 | +// Output |
| 104 | +// Important action performed [File: Example.swift, Function: performAction, Line: 42] |
| 105 | +``` |
| 106 | + |
| 107 | +### Advanced String Interpolation with `taMessage` |
| 108 | + |
| 109 | +The `taMessage` parameter allows for enhanced string interpolation in log messages, including: |
| 110 | +- **Privacy Options**: Use `.public` or `.private` to control the visibility of log message content. |
| 111 | +- **Formatting**: Apply formatting options such as `.fixed` for numeric precision. |
| 112 | +- **Alignment**: Define alignment and column width for text. |
| 113 | + |
| 114 | +**Example Usage**: |
| 115 | + |
| 116 | +```swift |
| 117 | +let testString = "Performance Test" |
| 118 | +let cpuUsage = 89.57 |
| 119 | + |
| 120 | +Loggers.main.info(taMessage: "\(testString, privacy: .public)") |
| 121 | +Loggers.main.error(taMessage: "High CPU usage: \(cpuUsage, format: .fixed(precision: 2), align: .left(columns: 10))%") |
| 122 | +Loggers.main.critical(taMessage: "System health critical. \(UUID(), privacy: .private) CPU: \(cpuUsage, privacy: .public)") |
| 123 | +Loggers.main.notice(taMessage: "Running maintenance. Task ID: \(UUID(), privacy: .public)") |
| 124 | +``` |
| 125 | + |
| 126 | +**Example Output**: |
| 127 | + |
| 128 | +``` |
| 129 | +Performance Test [File: SystemMonitor.swift, Function: checkPerformance, Line: 120] |
| 130 | +High CPU usage: <redacted>% |
| 131 | +System health critical. <redacted> CPU: 89.57 |
| 132 | +Running maintenance. Task ID: 5E6A10C8-45F0-4923-8C28-3A6C8D17F7AA |
| 133 | +``` |
| 134 | + |
| 135 | +### Logging with Bootstrapping |
| 136 | + |
| 137 | +To ensure all logs are effectively captured and routed through the desired logging backend, you need to bootstrap the logging system. Bootstrapping associates a specific handler, such as `SwiftLogOSLogHandler`, to all `Logger` instances created thereafter. |
| 138 | + |
| 139 | +Here’s how to configure OSLog as the universal backend by bootstrapping the logging system: |
| 140 | + |
| 141 | +```swift |
| 142 | +import Logging |
| 143 | +import SwiftLogOSLogHandler |
| 144 | + |
| 145 | +// Bootstrap the logging system with OSLog as the handler. |
| 146 | +LoggingSystem.bootstrap { label in |
| 147 | + SwiftLogOSLogHandler(label: label) |
| 148 | +} |
| 149 | + |
| 150 | +// Create a Logger instance after bootstrapping. |
| 151 | +let loggerMain = Logger(label: "Main") |
| 152 | + |
| 153 | +// Log messages using the logger instance. |
| 154 | +// These messages will now be routed and handled by the bootstrapped SwiftLogOSLogHandler. |
| 155 | +loggerMain.info("Application started successfully.") |
| 156 | +loggerMain.warning("Low disk space detected.") |
| 157 | +``` |
| 158 | + |
| 159 | +**OSLog Output**: |
| 160 | +``` |
| 161 | +Main: info: Application started successfully. |
| 162 | +Main: warning: Low disk space detected. |
| 163 | +``` |
| 164 | + |
| 165 | +### Important Considerations |
| 166 | + |
| 167 | +- **Bootstrap Before Using Loggers**: Ensure that you bootstrap the logging system *before* creating any `Logger` instances. Loggers created prior to bootstrapping will not be associated with the specified backend and may not output logs as expected. |
| 168 | + |
| 169 | +- **Universal Handling**: Once you bootstrap with `SwiftLogOSLogHandler`, all subsequent `Logger` instances in your application will use OSLog, ensuring consistent and centralized logging behavior. |
| 170 | + |
| 171 | +## License |
| 172 | + |
| 173 | +This project is licensed under the MIT License. See the LICENSE file for more details. |
0 commit comments