HBC Digital logo      Gilt Tech logo

CleanroomLogger

CleanroomLogger 提供了一个可扩展的、基于 Swift 的日志 API,它简单、轻量且性能出色。

CleanroomLogger 提供的 API 设计得很容易被熟悉诸如 CocoaLumberjacklog4j 之类软件包的人理解。

CleanroomLogger 是来自 Gilt TechCleanroom Project 的一部分。

Swift 兼容性

这是 master 分支。它使用 Swift 4.1 并且 需要 Xcode 9.3 才能编译。

当前状态

分支 构建状态
master Build status: master branch

目录

CleanroomLogger 的主要优势

▶︎ 为速度而生

你无需在流畅滚动和收集有意义的日志信息之间做出选择。CleanroomLogger 在调用线程上做的工作非常少,因此它可以尽快回到正轨。

▶ 具有一流传统支持的现代日志引擎

CleanroomLogger 利用了 Apple 新的 统一日志系统 (又名 “OSLog” 或 “os_log”),当运行在 iOS 10.0、macOS 10.12、tvOS 10.0、watchOS 3.0 或更高版本上时。

在 OSLog 不可用的系统上,CleanroomLogger 会优雅地自动回退到其他标准输出机制。

▶ 100% 文档化

良好的文档对于任何开源框架的实用性都至关重要。除了你在下面找到的广泛的高级文档之外,CleanroomLogger API 本身也是 100% 文档化的。

▶ 按严重性组织和过滤消息

消息被分配为五个 严重性级别 之一:最严重的是 error,其次是 warninginfodebugverbose,这是最不严重的。 了解消息的严重性可以让你执行额外的过滤; 例如,为了最大限度地减少在 App Store 二进制文件中记录日志的开销,你可以选择仅记录发布版本中的警告和错误。

▶ 颜色编码的日志消息

在 Xcode 控制台中快速发现运行时的问题,日志消息会按严重程度进行颜色编码

◽️ Verbose messages are tagged with a small gray square — easy to ignore
◾️ Debug messages have a black square; easier to spot, but still de-emphasized
🔷 Info messages add a splash of color in the form of a blue diamond
🔶 Warnings are highlighted with a fire-orange diamond
❌ Error messages stand out with a big red X — hard to miss!

▶ UNIX 友好

内置了对标准 UNIX 输出流的支持。 使用 StandardOutputLogRecorderStandardErrorLogRecorder 将输出定向到 stdoutstderr,分别。

或者,使用 StandardStreamsLogRecorder 将 verbose、debug 和 info 消息发送到 stdout,同时将 warnings 和 errors 发送到 stderr

▶ 自动处理 OS_ACTIVITY_MODE

当 Xcode 8 被引入时,控制台窗格变得更加冗长。 这是由于 ASL facility 被 OSLog 替换所致。 为了消除额外的冗余,开发者发现 OS_ACTIVITY_MODE 环境变量设置为 “disable 会恢复到旧的日志记录行为。 事实证明,这完全静默了 OSLog,因此不会将任何输出发送到控制台窗格。 CleanroomLogger 会注意到该设置何时存在,并在通过 os_log() 函数记录消息之外,还会将消息回显到 stdoutstderr

▶ 查看你的代码在哪里记录日志

如果你只是在到处使用 print()NSLog(),有时很难弄清楚哪个代码负责哪些日志消息。 默认情况下,CleanroomLogger 会输出负责发出每个日志消息的源文件和行号,因此你可以直接找到源头

🔶 AppleTart.framework didn’t load due to running on iOS 8 (AppleTartShim.swift:19)
◾️ Uploaded tapstream batch (TapstreamTracker.swift:166)
◽️ Presenting AccountNavigationController from SaleListingController (BackstopDeepLinkNavigator.swift:174)
🔷 Successfully navigated to .account for URL: gilt://account (DeepLinkConsoleOutput.swift:104)
❌ Unrecognized URL: CountrySelector (GiltOnTheGoDeepLinkRouter.swift:100)

▶ 旋转日志文件

