Swift SwiftLog、Extension追加、欲しいログ機能にしてみる

SwiftLogとは

https://github.com/apple/swift-log

Home Pageより

Swift用のロギングAPIパッケージです。バージョン1.0.0.0はSwift 5.0を必要としますが、Swift 5への移行を容易にするためにSwift 4用のバージョン0.x.yシリーズが用意されています。Swift4でSwiftLogを使用したり、サポートしたりする予定がある場合は、ドキュメントの最後にある段落を確認してください。

まず第一に。これは、コードであれ、ドキュメントであれ、アイデアであれ、積極的に貢献を求めているコミュニティ主導のオープンソースプロジェクトの始まりです。SwiftLog自体への貢献とは別に、現時点ではもう一つ大きなギャップがあります。SwiftLogは、エコシステムが使用できる共通のAPIを確立しようとするAPIパッケージです。ロギングを実世界のワークロードで本当に機能させるためには、ログメッセージをファイルに永続化したり、端末上でより良い色で表示したり、SplunkやELKに送信したりするSwiftLog互換のロギングバックエンドが必要です。

SwiftLogが現在提供しているものはAPIドキュメントにあります。

printからの脱却

本来「SwiftLog互換のロギングバックエンドが必要」なのですが、Xcode Outputで使用する範囲であればSwiftLogで問題ない。
そのままでも日時は表示される。
デバッグ使用するにはクラス名、メソッド名、ライン数は欲しい。
metadataで表示させる方法もあるが、表示が「function=関数名」(例)となり、格好良くない。
互換ライブラリ一覧がGitHubページに掲載れています。それを使えば解決するが、開発してみる。
LogHandlerベースで互換ライブラリ開発ではなく、Extensionを使った開発。

LoggerExtension.swift

import Logging

extension Logger {
    static var level = Logger.Level.info
    
    init(function: String = #function) {
        self.init(label: function)
        self.logLevel = Logger.level
    }
    
    func trace(_ message: String = "" , function: String = #function, line: Int = #line) {
        self.trace(Logger.Message(stringLiteral: String("[\(function):\(line)] \(message)")))
    }

    func debug(_ message: String = "" , function: String = #function, line: Int = #line) {
        self.debug(Logger.Message(stringLiteral: String("[\(function):\(line)] \(message)")))
    }

    func info(_ message: String = "" , function: String = #function, line: Int = #line) {
        self.info(Logger.Message(stringLiteral: String("[\(function):\(line)] \(message)")))
    }

    func notice(_ message: String = "" , function: String = #function, line: Int = #line) {
        self.notice(Logger.Message(stringLiteral: String("[\(function):\(line)] \(message)")))
    }

    func warning(_ message: String = "" , function: String = #function, line: Int = #line) {
        self.warning(Logger.Message(stringLiteral: String("[\(function):\(line)] \(message)")))
    }

    func error(_ message: String = "" , function: String = #function, line: Int = #line) {
        self.error(Logger.Message(stringLiteral: String("[\(function):\(line)] \(message)")))
    }

    func critical(_ message: String = "" , function: String = #function, line: Int = #line) {
        self.critical(Logger.Message(stringLiteral: String("[\(function):\(line)] \(message)")))
    }
}

使用Example

SwingLogの使い方と変わらない。
initとログ出力(info等)は引数なしを用意した。

import UIKit
import Logging

class ViewController: UIViewController {

    let logger = Logger()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        logger.info()
        logger.info("start")
:
:

表示例

2020-09-27T10:30:15+0900 info ViewController : [viewDidLoad():70] 

Swift

Posted by shi-n