如何从 Swift 在 CocoaLumberJack 中实现自定义日志级别?

How to implement Custom Log Levels in CocoaLumberJack from Swift?

提问人:nhgrif 提问时间:8/20/2021 更新时间:8/26/2021 访问量:442

问:

我正在将 CocoaLumberjack 用于 Swift 项目。我想实现自定义日志级别/标志,因为我想使用 6 而不是默认的 5,并且更喜欢不同的名称。

执行此操作的文档没有帮助。它只是 Objective-C 的一个解决方案。

DDLogFlag 被定义为 NS_OPTIONS 这一事实意味着我实际上可以简单地忽略此处的预定义值,创建我自己的常量,然后编写一些包装代码以从一个常量转换为另一个常量。

但是,DDLogLevel 被定义为 NS_ENUM,这意味着 Swift 不会对我尝试实例化要说的东西感到非常满意,这不是枚举中的现有值。如果它是 ,就像 ,我可以忽略库中预先存在的定义,并使用我想要的任何有效值。0b111111NS_OPTIONSDDLogFlagUInt

据我所知,我只需要编写一些 Objective-C 代码来定义我自己的替换 ,并编写一个自定义函数来将其传递给并访问 上的这些属性。但这感觉很糟糕。DDLogLevelDDLogFlagDDLogMessage

如何在 Swift 中将我自己的自定义日志记录级别与 CocoaLumberjack 一起使用?

斯威夫特 ·科克鲁姆伯杰克

答:

2赞 Florian Friedrich 8/26/2021 #1

这确实目前只在 Objective-C 中实现 - 而且也仅适用于 Log 宏。即便如此,我也可以想象“现代”ObjC 编译器会警告传递给 .#defineDDLogMessage

这里的文档确实有点过时了,并且源于 Objective-C 更接近 C 的时代,而不是现在的 Swift...... :-)

尽管如此,最终 和 都存储为 .这意味着理论它可以取任何值(也就是在 Swift 中)。DDLogLevelDDLogFlagNSUIntegerNSUIntegerUInt

要定义自己的级别,只需创建一个,然后编写自己的日志记录函数。 这些函数实际上可以转发到现有函数:enum MyLogLevel: UInt { /*...*/ }

extension DDLogFlag {
   public static let fatal = DDLogFlag(rawValue: 0x0001)
   public static let failure = DDLogFlag(rawValue: 0x0010)
}

public enum MyLogLevel: UInt {
    case fatal = 0x0001
    case failure = 0x0011
}

extension MyLogLevel {
    public static var defaultLevel: MyLogLevel = .fatal
}

@inlinable
public func LogFatal(_ message: @autoclosure () -> Any,
                       level: MyLogLevel = .defaultLevel,
                       context: Int = 0,
                       file: StaticString = #file,
                       function: StaticString = #function,
                       line: UInt = #line,
                       tag: Any? = nil,
                       asynchronous async: Bool = asyncLoggingEnabled,
                       ddlog: DDLog = .sharedInstance) {
    _DDLogMessage(message(), level: unsafeBitCast(level, to: DDLogLevel.self), flag: .fatal, context: context, file: file, function: function, line: line, tag: tag, asynchronous: async, ddlog: ddlog)
}

这里有效,因为最终它只是一个并且不会切换关卡,而是对 .unsafeBitCastUInt_DDLogMessageflag


免責聲明:我自己是 CocoaLumberjack 的维护者。


我们不建议在 Swift 中使用自定义日志级别。它没有太大的好处,像 swift-log 这样的日志框架也使用预定义的日志级别

但是,我个人也可以想象用 而不是 .OSLog Swift 覆盖层还使用可扩展的 OSLogType。 如果这是您希望看到的内容,请打开一个 PR,以便我们与团队讨论。我们需要对 API 兼容性有点小心,但就像我说的,这是完全可行的。DDLogLevelNS_OPTIONSNS_ENUM

顺便说一句:请问您需要自定义关卡做什么?

评论

0赞 nhgrif 8/27/2021
我将为 -> for 打开一个 PR,并将该 PR 用作讨论我的需求的起点。从机械上讲,这是允许我更轻松地拥有自己的自定义日志级别所需的最小更改,但我不知道这是否是 CocoaLumberjack 可以满足我需求的最佳整体更改。GitHub PR 是来回讨论的更好位置。NS_ENUMNS_OPTIONSDDLogLevel