CleanroomLogger 提供了 简单的基于文件的日志记录 支持,以及 自我修剪的旋转日志目录 实现。

▶ 超级简单的执行跟踪

开发者经常使用日志记录来执行跟踪。 无需编写大量不同的日志消息来弄清楚你的程序在运行时正在做什么,只需在你的源代码中散布 Log.debug?.trace()Log.verbose?.trace() 调用,你就可以准确地看到你的代码命中了哪些行,何时命中,以及在哪个线程上命中,以及正在执行的函数的签名

2017-01-05 13:46:16.681 -05:00 | 0001AEC4 ◾️ —> StoreDataTransaction.swift:42 - executeTransaction()
2017-01-05 13:46:16.683 -05:00 | 00071095 ◾️ —> LegacyStoresDeepLinking.swift:210 - viewControllerForRouter(_:destination:)
2017-01-05 13:46:16.683 -05:00 | 0001AEC4 ◽️ —> StoreDataTransaction.swift:97 - executeTransaction(completion:)
2017-01-05 13:46:16.684 -05:00 | 00071095 ◾️ —> ContainerViewController.swift:132 - setContentViewController(_:animated:completion:)
2017-01-05 13:46:16.684 -05:00 | 00071095 ◾️ —> DefaultBackstopDeepLinkNavigator.swift:53 - navigate(to:via:using:viewController:displayOptions:completion:)
2017-01-05 13:46:16.687 -05:00 | 00071095 ◽️ —> ViewControllerBase.swift:79 - viewWillAppear

▶ 有用的内置格式化器

CleanroomLogger 附带了两个通用的日志格式化器:ReadableLogFormatter 对于人工阅读很方便,而 ParsableLogFormatter 对于机器处理很有用。 两者都可以通过初始化程序进行自定义。

使用 ReadableLogFormatter() 构造的格式化器会产生如下所示的日志输出

2017-01-06 02:06:53.679 -05:00 | Debug   | 001BEF88 | DeepLinkRouterImpl.swift:132 - displayOptions(for:via:displaying:)
2017-01-06 02:06:53.682 -05:00 | Verbose | 001BEF88 | UIWindowViewControllerExtension.swift:133 - rootTabBarController: nil
2017-01-06 02:06:53.683 -05:00 | Info    | 001BEF88 | DeepLinkConsoleOutput.swift:104 - Successfully navigated to storeSale for URL: gilt://sale/women/winter-skin-rescue
2017-01-06 02:07:01.761 -05:00 | Error   | 001BEF88 | Checkout.swift:302 - The user transaction failed
2017-01-06 02:07:02.397 -05:00 | Warning | 001BEF88 | MemoryCache.swift:233 - Caching is temporarily disabled due to a recent memory warning

当相同的日志消息由使用 ParsableLogFormatter() 构造的格式化器处理时,时间戳以 UNIX 格式输出,制表符用作字段分隔符,并且严重性以数字方式指示

1483686413.67946	2	001BEF88	DeepLinkRouterImpl.swift:132 - displayOptions(for:via:displaying:)
1483686413.68170	1	001BEF88	UIWindowViewControllerExtension.swift:133 - rootTabBarController: nil
1483686413.68342	3	001BEF88	DeepLinkConsoleOutput.swift:104 - Successfully navigated to storeSale for URL: gilt://sale/women/winter-skin-rescue
1483686421.76101	5	001BEF88	Checkout.swift:302 - The user transaction failed
1483686422.39651	4	001BEF88	MemoryCache.swift:233 - Caching is temporarily disabled due to a recent memory warning

▶ 轻松混合搭配格式

如果内置格式化器不符合要求,你可以使用 FieldBasedLogFormatter 来组装几乎任何可能的日志格式。

假设你想要一个日志格式化器,其时间戳采用 ISO 8601 日期格式,一个制表符,调用站点的源文件和行号,然后是严重性,以大写字符串显示,并在 8 个字符的字段中右对齐,然后是一个冒号和一个空格,最后是日志条目的有效负载。 你可以通过如下构造 FieldBasedLogFormatter 来做到这一点

