Beacon 与传统的日志记录系统不同之处在于,它处理任意值,而不仅仅是字符串,并且摒弃了严重性级别,而采用基于类型的过滤。
此框架提供了将任何类型的值记录到控制台、文件或远程服务所需的一切。它还提供了对缓冲和基于流的日志记录的更广泛支持,从而可以轻松实现自定义日志记录工具。
更多信息
使用 Beacon 进行日志记录是启动记录器并发出值的问题。
let consoleLogger = ConsoleLogger.starting(name: "Console")
emit("A message")
以上等同于在控制台中打印带时间戳的消息,类似于传统的日志记录系统。但是,您不仅限于发出字符串 - 可以发出任何类型的值
do {
let result: MyThing = try something()
emit(result)
} catch {
emit(error: error)
}
无需指定调试级别 - 只需发出感兴趣的值即可。 Beacon 允许您通过过滤器和约束来控制记录的内容和位置。
⓪ let memoryLogger = MemoryLogger(name: "Memory")
① let consoleLogger = ConsoleLogger.starting(name: "Console") {
② $0 is StringSignal
}
③ Constraint.activate {
-Signal.self
+ErrorSignal.self ~> memoryLogger
}
④ emit()
do {
⑤ memoryLogger.run {
let result = try something()
⑥ emit(result, on: [.shared], userInfo: ["detail": "Detail info"])
}
}
catch {
⑦ emit(error: error)
}
⑧ consoleLogger.stop()
⑨ Constraint.enableAllSignals()
⓪ 创建一个 MemoryLogger
实例。此记录器只是将信号捕获到数组中,可通过 recordings
属性获得。请注意,此记录器尚未运行。
① 创建并启动 ConsoleLogger
。此记录器只是将发出值的带时间戳的 debugDescription
打印到控制台,类似于传统系统记录消息的方式。 与 ⓪ 中创建的内存记录器相比 - 此记录器正在运行并将处理发出的信号。 有关可用记录器的列表,请参见 组件。
② 控制台记录器设置为过滤掉不是 StringSignal
的任何内容 - 这就是当我们调用 emit("with a string")
时实际记录的内容。 不同的值类型由不同类型的信号表示,回退到 WrapperSignal
以捕获任意值。 信号可以轻松扩展以适应特定类型的值,并且是 可移植的。 有关可用信号的列表,请参见 组件。
③ 通过定义约束来控制信号流。 第一个约束禁用所有类型信号的日志记录。 第二个约束启用 ErrorSignal
的日志记录,但仅由 memoryLogger
进行。 效果是仅记录 ErrorSignal
,并且仅由 memoryLogger
记录。 默认情况下,所有类型的信号都是记录器,这等同于 +Signal.self
作为唯一的约束。 有关约束的更多信息,请参见 过滤。
④ 调用没有值的 emit()
会记录执行上下文,捕获导致调用的堆栈跟踪。 这是通过创建和发出 ContextSignal
来实现的。 此外,Beacon 提供了专用信号来捕获 符号化那些堆栈跟踪 所需的信息。
⑤ 可以执行一次性日志记录 - 即,仅在块闭包的持续时间内启动记录器。
⑥ 每种形式的 emit()
都有两个额外的可选参数:要在其上发出信号的 Beacon
列表(默认为 Beacon.shared
)和任意 userInfo 值。
⑦ 发出一个 ErrorSignal
,包装错误。 请注意,此 emit()
变体具有命名参数。 emit(anError)
(将发出 WrapperSignal
)和 emit(error: anError)
(将发出 ErrorSignal
)之间存在差异。
⑧ 由于我们在 ① 中启动了控制台记录器,因此我们应该在使用完毕后停止它。
⑨ 将约束恢复为其默认值。
该框架提供以下构建块
信号 | 描述 |
---|---|
ContextSignal |
在初始化站点捕获执行上下文 - 例如,包含方法的名称和堆栈跟踪 |
ErrorSignal |
捕获错误以及导致错误的堆栈跟踪 |
StringSignal |
捕获字符串 - 类似于传统的日志记录系统 |
WrapperSignal |
捕获任意值 - 请注意变异值,因为某些日志记录工具可能会在稍后的时间记录 |
IdentitySignal |
捕获有关 Beacon 本身的信息 - 例如版本、当前平台、体系结构等 |
MachImageImportsSignal |
捕获 MachO 映像的添加和删除 - 这主要是为了帮助进行堆栈符号化 |
自定义信号通常实现为 WrapperSignal
的子类,因为它在基本 Signal
类的基础上提供了一些有用的机制。
记录器 | 描述 |
---|---|
MemoryLogger |
将信号记录到固定大小的数组中 |
ConsoleLogger |
将信号打印到控制台 |
JRPCLogger |
将信号发送到 JSON-RPC 服务器(有关 Pharo 中的服务器实现,请参见 Beacon-Server) |
FileLogger |
将信号记录到文件,具有轮换支持 |
此外,还有一些抽象记录器
StreamLogger
在任意 OutputStream
上写出信号(例如 FileLogger
)IntervalLogger
提供缓冲接口以写出信号(例如 JRPCLogger
)一些信号,即 ErrorSignal
和 ContextSignal
,捕获导致信号发出的堆栈跟踪。 在某些情况下,二进制文件可能会被剥离其符号,并且需要对这些堆栈跟踪进行符号化才能理解它们。 为了帮助实现这一点,Beacon 使用两个特殊信号:IdentitySignal
和 MachImageImportsSignal
。 前者捕获当前运行环境 - 操作系统和处理器体系结构,而后者捕获 MachO 映像的插入和删除。 凭借二进制文件及其依赖项的体系结构和加载地址,可以使用 atos
之类的工具对这些堆栈跟踪进行符号化。
可以配置记录器以发出这些信号
let consoleLogger = ConsoleLogger(name: "Console")
// Will emit IdentitySignal when started
consoleLogger.identifiesOnStart = true
// Will emit MachImageImportsSignal for all loaded MachO images when started
// and then track subsequently loaded and unloaded images
consoleLogger.tracksMachImageImports = true
consoleLogger.start()
该框架同时支持 Swift 和 Objective-C。 但是,两者之间存在一些特定于语言的差异。 在 Objective-C 中发出信号时,为了方便起见,定义了以下宏
// emit context signal
BeaconEmit(beacons, userInfo);
// emit value
BeaconEmit(someObject, beacons, userInfo);
// emit error
BeaconEmitError(someError, beacons, userInfo);
beacons
参数需要 NSArray<Beacon*>*
或 nil,这意味着共享的 beacon 对象。
当需要发出自定义信号时,您必须提供自己的宏或使用此流程
MySignal *signal = [MySignal new];
BeaconEmitSignal(signal, on: arrayOfBeacons, userInfo: aUserInfoDictionary)
您可以在此处找到一个代码片段,以简化自定义信号的创建。 如果您喜欢这种事情,请将其添加到您现有的 Xcode 代码段集合中...