LoginSignup
5

More than 1 year has passed since last update.

posted at

updated at

apple/swift-logコンパチのSwiftログライブラリ「Puppy」をつくった

先日、PuppyというSwiftログライブラリをつくりました。本ライブラリは、apple/swift-logのREADMEにもapple/swift-logのバックエンドコンパチログライブラリの1つとしても記載されています。また、単体の(例えばiOS向けの)ログライブラリとしても使うことができるようになっており、LinuxとDarwin(macOS/iOS/tvOS/watchOS)のいずれの環境でも動作します。サーバーサイドSwiftに興味のある方はもちろんのことiOSアプリ等を開発をする方にも一度使ってみてもらえればと思います。
https://github.com/sushichop/Puppy
※ STARをもらえると励みになります🙂

なぜつくったのか?

私はObjective-C全盛時代によく使われていたログライブラリCocoaLumberjackのメンテナの1人として今現在もメンテナ活動を続けています。少なくとも昔はよくできたライブラリだとは思いますが、Swift環境では使いにくい、Linux環境では使えない等の問題があります。
私が必要としていたのは、1つのライブラリでLinux、Dwarinのいずれの環境でも十分に使えること、及びログローテーションをサポートしていることでした。特に必要としていたのはLinux環境におけるファイルログローテーション機能です。
既存のOSSのSwiftログライブラリでは私の需要を満たせなかったので、自ら作ることにしました。

ライブラリ名 Linuxサポート syslog(Linux)サポート ログローテーション機能 apple/swift-logサポート
SwiftyBeaver N/A N/A N/A
XCGLogger N/A N/A N/A
Puppy

動作環境

  • Swift 5.0以上(Swift 5.3以上推奨)
  • CocoaPods、Carthage、Swift Package Manager

使い方

ロギング先としてコンソール、ファイル、syslog(Linux)等をサポートしています。カスタムログフォーマットにも対応しています。詳しくはsushichop/PuppyのREADMEを参照してもらえればと思いますが、以下に使い方の例を2つ簡単に書いておきます。

使い方その1(ファイルログローテーション)

下記はファイルへロギングしつつ、10MBのログファイルを5つまでログローテーションする例です。FileRotationLoggerの第1引数にはIDとなる逆FQDN形式の文字列を指定してください。第2引数にはファイル名を指定します。ログローテーション完了通知についてはdelegateで実現しています。

import Puppy

class ViewController: UIViewController {
    let delegate = SampleFileRotationDelegate()
    override func viewDidLoad() {
        super.viewDidLoad()
        let fileRotation = try! FileRotationLogger("com.example.yourapp.filerotation", fileURL: "./rotation/foo.log")
        fileRotation.maxFileSize = 10 * 1024 * 1024
        fileRotation.maxArchivedFilesCount = 5
        fileRotation.delegate = delegate
        let log = Puppy()
        log.add(fileRotation)
        log.info("INFO message")
        log.warning("WARNING message")
    }
}

class SampleFileRotationDelegate: FileRotationLoggerDeletate {
    func fileRotationLogger(_ fileRotationLogger: FileRotationLogger,
                            didArchiveFileURL: URL, toFileURL: URL) {
        print("didArchiveFileURL: \(didArchiveFileURL), toFileURL: \(toFileURL)")
    }
    func fileRotationLogger(_ fileRotationLogger: FileRotationLogger,
                            didRemoveArchivedFileURL: URL) {
        print("didRemoveArchivedFileURL: \(didRemoveArchivedFileURL)")
    }
}

使い方その2(apple/swift-logバックエンド)

apple/swift-logバックエンドとして使う場合は、Carthageは利用できません。これはapple/swift-logがCarthageをサポートしていないためです。CocoaPodsまたはSwift Package Managerを使ってインテグレーションしてください。
下記はコンソールとsyslogへロギングする例です。Puppyに加えてLoggingもインポートする必要がある点に注意ください。

import Puppy
import Logging

let console = ConsoleLogger("com.example.yourapp.console")
let syslog = SystemLogger("com.example.yourapp.syslog")

let puppy = Puppy.default
puppy.add(console)
puppy.add(syslog)

LoggingSystem.bootstrap {
    var handler = PuppyLogHandler(label: $0, puppy: puppy)
    // Set the logging level.
    handler.logLevel = .trace
    return handler
}

log.trace("TRACE message")  // Will be logged.
log.debug("DEBUG message")  // Will be logged.

その他(補足)

本ライブラリでは、あえて実装していない機能等もあります。その1つが__dispatch_queue_get_label(nil)関数によるDispatchキューラベル取得機能です。これは、Linux環境で使えないこと、及びここにもあるように本関数を呼び出すことにより、潜在的にクラッシュする可能性があるためです。
どうしても使いたい場合は、本ライブラリではLogFormattableプロトコルによるカスタムログフォーマットに対応していますので、ライブラリ利用者は必要に応じて本プロトコル実装の中で、上記関数を呼び出すことにより対応できます。

最後に

今回つくったSwiftログライブラリPuppyについては、Linux/Darwinの両環境で動作することを重視しており、今後も適宜改版していく予定です。サーバサイドSwift盛り上がっていくといいですね🙂

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
5