FieldBasedLogFormatter(fields: [
	.timestamp(.custom("yyyy-MM-dd'T'HH:mm:ss.SSSZ")),
	.delimiter(.tab),
	.callSite,
	.severity(.custom(textRepresentation: .uppercase, truncateAtWidth: nil, padToWidth: 8, rightAlign: true)),
	.literal(": "),
	.payload])

生成的输出将如下所示

2017-01-08T12:55:17.905-0500	DeepLinkRouterImpl.swift:207        DEBUG: destinationForURL
2017-01-08T12:55:20.716-0500	DefaultDeepLinkRouter.swift:95       INFO: Attempting navigation to storeSale
2017-01-08T12:55:21.995-0500	LegacyUserEnvironment.swift:109		ERROR: Can’t fetch user profile without user guid
2017-01-08T12:55:25.960-0500	DeepLinkConsoleOutput.swift:104	  WARNING: Can’t find storeProduct for URL
2017-01-08T12:55:33.457-0500	ProductViewController.swift:92    VERBOSE: deinit

▶ 完全可扩展

CleanroomLogger 公开了三个主要扩展点,用于实现你自己的自定义逻辑

许可证

CleanroomLogger 在 MIT 许可证 下分发。

CleanroomLogger 以“按原样”的方式免费提供给你使用。 我们不作任何保证、承诺或道歉。 Caveat developer.

将 CleanroomLogger 添加到你的项目

Carthage compatible

集成 CleanroomLogger 最简单的方法是使用 Carthage 依赖管理工具。

首先,将此行添加到你的 Cartfile

github "emaloney/CleanroomLogger" ~> 6.0.0

然后,使用 carthage 命令 更新你的依赖项

最后,你需要 将 CleanroomLogger 集成到你的项目中 才能使用它提供的 API

成功集成后,只需将以下语句添加到要使用 CleanroomLogger 的任何 Swift 文件中

import CleanroomLogger

有关将 CleanroomLogger 集成到你的项目中的其他详细信息,请参阅 集成文档

使用 CleanroomLogger

CleanroomLogger 的主要公共 API 由 Log 提供。

Log 维护五个静态只读 LogChannel 属性,它们对应于五个严重性级别之一,指示通过该通道发送的消息的重要性。 发送消息时,你将选择适合该消息的严重性,并使用相应的通道

每个 LogChannel 都提供三个函数来记录日志消息

启用日志记录

默认情况下,日志记录是禁用的,这意味着 Log 的所有通道都没有被填充。 因此,它们具有 nil 值,并且任何执行日志记录的尝试都将静默失败。

为了使用 CleanroomLogger,您必须显式启用日志记录,这可以通过调用 Log.enable() 函数之一来完成。

理想情况下,日志记录应在应用程序启动周期的第一个可能点启用。 否则,由于记录器尚未初始化,因此可能会在启动期间错过关键日志消息。

放置 Log.enable() 调用的最佳位置是在应用程序委托的 init() 的第一行。

如果您由于某些原因不想这样做,那么下一个最佳位置是在应用程序委托的 application(_:willFinishLaunchingWithOptions:) 函数中。 您会注意到我们特别推荐 will 函数,而不是典型的 did,因为前者在应用程序启动周期中更早被调用。

注意: 在应用程序进程的运行生命周期中,只有第一次调用 Log.enable() 函数才会生效。 所有后续调用都会被静默忽略。 您还可以通过调用 Log.neverEnable() 来完全阻止启用 CleanroomLogger。

日志记录示例

要在日志中记录项目,只需选择适当的通道并调用适当的函数。

以下是一些示例

记录任意文本消息

假设您的应用程序刚刚完成启动。 这是一个重要的事件,但它不是错误。 您可能还希望在生产应用程序日志中看到此信息。 因此,您确定适当的 LogSeverity.info,并且您选择相应的 LogChannel,即 Log.info。 然后,要记录消息,只需调用通道的 message() 函数

Log.info?.message("The application has finished launching.")

记录跟踪消息

