Skip to content

Instantly share code, notes, and snippets.

@smosko
Last active December 26, 2022 07:54
Show Gist options
  • Save smosko/6b8c161a7ae092e7b72e891a5050deaa to your computer and use it in GitHub Desktop.
Save smosko/6b8c161a7ae092e7b72e891a5050deaa to your computer and use it in GitHub Desktop.
Unified Logging Wrapper
import Foundation
@_exported import os.log
public extension OSLog {
convenience init(_ bundle: Bundle = .main, category: String? = nil) {
self.init(subsystem: bundle.bundleIdentifier ?? "default", category: category ?? "default")
}
convenience init(_ aClass: AnyClass, category: String? = nil) {
self.init(Bundle(for: aClass), category: category ?? String(describing: aClass))
}
@inlinable func log(_ message: StaticString, _ args: CVarArg...) {
log(message, type: .default, args)
}
@inlinable func info(_ message: StaticString, _ args: CVarArg...) {
log(message, type: .info, args)
}
@inlinable func debug(_ message: StaticString, _ args: CVarArg...) {
log(message, type: .debug, args)
}
@inlinable func error(_ message: StaticString, _ args: CVarArg...) {
log(message, type: .error, args)
}
@inlinable func fault(_ message: StaticString, _ args: CVarArg...) {
log(message, type: .fault, args)
}
func print(_ value: @autoclosure () -> Any) {
guard isEnabled(type: .debug) else { return }
os_log("%{public}@", log: self, type: .debug, String(describing: value()))
}
func dump(_ value: @autoclosure () -> Any) {
guard isEnabled(type: .debug) else { return }
var string = String()
Swift.dump(value(), to: &string)
os_log("%{public}@", log: self, type: .debug, string)
}
func trace(file: StaticString = #file, function: StaticString = #function, line: UInt = #line) {
guard isEnabled(type: .debug) else { return }
let file = URL(fileURLWithPath: String(describing: file)).deletingPathExtension().lastPathComponent
var function = String(describing: function)
function.removeSubrange(function.firstIndex(of: "(")!...function.lastIndex(of: ")")!)
os_log("%{public}@.%{public}@():%ld", log: self, type: .debug, file, function, line)
}
@usableFromInline internal func log(_ message: StaticString, type: OSLogType, _ a: [CVarArg]) {
// The Swift overlay of os_log prevents from accepting an unbounded number of args
// http://www.openradar.me/33203955
assert(a.count <= 5)
switch a.count {
case 5: os_log(message, log: self, type: type, a[0], a[1], a[2], a[3], a[4])
case 4: os_log(message, log: self, type: type, a[0], a[1], a[2], a[3])
case 3: os_log(message, log: self, type: type, a[0], a[1], a[2])
case 2: os_log(message, log: self, type: type, a[0], a[1])
case 1: os_log(message, log: self, type: type, a[0])
default: os_log(message, log: self, type: type)
}
}
}
import UIKit
final class SampleViewController: UIViewController {
// initialize with bundle identifier of the current class and optional category
private let log = OSLog(SampleViewController.self, category: "UI")
override func viewDidLoad() {
super.viewDidLoad()
// log messages using different levels
log.log("default")
log.info("info")
log.debug("debug")
log.error("error")
log.fault("fault")
// trace source location
log.trace()
// print object description
log.print(view)
// dump any object
log.dump(view)
}
}