首先,这是一个社区驱动的开源项目的开始,该项目积极寻求贡献,无论是代码、文档还是想法。除了对SwiftLog
本身做出贡献之外,目前还存在另一个巨大的差距: SwiftLog
是一个API 包,它试图建立一个生态系统可以使用的通用 API。为了使日志记录真正适用于现实世界的工作负载,我们需要与SwiftLog
兼容的日志记录后端,然后将日志消息保留在文件中,在终端上以更好的颜色呈现它们,或者将它们发送到 Splunk 或 ELK。
SwiftLog
今天提供的内容可以在 API 文档中找到。
如果您有一个服务器端 Swift 应用程序,或者可能是一个跨平台(例如 Linux 和 macOS)应用程序/库,并且您想要记录日志,我们认为针对此日志记录 API 包是一个好主意。您将在下面找到入门所需的所有信息。
SwiftLog
是为 Swift 5.8 及更高版本设计的。要依赖日志记录 API 包,您需要在Package.swift
中声明您的依赖项:
. package ( url : " https://github.com/apple/swift-log.git " , from : " 1.0.0 " ) ,
并在您的应用程序/库目标中,将"Logging"
添加到您的dependencies
中,例如如下所示:
. target ( name : " BestExampleApp " , dependencies : [
. product ( name : " Logging " , package : " swift-log " )
] ,
// 1) let's import the logging API package
import Logging
// 2) we need to create a logger, the label works similarly to a DispatchQueue label
let logger = Logger ( label : " com.example.BestExampleApp.main " )
// 3) we're now ready to use it
logger . info ( " Hello World! " )
2019-03-13T15:46:38+0000 info: Hello World!
Logger
行为SwiftLog
通过StreamLogHandler
提供非常基本的开箱即用的控制台日志记录。可以将默认输出切换到stderr
如下所示:
LoggingSystem . bootstrap ( StreamLogHandler . standardError )
StreamLogHandler
主要只是为了方便,不提供任何实质性的定制。旨在构建自己的日志记录后端以进行集成和使用的库维护者应该直接实现LogHandler
协议,如“日志记录后端的实现”部分中所述。
如需了解更多信息,请查看 API 文档。
您可以选择以下后端之一来使用您的日志。如果您有兴趣实施,请参阅下面的“实施注意事项”部分,解释如何实施。现有 SwiftLog API 兼容库列表:
存储库 | 处理程序描述 |
---|---|
Kitura/氦记录器 | Kitura 生态系统中广泛使用的日志记录后端 |
ianpartridge/swift-log-系统日志 | 系统日志后端 |
Adorkable/swift-log-格式和管道 | 允许自定义输出格式和结果目的地的后端 |
chrisaljoudi/swift-log- oslog | 用于 Apple 平台的 OSLog 统一日志记录后端。重要提示:我们建议直接使用 os_log,如此处所述。使用此后端通过 swift-log 使用 os_log 效率会较低,并且还会阻止指定消息的隐私。后端始终使用%{public}@ 作为格式字符串,并急切地将所有字符串插值转换为字符串。这有两个缺点: 1.字符串插值的静态组件会被统一日志系统急切地复制,这将导致性能损失。 2.它使所有消息公开,这改变了os_log的默认隐私策略,并且不允许指定消息部分的细粒度隐私。在一项正在进行的单独工作中,正在改进 os_log 的 Swift API,使其与 swift-log API 紧密结合。参考文献:统一日志记录级别,使 os_log 使用编译时解释接受字符串插值。 |
Brainfinance/StackdriverLogging | 结构化 JSON 日志记录后端,可通过 Stackdriver 日志代理在 Google Cloud Platform 上使用 |
DnV1eX/GoogleCloudLogging | 一个客户端库,用于通过 REST API v2 记录 Google Cloud 中的应用程序事件。 |
蒸汽/控制台套件 | 当前终端或标准输出的记录器,具有风格化 (ANSI) 输出。所有 Vapor 应用程序的默认记录器 |
尼尔斯特/swift-log-测试 | 提供对日志消息的访问以在断言中使用(在测试目标内) |
wlisac/swift-log-slack | 向 Slack 发送关键日志消息的日志记录后端 |
NSHipster/swift-log-github-actions | 将日志记录消息转换为 GitHub Actions 的工作流命令的日志记录后端。 |
stevapple/swift-log-电报 | 将日志消息发送到任何 Telegram 聊天的日志记录后端(受 wlisac/swift-log-slack 启发并派生) |
jagreenwood/swift-log-datadog | 将日志消息发送到 Datadog 日志管理服务的日志记录后端 |
谷歌/SwiftLogFireCloud | 用于时间序列日志记录的日志记录后端,它将日志作为平面文件推送到 Firebase Cloud Storage。 |
crspybits/swift-日志文件 | 一个简单的本地文件记录器(使用Foundation FileManager ) |
寿司排/小狗 | 支持多种传输(控制台、文件、系统日志等)并具有格式化和文件日志轮换功能的日志记录后端 |
ShivaHuang/swift-log-SwiftyBeaver | 日志记录后端,用于将彩色日志记录打印到 Xcode 控制台/文件,或将加密日志记录发送到 SwiftyBeaver 平台。 |
Apodini/斯威夫特-日志-麋鹿 | 日志记录后端,用于格式化、缓存日志数据并将其发送到 elastic/logstash |
二进制抓取/swift-log-supabase | 将日志条目发送到 Supabase 的日志记录后端。 |
kiliankoe/swift-log-矩阵 | 用于将日志直接发送到 Matrix room 的日志记录后端 |
DiscordBM/DiscordLogger | 一个 Discord 日志记录实现,以美观的方式将日志发送到 Discord 通道,并具有许多配置选项,包括仅发送一些重要日志级别的能力,例如warning / error / critical 。 |
可可伐木工 | 一个适用于 macOS、iOS、tvOS 和 watchOS 的快速、简单、强大且灵活的日志记录框架,其中包括 swift-log 的日志记录后端。 |
rwbutler/swift-log-ecs | 用于以 ECS 日志格式进行日志记录的日志记录后端。与 Vapor 兼容并允许链接多个 LogHandler。 |
ShipBook/swift-log -shipbook | 将日志条目发送到 Shipbook 的日志记录后端 - Shipbook 使您能够基于每个用户和会话远程收集、搜索和分析云中的用户日志和异常情况。 |
你的图书馆? | 联系我们! |
很高兴你问了。我们相信,对于 Swift on Server 生态系统来说,拥有一个任何人都可以采用的日志 API 至关重要,这样来自不同方的众多库都可以登录到共享目的地。更具体地说,这意味着我们相信来自所有库的所有日志消息最终都会存储在同一个文件、数据库、Elastic Stack/Splunk 实例或您可能选择的任何内容中。
然而,在现实世界中,对于日志系统应该如何运行、日志消息应该采用什么样的格式以及应该在哪里/如何持久保存有很多意见。我们认为等待一个日志记录包来支持特定部署所需的一切,同时仍然足够容易使用并保持性能是不可行的。这就是为什么我们决定将问题减半:
该包仅提供日志记录 API 本身,因此SwiftLog
是一个“日志记录 API 包”。 SwiftLog
(使用LoggingSystem.bootstrap
)可以配置为选择任何兼容的日志记录后端实现。这样,包就可以采用 API,并且应用程序可以选择任何兼容的日志记录后端实现,而不需要对任何库进行任何更改。
只是为了完整性:这个 API 包实际上包含一个过于简单且不可配置的日志后端实现,它只是将所有日志消息写入stdout
。包含这种过于简单的日志记录后端实现的原因是为了改善首次使用体验。假设您启动一个项目并第一次尝试SwiftLog
,看到您记录的内容以简单的格式出现在stdout
上比什么也没发生要好得多。对于任何实际应用程序,我们建议配置另一个日志记录后端实现,以您喜欢的方式进行日志记录。
Logger
用于发出日志消息,因此是SwiftLog
中最重要的类型,因此它们的使用应该尽可能简单。最常见的是,它们用于发出特定日志级别的日志消息。例如:
// logging an informational message
logger . info ( " Hello World! " )
// ouch, something went wrong
logger . error ( " Houston, we have a problem: ( problem ) " )
支持以下日志级别:
trace
debug
info
notice
warning
error
critical
可以更改给定记录器的日志级别,但更改只会影响您更改它的特定记录器。你可以说Logger
是一个关于日志级别的值类型。
记录元数据是可以附加到记录器以添加调试问题时至关重要的信息的元数据。在服务器中,通常的示例是将请求 UUID 附加到记录器,然后该记录器将出现在使用该记录器记录的所有日志消息中。例子:
var logger = logger
logger [ metadataKey : " request-uuid " ] = " ( UUID ( ) ) "
logger . info ( " hello world " )
将打印
2019-03-13T18:30:02+0000 info: request-uuid=F8633013-3DD8-481C-9256-B296E43443ED hello world
使用SwiftLog
附带的默认日志记录后端实现。不用说,格式完全由您选择的日志记录后端定义。
LogHandler
)的实现注意:如果您不想实现自定义日志记录后端,本节中的所有内容可能不太相关,因此请随意跳过。
要成为所有SwiftLog
消费者都可以使用的兼容日志记录后端,您需要做两件事:1) 实现一个实现LogHandler
( SwiftLog
提供的协议)的类型(通常是struct
),2) 指示SwiftLog
使用您的日志记录后端实现。
LogHandler
或日志记录后端实现是符合以下协议的任何内容
public protocol LogHandler {
func log ( level : Logger . Level , message : Logger . Message , metadata : Logger . Metadata ? , source : String , file : String , function : String , line : UInt )
subscript ( metadataKey _ : String ) -> Logger . Metadata . Value ? { get set }
var metadata : Logger . Metadata { get set }
var logLevel : Logger . Level { get set }
}
指示SwiftLog
使用您的日志记录后端作为整个应用程序(包括所有库)应该使用的后端非常简单:
LoggingSystem . bootstrap ( MyLogHandler . init )
LogHandler
控制日志系统的大部分部分:
LogHandler
的控制下LogHandler
控制Logger
配置的两个关键部分,即:
logger.logLevel
属性)logger[metadataKey:]
和logger.metadata
)然而,为了使系统正常工作, LogHandler
将配置视为值类型非常重要。这意味着LogHandler
应该是struct
,并且日志级别或日志记录元数据的更改应该只影响它所更改的LogHandler
。
但是,在特殊情况下, LogHandler
提供一些可能影响创建的所有LogHandler
全局日志级别覆盖是可以接受的。
LogHandler
的控制LogHandler
不控制是否应记录消息。仅当Logger
确定应在给定配置的日志级别的情况下发出日志消息时, Logger
才会调用LogHandler
的log
函数。
Logger
带有(不可变的) label
,每条日志消息都带有source
参数(自 SwiftLog 1.3.0 起)。 Logger
的标签标识了Logger
的创建者。如果您通过跨多个模块保留元数据来使用结构化日志记录,则Logger
的label
不是识别日志消息来源的好方法,因为它标识了Logger
的创建者,该创建者通常在库之间传递以保留元数据和之类的。
如果要过滤源自某个子系统的所有日志消息,请按source
进行过滤,默认为发出日志消息的模块。
SwiftLog 的安全流程请参见 SECURITY.md。
此日志记录 API 是与 Swift on Server 社区的贡献者共同设计的,并经 SSWG(Swift 服务器工作组)批准进入 SSWG 孵化过程的“沙箱级别”。