如果您正在处理一些代码,并且对执行顺序感到好奇,您可以散布一些 trace() 调用。

此函数输出文件名、行号和调用函数的名称。

例如,如果您将以下代码放在 ModularTable.swift 文件的第 364 行,该文件位于具有签名 tableView(_:cellForRowAt:) 的函数中

Log.debug?.trace()

假设为 .debug 严重性启用了日志记录,则在执行该行时将记录以下消息

ModularTable.swift:364 — tableView(_:cellForRowAt:)

记录任意值

value() 函数可用于输出有关特定值的信息。 该函数采用 Any? 类型的参数,旨在接受任何有效的运行时值。

例如,您可能想要输出传递给 UITableViewDataSourcetableView(_:cellForRowAt:) 函数的 IndexPath

Log.verbose?.value(indexPath)

这将导致如下所示的输出

= IndexPath: [0, 2]

该函数还处理可选值

var str: String?
Log.verbose?.value(str)

此函数的输出将是

= nil

CleanroomLogger 深入探讨

本节深入探讨了配置和自定义 CleanroomLogger 以满足您需求的具体细节。

配置 CleanroomLogger

当调用 Log.enable() 函数变体之一时,将配置 CleanroomLogger。 配置最多可以在运行进程的生命周期内进行一次。 一旦设置,配置就无法更改;它是不可变的。

LogConfiguration 协议表示可用于配置 CleanroomLogger 的机制。 LogConfiguration 允许将相关设置和行为封装在单个实体中,并且可以使用多个 LogConfiguration 实例配置 CleanroomLogger 以允许组合行为。

每个 LogConfiguration 指定

当 CleanroomLogger 收到记录某些内容的请求时,会选择零个或多个 LogConfiguration 来处理该请求

  1. 传入的 LogEntryseverity 与每个 LogConfigurationminimumSeverity 进行比较。 将选择任何 minimumSeverity 等于或小于 LogEntryseverityLogConfiguration 以供进一步考虑。
  2. 然后,将 LogEntry 依次传递给每个 LogConfigurationfiltersshouldRecord(entry:) 函数。 如果任何 LogFilter 返回 false,则不会选择关联的配置来记录该日志条目。
XcodeLogConfiguration

XcodeLogConfiguration 非常适合在开发期间进行实时查看,它会检查运行时环境以优化 CleanroomLogger 在 Xcode 中的使用。

XcodeLogConfiguration 考虑了

使用统一日志记录系统时,Xcode 控制台中的消息会带有如下所示的信息头前缀

2017-01-04 22:56:47.448224 Gilt[5031:89847] [CleanroomLogger]	
2017-01-04 22:56:47.448718 Gilt[5031:89847] [CleanroomLogger]	
2017-01-04 22:56:47.449487 Gilt[5031:89847] [CleanroomLogger]	
2017-01-04 22:56:47.450127 Gilt[5031:89847] [CleanroomLogger]	
2017-01-04 22:56:47.450722 Gilt[5031:89847] [CleanroomLogger]	

此标头不是由 CleanroomLogger 添加的; 它是由于在 Xcode 中使用 OSLog 而添加的。 它显示日志条目的时间戳,后跟进程名称、进程 ID、调用线程 ID 和日志记录系统名称。

为了确保跨平台的一致输出,即使记录到 stdoutstderrXcodeLogConfiguration 也会模仿此标头。 您可以通过将 false 作为 mimicOSLogOutput 参数传递来禁用此行为。 禁用后,将使用更简洁的标头,仅显示时间戳和调用线程 ID

2017-01-04 23:46:17.225 -05:00 | 00071095
2017-01-04 23:46:17.227 -05:00 | 00071095
2017-01-04 23:46:17.227 -05:00 | 000716CA
2017-01-04 23:46:17.228 -05:00 | 000716CA
2017-01-04 23:46:17.258 -05:00 | 00071095

为了更容易在运行时快速识别重要的日志消息,XcodeLogConfiguration 使用了 XcodeLogFormatter,它嵌入了每条消息严重性的颜色编码表示形式

