|
|
@@ -13,421 +13,10 @@
|
|
|
// to endorse or promote products derived from this software without specific
|
|
|
// prior written permission of Deusty, LLC.
|
|
|
|
|
|
-// swiftlint:disable file_length
|
|
|
-
|
|
|
-#if canImport(Synchronization)
|
|
|
-import Synchronization
|
|
|
-#endif
|
|
|
-@_exported import CocoaLumberjack
|
|
|
+@_exported public import CocoaLumberjack
|
|
|
#if SWIFT_PACKAGE
|
|
|
-import CocoaLumberjackSwiftSupport
|
|
|
-#endif
|
|
|
-
|
|
|
-extension DDLogFlag {
|
|
|
- public static func from(_ logLevel: DDLogLevel) -> DDLogFlag {
|
|
|
- DDLogFlag(rawValue: logLevel.rawValue)
|
|
|
- }
|
|
|
-
|
|
|
- public init(_ logLevel: DDLogLevel) {
|
|
|
- self = DDLogFlag(rawValue: logLevel.rawValue)
|
|
|
- }
|
|
|
-
|
|
|
- /// Returns the log level, or the lowest equivalent.
|
|
|
- public func toLogLevel() -> DDLogLevel {
|
|
|
- if let ourValid = DDLogLevel(rawValue: rawValue) {
|
|
|
- return ourValid
|
|
|
- } else {
|
|
|
- if contains(.verbose) {
|
|
|
- return .verbose
|
|
|
- } else if contains(.debug) {
|
|
|
- return .debug
|
|
|
- } else if contains(.info) {
|
|
|
- return .info
|
|
|
- } else if contains(.warning) {
|
|
|
- return .warning
|
|
|
- } else if contains(.error) {
|
|
|
- return .error
|
|
|
- } else {
|
|
|
- return .off
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#if canImport(Synchronization)
|
|
|
-#if compiler(>=6.0)
|
|
|
-@available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *)
|
|
|
-extension DDLogLevel: @retroactive AtomicRepresentable {}
|
|
|
-#else
|
|
|
-extension DDLogLevel: AtomicRepresentable {}
|
|
|
-#endif
|
|
|
-
|
|
|
-@available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *)
|
|
|
-private let _dynamicLogLevel = Atomic(DDLogLevel.all)
|
|
|
-#endif
|
|
|
-
|
|
|
-private let _dynamicLogLevelLock = NSLock()
|
|
|
-#if swift(>=5.9)
|
|
|
-nonisolated(unsafe) private var _dynamicLogLevelStorage = DDLogLevel.all
|
|
|
-#else
|
|
|
-private var _dynamicLogLevelStorage = DDLogLevel.all
|
|
|
-#endif
|
|
|
-
|
|
|
-private func _readDynamicLogLevel() -> DDLogLevel {
|
|
|
-#if canImport(Synchronization)
|
|
|
- if #available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *) {
|
|
|
- return _dynamicLogLevel.load(ordering: .relaxed)
|
|
|
- }
|
|
|
-#endif
|
|
|
- _dynamicLogLevelLock.lock()
|
|
|
- defer { _dynamicLogLevelLock.unlock() }
|
|
|
- return _dynamicLogLevelStorage
|
|
|
-}
|
|
|
-
|
|
|
-private func _writeDynamicLogLevel(_ newValue: DDLogLevel) {
|
|
|
-#if canImport(Synchronization)
|
|
|
- if #available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *) {
|
|
|
- _dynamicLogLevel.store(newValue, ordering: .relaxed)
|
|
|
- return
|
|
|
- }
|
|
|
-#endif
|
|
|
- _dynamicLogLevelLock.lock()
|
|
|
- defer { _dynamicLogLevelLock.unlock() }
|
|
|
- _dynamicLogLevelStorage = newValue
|
|
|
-}
|
|
|
-
|
|
|
-#if swift(>=5.9)
|
|
|
-/// The log level that can dynamically limit log messages (vs. the static ``DDDefaultLogLevel``). This log level will only be checked, if the message passes the ``DDDefaultLogLevel``.
|
|
|
-public nonisolated(unsafe) var dynamicLogLevel: DDLogLevel {
|
|
|
- get {
|
|
|
- _readDynamicLogLevel()
|
|
|
- }
|
|
|
- set {
|
|
|
- _writeDynamicLogLevel(newValue)
|
|
|
- }
|
|
|
-}
|
|
|
-#else
|
|
|
-/// The log level that can dynamically limit log messages (vs. the static ``DDDefaultLogLevel``). This log level will only be checked, if the message passes the ``DDDefaultLogLevel``.
|
|
|
-public var dynamicLogLevel: DDLogLevel {
|
|
|
- get {
|
|
|
- _readDynamicLogLevel()
|
|
|
- }
|
|
|
- set {
|
|
|
- _writeDynamicLogLevel(newValue)
|
|
|
- }
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
-/// Resets the ``dynamicLogLevel`` to ``DDLogLevel/all``.
|
|
|
-/// - SeeAlso: ``dynamicLogLevel``
|
|
|
-@inlinable
|
|
|
-public func resetDynamicLogLevel() {
|
|
|
- dynamicLogLevel = .all
|
|
|
-}
|
|
|
-
|
|
|
-@available(*, deprecated, message: "Please use dynamicLogLevel", renamed: "dynamicLogLevel")
|
|
|
-public var defaultDebugLevel: DDLogLevel {
|
|
|
- get {
|
|
|
- dynamicLogLevel
|
|
|
- }
|
|
|
- set {
|
|
|
- dynamicLogLevel = newValue
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-@available(*, deprecated, message: "Please use resetDynamicLogLevel", renamed: "resetDynamicLogLevel")
|
|
|
-public func resetDefaultDebugLevel() {
|
|
|
- resetDynamicLogLevel()
|
|
|
-}
|
|
|
-
|
|
|
-#if canImport(Synchronization)
|
|
|
-@available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *)
|
|
|
-private let _asyncLoggingEnabled = Atomic(true)
|
|
|
-#endif
|
|
|
-
|
|
|
-private let _asyncLoggingEnabledLock = NSLock()
|
|
|
-#if swift(>=5.9)
|
|
|
-nonisolated(unsafe) private var _asyncLoggingEnabledStorage = true
|
|
|
-#else
|
|
|
-private var _asyncLoggingEnabledStorage = true
|
|
|
-#endif
|
|
|
-
|
|
|
-private func _readAsyncLoggingEnabled() -> Bool {
|
|
|
-#if canImport(Synchronization)
|
|
|
- if #available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *) {
|
|
|
- return _asyncLoggingEnabled.load(ordering: .relaxed)
|
|
|
- }
|
|
|
-#endif
|
|
|
- _asyncLoggingEnabledLock.lock()
|
|
|
- defer { _asyncLoggingEnabledLock.unlock() }
|
|
|
- return _asyncLoggingEnabledStorage
|
|
|
-}
|
|
|
-
|
|
|
-private func _writeAsyncLoggingEnabled(_ newValue: Bool) {
|
|
|
-#if canImport(Synchronization)
|
|
|
- if #available(macOS 15, iOS 18, tvOS 18, watchOS 11, visionOS 2, *) {
|
|
|
- _asyncLoggingEnabled.store(newValue, ordering: .relaxed)
|
|
|
- return
|
|
|
- }
|
|
|
-#endif
|
|
|
- _asyncLoggingEnabledLock.lock()
|
|
|
- defer { _asyncLoggingEnabledLock.unlock() }
|
|
|
- _asyncLoggingEnabledStorage = newValue
|
|
|
-}
|
|
|
-
|
|
|
-#if swift(>=5.9)
|
|
|
-/// If `true`, all logs (except errors) are logged asynchronously by default.
|
|
|
-public nonisolated(unsafe) var asyncLoggingEnabled: Bool {
|
|
|
- get {
|
|
|
- _readAsyncLoggingEnabled()
|
|
|
- }
|
|
|
- set {
|
|
|
- _writeAsyncLoggingEnabled(newValue)
|
|
|
- }
|
|
|
-}
|
|
|
-#else
|
|
|
-/// If `true`, all logs (except errors) are logged asynchronously by default.
|
|
|
-public var asyncLoggingEnabled: Bool {
|
|
|
- get {
|
|
|
- _readAsyncLoggingEnabled()
|
|
|
- }
|
|
|
- set {
|
|
|
- _writeAsyncLoggingEnabled(newValue)
|
|
|
- }
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
-@frozen
|
|
|
-public struct DDLogMessageFormat: ExpressibleByStringInterpolation {
|
|
|
- public typealias StringLiteralType = String
|
|
|
-
|
|
|
- @usableFromInline
|
|
|
- struct Storage {
|
|
|
-#if swift(>=5.6)
|
|
|
- @usableFromInline
|
|
|
- typealias VArg = any CVarArg
|
|
|
-#else
|
|
|
- @usableFromInline
|
|
|
- typealias VArg = CVarArg
|
|
|
+public import CocoaLumberjackSwiftSupport
|
|
|
#endif
|
|
|
- @usableFromInline
|
|
|
- let requiresArgumentParsing: Bool
|
|
|
- @usableFromInline
|
|
|
- var format: String
|
|
|
- @usableFromInline
|
|
|
- var args: Array<VArg> {
|
|
|
- willSet {
|
|
|
- // We only assert here to let the compiler optimize it away.
|
|
|
- // The setter will be used repeatedly during string interpolation, thus should stay fast.
|
|
|
- assert(requiresArgumentParsing || newValue.isEmpty, "Non-empty arguments always require argument parsing!")
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @usableFromInline
|
|
|
- init(requiresArgumentParsing: Bool, format: String, args: Array<VArg>) {
|
|
|
- precondition(requiresArgumentParsing || args.isEmpty, "Non-empty arguments always require argument parsing!")
|
|
|
- self.requiresArgumentParsing = requiresArgumentParsing
|
|
|
- self.format = format
|
|
|
- self.args = args
|
|
|
- }
|
|
|
-
|
|
|
- @available(*, deprecated, message: "Use initializer specifying the need for argument parsing: init(requiresArgumentParsing:format:args:)")
|
|
|
- @usableFromInline
|
|
|
- init(format: String, args: Array<VArg>) {
|
|
|
- self.init(requiresArgumentParsing: !args.isEmpty, format: format, args: args)
|
|
|
- }
|
|
|
-
|
|
|
- @usableFromInline
|
|
|
- mutating func addString(_ string: String) {
|
|
|
- format.append(string.replacingOccurrences(of: "%", with: "%%"))
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- mutating func addValue(_ arg: VArg, withSpecifier specifier: String) {
|
|
|
- format.append(specifier)
|
|
|
- args.append(arg)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @frozen
|
|
|
- public struct StringInterpolation: StringInterpolationProtocol {
|
|
|
- @usableFromInline
|
|
|
- var storage: Storage
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public init(literalCapacity: Int, interpolationCount: Int) {
|
|
|
- var format = String()
|
|
|
- format.reserveCapacity(literalCapacity)
|
|
|
- var args = Array<Storage.VArg>()
|
|
|
- args.reserveCapacity(interpolationCount)
|
|
|
- storage = .init(requiresArgumentParsing: true, format: format, args: args)
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendLiteral(_ literal: StringLiteralType) {
|
|
|
- storage.addString(literal)
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation<S: StringProtocol>(_ string: S) {
|
|
|
- storage.addValue(String(string), withSpecifier: "%@")
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation(_ int: Int8) {
|
|
|
- storage.addValue(int, withSpecifier: "%c")
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation(_ int: UInt8) {
|
|
|
- storage.addValue(int, withSpecifier: "%c")
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation(_ int: Int16) {
|
|
|
- storage.addValue(int, withSpecifier: "%i")
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation(_ int: UInt16) {
|
|
|
- storage.addValue(int, withSpecifier: "%u")
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation(_ int: Int32) {
|
|
|
- storage.addValue(int, withSpecifier: "%li")
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation(_ int: UInt32) {
|
|
|
- storage.addValue(int, withSpecifier: "%lu")
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation(_ int: Int64) {
|
|
|
- storage.addValue(int, withSpecifier: "%lli")
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation(_ int: UInt64) {
|
|
|
- storage.addValue(int, withSpecifier: "%llu")
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation(_ int: Int) {
|
|
|
-#if arch(arm64) || arch(x86_64)
|
|
|
- storage.addValue(int, withSpecifier: "%lli")
|
|
|
-#else
|
|
|
- storage.addValue(int, withSpecifier: "%li")
|
|
|
-#endif
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation(_ int: UInt) {
|
|
|
-#if arch(arm64) || arch(x86_64)
|
|
|
- storage.addValue(int, withSpecifier: "%llu")
|
|
|
-#else
|
|
|
- storage.addValue(int, withSpecifier: "%lu")
|
|
|
-#endif
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation(_ flt: Float) {
|
|
|
- storage.addValue(flt, withSpecifier: "%f")
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation(_ dbl: Double) {
|
|
|
- storage.addValue(dbl, withSpecifier: "%lf")
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation(_ bool: Bool) {
|
|
|
- storage.addValue(bool, withSpecifier: "%i") // bools are printed as ints
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation<Convertible: ReferenceConvertible>(_ convertible: Convertible) {
|
|
|
- if convertible is Storage.VArg {
|
|
|
- print("""
|
|
|
- [WARNING]: CocoaLumberjackSwift is creating a \(DDLogMessageFormat.self) with an interpolation conforming to `CVarArg` \
|
|
|
- using the overload for `ReferenceConvertible` interpolations!
|
|
|
- Please report this as a bug, including the following snippet:
|
|
|
- ```
|
|
|
- Convertible: \(Convertible.self), ReferenceType: \(Convertible.ReferenceType.self), type(of: convertible): \(type(of: convertible))
|
|
|
- ```
|
|
|
- """)
|
|
|
- }
|
|
|
- // This should be safe, sine the compiler should convert it to the reference.
|
|
|
- // swiftlint:disable:next force_cast
|
|
|
- storage.addValue(convertible as? Storage.VArg ?? convertible as! Convertible.ReferenceType, withSpecifier: "%@")
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public mutating func appendInterpolation<Obj: NSObject>(_ object: Obj) {
|
|
|
- storage.addValue(object, withSpecifier: "%@")
|
|
|
- }
|
|
|
-
|
|
|
- @_disfavoredOverload
|
|
|
- public mutating func appendInterpolation(_ any: Any) {
|
|
|
- appendInterpolation(String(describing: any))
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @usableFromInline
|
|
|
- let storage: Storage
|
|
|
-
|
|
|
- @inlinable
|
|
|
- var format: String { storage.format }
|
|
|
- @inlinable
|
|
|
- var args: Array<Storage.VArg> { storage.args }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- var formatted: String {
|
|
|
- guard storage.requiresArgumentParsing else { return storage.format }
|
|
|
- return String(format: storage.format, arguments: storage.args)
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public init(stringLiteral value: StringLiteralType) {
|
|
|
- storage = .init(requiresArgumentParsing: false, format: value, args: [])
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- public init(stringInterpolation: StringInterpolation) {
|
|
|
- storage = stringInterpolation.storage
|
|
|
- }
|
|
|
-
|
|
|
- @inlinable
|
|
|
- internal init(_formattedMessage: String) {
|
|
|
- storage = .init(requiresArgumentParsing: false, format: _formattedMessage, args: [])
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-extension DDLogMessage {
|
|
|
- @inlinable
|
|
|
- public convenience init(_ format: DDLogMessageFormat,
|
|
|
- level: DDLogLevel,
|
|
|
- flag: DDLogFlag,
|
|
|
- context: Int = 0,
|
|
|
- file: StaticString = #file,
|
|
|
- function: StaticString = #function,
|
|
|
- line: UInt = #line,
|
|
|
- tag: Any? = nil,
|
|
|
- timestamp: Date? = nil) {
|
|
|
- self.init(format: format.format,
|
|
|
- formatted: format.formatted,
|
|
|
- level: level,
|
|
|
- flag: flag,
|
|
|
- context: context,
|
|
|
- file: String(describing: file),
|
|
|
- function: String(describing: function),
|
|
|
- line: line,
|
|
|
- tag: tag,
|
|
|
- options: [.dontCopyMessage],
|
|
|
- timestamp: timestamp)
|
|
|
- }
|
|
|
-}
|
|
|
|
|
|
@inlinable
|
|
|
public func _DDLogMessage(_ messageFormat: @autoclosure () -> DDLogMessageFormat,
|
|
|
@@ -711,26 +300,3 @@ public func DDLogError(_ message: @autoclosure () -> Any,
|
|
|
asynchronous: async ?? false,
|
|
|
ddlog: ddlog)
|
|
|
}
|
|
|
-
|
|
|
-/// Returns a String of the current filename, without full path or extension.
|
|
|
-/// Analogous to the C preprocessor macro `THIS_FILE`.
|
|
|
-public func currentFileName(_ fileName: StaticString = #file) -> String {
|
|
|
- var str = String(describing: fileName)
|
|
|
- if let idx = str.range(of: "/", options: .backwards)?.upperBound {
|
|
|
- str = String(str[idx...])
|
|
|
- }
|
|
|
- if let idx = str.range(of: ".", options: .backwards)?.lowerBound {
|
|
|
- str = String(str[..<idx])
|
|
|
- }
|
|
|
- return str
|
|
|
-}
|
|
|
-
|
|
|
-// swiftlint:disable identifier_name
|
|
|
-// swiftlint doesn't like func names that begin with a capital letter - deprecated
|
|
|
-@available(*, deprecated, message: "Please use currentFileName", renamed: "currentFileName")
|
|
|
-public func CurrentFileName(_ fileName: StaticString = #file) -> String {
|
|
|
- currentFileName(fileName)
|
|
|
-}
|
|
|
-// swiftlint:enable identifier_name
|
|
|
-
|
|
|
-// swiftlint:enable file_length
|