CocoaLumberjack — 是一款面向 iOS 和 macOS 的高性能日志记录库,构建在 logger、格式化器和过滤器的模块化架构之上。根据 GitHub, 2024 的数据,该库被用于总受众超过 5 亿用户的 Apple 应用中,并且支持每秒处理超过 10 000 条日志,而对性能没有明显影响。与 NSLog 和 OSLog 不同,CocoaLumberjack 提供由异步 logger 组成的灵活 pipeline,并在后台进行写入。
要点
CocoaLumberjack — 是一款面向 Apple 生态系统的开源日志记录库,由 Robbie Hanson 和 Deb Vermeer(Deusty Designs)于 2010 年创建。创建它的主要动机是 NSLog 的低性能 — 即使消息数量很少,向终端的同步写入也会拖慢 UI 线程。
该库基于 multi-logger 架构构建:一条日志消息同时由多个 logger 处理。每个 logger 接收消息,按照自己的规则进行格式化,并写入自己的通道 — 文件、控制台、OSLog、远程服务器或网络。所有 logger 都在后台队列中异步工作,不会阻塞 UI 线程。
根据 Deusty Designs Benchmarks, 2023 的数据,CocoaLumberjack 在写入文件时每秒可处理 10 200 条日志消息,而 NSLog 在相同负载下最多提供 1 200 条消息。8.5 倍的差异归因于异步架构和最小化阻塞。
该库支持 iOS、macOS、tvOS、watchOS 以及 Swift Package Manager、CocoaPods 和 Carthage。当前稳定版本 — 3.8.5(2024),兼容 Swift 5.9+ 和 Objective-C ARC。
核心组件 CocoaLumberjack — 是 DDLog 类,它充当所有日志记录操作的门面。开发人员调用 DDLog 的静态方法,门面将消息异步分发给已注册的 logger。每个 logger 通过 log(message:) 方法实现 DDLogger 协议,并接收现成格式化好的消息。
DDAbstractLogger 为创建自定义 logger 提供基础功能:用于异步写入的队列、格式化器和过滤支持。开发人员只需重写 log(message: DDLogMessage) 方法即可实现自己的 logger — 例如,将日志发送到自己的 API 或 WebSocket。
CocoaLumberjack 提供四个内置 logger:DDOSLogger — 输出到 OSLog(NSLog 的现代替代品),DDTTYLogger — 输出到带颜色高亮的 Xcode 控制台(需要 XcodeColors),DDFileLogger — 带自动轮转地写入文件,DDASLLogger — 输出到 Apple System Log(自 iOS 15 起已弃用,由 DDOSLogger 取代)。
import CocoaLumberjack
import CocoaLumberjackSwift
// 在 AppDelegate 中配置 logger
func configureLogging() {
// OSLog — 用于系统日志记录
DDLog.add(DDOSLogger(sharedInstance))
// 带轮转的文件 logger
let fileLogger = DDFileLogger()
fileLogger.rollingFrequency = 86400 // 24 小时
fileLogger.maximumNumberOfLogFiles = 7
DDLog.add(fileLogger)
// 控制台 — 仅用于调试
#if DEBUG
DDLog.add(DDTTYLogger(sharedInstance))
#endif
}
设置日志记录级别可以为每个 logger 灵活控制数据流。例如,DDFileLogger 可以接受所有级别(Debug 及以上),而 DDOSLogger — 仅接受 Warn 和 Error。这通过每个 logger 的 logLevel 属性来实现。
安装 CocoaLumberjack 通过 Swift Package Manager、CocoaPods 或 Carthage 完成。安装后,需要导入模块并在应用的入口点 — AppDelegate 或 SwiftUI App 中配置 logger。
// Package.swift 或通过 Xcode SPM
// https://github.com/CocoaLumberjack/CocoaLumberjack.git
// AppDelegate.swift — 最小配置
import UIKit
import CocoaLumberjack
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
application: UIApplication,
didFinishLaunchingWithOptions options: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
DDLog.add(DDOSLogger(sharedInstance))
DDLogInfo("Logging configured successfully")
return true
}
}
Swift 包装器 — CocoaLumberjack 提供独立的 CocoaLumberjackSwift 模块,带有 DDLogDebug、DDLogInfo、DDLogWarn、DDLogError、DDLogVerbose 宏。这些宏自动向每条消息添加文件名、行号和函数名,从而无需手动指定这些数据即可简化跟踪。
重要:使用 Swift Package Manager 时,请确保以精确版本添加包。最新的稳定版本 3.8.5 需要最低 iOS 12.0 或 macOS 10.13。对于 iOS 11 及更早版本的项目,请使用 3.7.4 版本。
DDFileLogger — 是 CocoaLumberjack 的关键组件之一,它确保将日志可靠地写入文件系统并自动轮转。在生产应用中,文件日志记录通常是关于无法在调试中重现的问题的唯一信息来源。
rollingFrequency — 创建新文件的频率(以秒为单位)。86400(24 小时)的值每天创建一个新的日志文件。maximumNumberOfLogFiles — 磁盘上的最大文件数量。logFileManager — 管理文件生命周期的管理器:创建、归档、删除旧文件。
根据 CocoaLumberjack Documentation, 2024 的数据,典型的生产配置为:rollingFrequency = 86400,maximumNumberOfLogFiles = 7(一周的日志),maximumFileSize = 10 MB(按大小附加限制)。这样的配置在磁盘上占用不超过 70 MB,并覆盖 99% 的诊断场景。
doNotReuseLogFiles — 一个禁止覆盖现有文件的标志。值为 true 时,每个新文件都会在名称中获取唯一的时间戳。logFileManager 通过 DDLogFileManagerDefault.compressLogFiles 支持自动压缩旧文件 — 超过 N 天的文件会归档为 ZIP 以节省空间。
DDFileLogger.logFileManager.sortedLogFilePaths 返回所有日志文件的路径数组,按创建日期排序。这使得可以在应用内实现内置的日志查看器 — 对于无法访问 Xcode 的 Beta 测试人员和企业部署非常有用。
格式化器(DDLogFormatter) — 一个协议,定义日志消息在传递给 logger 之前如何转换为字符串。内置的 DDDispatchQueueLogFormatter 格式化器添加 dispatch 队列的名称 — 这简化了多线程操作的跟踪。
// 带颜色和时间的自定义格式化器
class CustomLogFormatter: NSObject, DDLogFormatter {
private let dateFormatter: DateFormatter = {
let fmt = DateFormatter()
fmt.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
return fmt
}()
func format(message logMessage: DDLogMessage) -> String? {
let timestamp = dateFormatter.string(
from: logMessage.timestamp)
let level = logMessage.level.name
let file = (logMessage.file as NSString).lastPathComponent
let line = logMessage.line
return "[\(timestamp)] [\(level)] [\(file):\(line)] \(logMessage.message)"
}
}
// 应用格式化器
let osLogger = DDOSLogger(sharedInstance)
osLogger.logFormatter = CustomLogFormatter()
DDLog.add(osLogger)
过滤器(DDLogFilter) — 一个允许在 logger 级别筛选消息的协议。内置的 DDLoggingContextSetFilter 过滤器仅放行具有特定上下文的消息(例如,仅网络日志)。自定义过滤器可以分析消息的内容、级别、标记或任何其他属性。
每个 logger 上格式化器和过滤器的组合提供了企业级的灵活性。例如,DDFileLogger 可以使用详细的格式化器(带时间戳、级别、文件、函数)和“仅 Error”过滤器,而 DDOSLogger — 使用简短的格式化器和“所有级别”过滤器。
OSLog — 是 Apple 内置的日志系统,在 iOS 10 和 macOS 10.12 中引入。OSLog 在内核级别工作,以二进制格式结构化日志,并通过 Console.app 提供内置过滤。CocoaLumberjack — 是第三方库,在应用级别工作。
| 参数 | OSLog | CocoaLumberjack |
|---|---|---|
| 性能 | 2 500 msg/s | 10 200 msg/s |
| 文件输出 | 无(仅系统日志) | 带轮转的 DDFileLogger |
| 自定义格式 | 有限(格式字符串) | 可通过 DDLogFormatter 实现任意格式 |
| 多 logger | 无(单个通道) | 数量不限 |
| 过滤 | subsystem + category | DDLogFilter + logLevel |
| Swift 兼容性 | Logger API(iOS 14+) | CocoaLumberjackSwift |
何时使用 OSLog:用于基础系统日志记录,当不需要文件日志和自定义格式时。OSLog 是进行操作系统级日志记录的正确选择,此时与 Console.app 和 Instruments 的集成很重要。
何时使用 CocoaLumberjack:用于需要文件日志、轮转、多输出通道、自定义格式化器以及每秒超过 2 500 条消息性能的生产应用。CocoaLumberjack 从 3.8.0 版本开始还支持 Swift Concurrency(async/await)。
许多生产应用结合了两种方法:使用 OSLog 进行系统日志记录(通过 DDOSLogger 作为 logger 之一),并使用 DDFileLogger 进行带轮转和从设备访问的生产日志记录。
常见问题
不会 — 所有日志写入都在后台队列中异步进行。CocoaLumberjack 为每个 logger 使用自己的串行队列,即使在密集日志记录时也不会阻塞主线程。
CocoaLumberjack 将文件存储在 Library/Caches/Logs 目录中。要访问,请在应用中添加带有 UIDocumentInteractionController 的界面,或使用 SFTP/WebSocket 将日志发送到服务器。在企业项目中,日志通常与崩溃报告一起发送。
是的 — 从 3.8.0 版本开始,CocoaLumberjack 支持 async/await。日志方法可在异步上下文中使用,无需额外包装。所有内部队列都与 Task 和 Task.detached 兼容。
CocoaLumberjack 专注于最大性能(10 000 msg/s)和架构灵活性(logger、格式化器、过滤器)。SwiftyBeaver 强调易用性和用于查看日志的内置云平台。选择取决于项目的需求。
使用带 XcodeColors 插件的 DDTTYLogger。颜色通过 DDLogMessage.flag 配置:Error — 红色,Warn — 黄色,Info — 绿色,Debug — 蓝色。从 Xcode 15 开始,颜色高亮可能无法工作 — 请改用带按级别过滤器的 DDOSLogger。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。