◽️ Verbose messages are tagged with a small gray square — easy to ignore
◾️ Debug messages have a black square; easier to spot, but still de-emphasized
🔷 Info messages add a splash of color in the form of a blue diamond
🔶 Warnings are highlighted with a fire-orange diamond
❌ Error messages stand out with a big red X — hard to miss!

使用 XcodeLogConfiguration 启用 CleanroomLogger 的最简单方法是调用

Log.enable()

感谢默认参数值的魔力,这等效于以下 Log.enable() 调用

Log.enable(minimumSeverity: .info,
                 debugMode: false,
          verboseDebugMode: false,
            stdStreamsMode: .useAsFallback,
          mimicOSLogOutput: true,
              showCallSite: true,
                   filters: [])

这将使用带有 默认设置XcodeLogConfiguration 配置 CleanroomLogger。

注意: 如果 debugModeverboseDebugModetrue,则 XcodeLogConfiguration 将在 synchronousMode 中使用,不建议在生产代码中使用。

上面的调用也等同于

Log.enable(configuration: XcodeLogConfiguration())
RotatingLogFileConfiguration

可以使用 RotatingLogFileConfiguration 来维护一个每日轮换的日志文件目录。

警告:RotatingLogFileConfiguration 创建的 RotatingLogFileRecorder 假定对日志目录具有完全控制权。 任何未被识别为活动日志文件的文件将在自动清理过程中被删除,该过程可能随时发生。 这意味着如果您不注意传递的 directoryPath,您可能会丢失有价值的数据!

至少,RotatingLogFileConfiguration 要求您指定日志记录的 minimumSeverity,保留日志文件的天数以及存储这些文件的目录

// logDir is a String holding the filesystem path to the log directory
let rotatingConf = RotatingLogFileConfiguration(minimumSeverity: .info,
                                                     daysToKeep: 7,
                                                  directoryPath: logDir)

Log.enable(configuration: rotatingConf)

上面的代码将记录严重性为 .info 或更高的任何日志条目,该文件将至少保留 7 天,然后进行清理。 此特定配置使用 ReadableLogFormatter 来格式化日志条目。

RotatingLogFileConfiguration 还可以用于指定 synchronousMode,要应用的一组 LogFilter 以及一个或多个自定义 LogFormatter

多个配置

CleanroomLogger 还支持多个配置,允许同时使用不同的日志记录行为。

每当记录消息时,都会分别查询每个 LogConfiguration,并有机会处理该消息。 通过提供 minimumSeverity 和唯一的 LogFilter 集,每个配置都可以指定其自己的逻辑来筛选掉不需要的消息。 然后,将幸存的消息传递给配置的 LogFormatter,依次传递,直到一个返回非 nil 字符串。 该字符串(格式化的日志消息)最终传递给一个或多个 LogRecorder,以写入某些底层日志记录工具。

请注意,每个配置都是一个独立的实体。 给定 LogConfiguration 的任何设置、行为或操作都不会影响任何其他配置。

有关其工作方式的示例,请想象一下将调试模式 XcodeLogConfiguration 添加到上面声明的 rotatingConf。 您可以通过编写以下代码来做到这一点

Log.enable(configuration: [XcodeLogConfiguration(debugMode: true), rotatingConf])

在此示例中,当每次进行日志记录调用时,都会查询 XcodeLogConfigurationRotatingLogFileConfiguration。 由于 XcodeLogConfiguration 是使用 debugMode: true 声明的,因此它将在 synchronousMode 中运行,而 rotatingConf 将异步运行。

此外,XcodeLogConfiguration 将导致消息通过统一日志系统(如果可用)和/或正在运行的进程的 stdoutstderr 流进行记录。 另一方面,RotatingLogFileConfiguration 导致消息写入文件。

最后,每个配置都会导致使用不同的消息格式。

实现您自己的配置

虽然您可以提供 LogConfiguration 协议的自己的实现,但创建 BasicLogConfiguration 实例并将相关参数传递给 初始化程序可能会更简单。

如果您想进一步封装您的配置,您也可以继承 BasicLogConfiguration

一个复杂的例子

假设您要配置 CleanroomLogger 以

  1. .verbose.debug.info 消息打印到 stdout,同时将 .warning.error 消息定向到 stderr
  2. 如果 OSLog 在运行时平台上可用,则将所有消息镜像到 OSLog
  3. 在路径 /tmp/CleanroomLogger 创建一个轮换的日志文件目录,以存储 .info.warning.error 消息最多 15 天

此外,您希望每个日志条目的格式都不同

  1. 用于 stdoutstderrXcodeLogFormatter
  2. 用于 OSLog 的 ReadableLogFormatter
  3. 用于日志文件的 ParsableLogFormatter

要配置 CleanroomLogger 来执行所有这些操作,您可以编写

var configs = [LogConfiguration]()

// create a recorder for logging to stdout & stderr
// and add a configuration that references it
let stderr = StandardStreamsLogRecorder(formatters: [XcodeLogFormatter()])
configs.append(BasicLogConfiguration(recorders: [stderr]))

// create a recorder for logging via OSLog (if possible)
// and add a configuration that references it
if let osLog = OSLogRecorder(formatters: [ReadableLogFormatter()]) {
	// the OSLogRecorder initializer will fail if running on 
	// a platform that doesn’t support the os_log() function
	configs.append(BasicLogConfiguration(recorders: [osLog]))
}

// create a configuration for a 15-day rotating log directory
let fileCfg = RotatingLogFileConfiguration(minimumSeverity: .info,
												daysToKeep: 15,
											 directoryPath: "/tmp/CleanroomLogger",
												formatters: [ParsableLogFormatter()])

// crash if the log directory doesn’t exist yet & can’t be created
try! fileCfg.createLogDirectory()

configs.append(fileCfg)

// enable logging using the LogRecorders created above
Log.enable(configuration: configs)

自定义日志格式

尝试将 LogEntry 转换为字符串时,会查询 LogFormatter 协议。

CleanroomLogger 附带了几个用于特定目的的高级 LogFormatter 实现

后两个 LogFormatter 都是 StandardLogFormatter 的子类,它提供了一种用于自定义格式化行为的基本机制。

您还可以使用 FieldBasedLogFormatter 轻松组装完全自定义的格式化程序,该格式化程序允许您混合和匹配 Field 以推出自己的格式化程序。

API 文档

有关使用 CleanroomLogger 的详细信息,请参见 API 文档

设计理念

应用程序开发人员应完全控制整个过程的日志记录。 与执行的任何代码一样,日志记录需要付出一定的代价,应用程序开发人员应该决定如何在收集日志的效用与以给定的详细程度收集日志的代价之间进行权衡。

CleanroomLogger 的配置只能在应用程序的生命周期内设置一次;之后,该配置将变为不可变的。 使用 CleanroomLogger 的任何第三方框架都将仅限于应用程序开发人员明确允许的内容。 因此,使用 CleanroomLogger 的嵌入式代码本质上是表现良好的。

我们非常坚信这种理念,以至于我们甚至为从不希望在其应用程序中使用 CleanroomLogger 的开发人员构建了一项功能。 是的,我们创建了一种让开发人员完全避免使用我们的项目的方法。 因此,如果您需要包含使用 CleanroomLogger 的第三方库,但您不想产生任何日志记录开销,只需调用 Log.neverEnable() 而不是 Log.enable()。 CleanroomLogger 将被完全禁用。

尊重调用线程。print()NSLog() 这样的函数可以在调用线程上完成大量工作,并且当从主线程使用时,这可能会导致较低的帧速率和断断续续的滚动。

当 CleanroomLogger 被要求记录某些内容时,它会立即移交给异步后台队列以进行进一步分派,从而使调用线程可以尽快恢复工作。 每个 LogRecorder 还维护其自己的异步后台队列,该队列用于格式化日志消息并将其写入底层存储工具。 这种设计确保如果一个记录器陷入困境,它不会阻止任何其他记录器处理日志消息。

避免不必要的代码执行。 CleanroomLogger 提供的日志记录 API 利用 Swift 短路来避免在已知永远不会记录给定严重性的消息时执行代码。

例如,在以 .info 作为最小 LogSeverity 的生产代码中,严重性为 .verbose.debug 的消息将始终被忽略。 在这种情况下,Log.debugLog.verbose 将为 nil,从而可以有效地对尝试使用这些非活动日志通道的任何代码进行短路。 像 Log.verbose?.trace()Log.debug?.message("正在加载 URL: \(url)") 这样的代码实际上会在运行时变为空操作。 调试日志记录为您的生产版本增加了零开销,因此请不要害羞地利用它。

架构概述

CleanroomLogger 旨在避免在调用线程上执行格式化或日志记录工作,而是利用 Grand Central Dispatch (GCD) 队列进行高效处理。

就执行线程而言,记录任何内容的每个请求都可能经历三个主要处理阶段

  1. 在调用线程上

  2. 调用者尝试通过调用由 Log 维护的相应 LogChannel 的日志记录函数(例如,message()trace()value())来发出日志请求。 - 如果没有给定日志消息严重性LogChannel(因为 CleanroomLogger 尚未 enabled() 或未配置为以该严重性记录日志),Swift 短路将阻止进一步执行。 这使得在发布生产代码时将调试日志记录调用保留在原位成为可能,而不会影响性能。

  3. 如果 LogChannel 确实存在,它将创建一个不可变的 LogEntry 结构来表示要记录的事物

  4. 然后,将 LogEntry 传递给与 LogChannel 关联的 LogReceptacle

  5. 根据 LogEntry 的严重性,LogReceptacle 选择一个或多个 LogConfiguration 来用于记录消息。 除其他事项外,这些配置确定传递到底层 LogReceptacle 的 GCD 队列时,进一步的处理是同步进行还是异步进行。 (同步处理在调试期间很有用,但不建议用于常规生产代码。)

  6. LogReceptacle 队列上

  7. LogEntry 通过零个或多个 LogFilter 传递,这些 LogFilter 有机会阻止进一步处理 LogEntry。 如果任何过滤器指示不应记录 LogEntry,则处理停止。

  8. LogConfiguration 用于确定将使用哪些 LogRecorder(如果有)来记录 LogEntry

  9. 对于配置指定的每个 LogRecorder 实例,LogEntry 然后被分派到 LogRecorder 提供的 GCD 队列。

  10. 在每个 LogRecorder 队列上

  11. LogEntry 会被顺序传递给 LogRecorder 提供的每一个 LogFormatter,以便这些格式化器有机会为 LogEntry 创建格式化的消息。- 如果没有 LogFormatter 返回 LogEntry 的字符串表示,则进一步处理会停止,并且不会记录任何内容。- 如果任何 LogFormatter 返回一个非 nil 值来表示 LogEntry 的格式化消息,则该字符串会被传递给 LogRecorder 以进行最终的日志记录。

关于

Cleanroom 项目最初是一个实验,旨在用一个没有历史包袱、基于 Swift 的版本重新构想 Gilt 的 iOS 代码库。

从那时起,我们将 Cleanroom 项目扩展到包含多平台支持。我们的大部分代码库现在除了支持 iOS 之外,还支持 tvOS,并且我们的底层代码也可以在 macOS 和 watchOS 上使用。

Cleanroom 项目代码是 Gilt on TV 的基础,我们的 tvOS 应用 在 Apple 发布新款 Apple TV 时被 Apple 重点展示。随着时间的推移,我们将用 Cleanroom 实现替换越来越多的现有 Objective-C 代码库。

与此同时,我们将跟踪 Swift 和 Xcode 的最新版本,并一路开源我们代码库的主要部分

贡献

CleanroomLogger 正在积极开发中,我们欢迎您的贡献。

如果您想为此或任何其他 Cleanroom 项目仓库做出贡献,请阅读贡献指南。如果您有任何问题,请联系项目负责人 Paul Lee

致谢

API 文档是使用 Realmjazzy 项目生成的,该项目由 JP SimardSamuel E. Giddins 维护。