OSLogはAppleのUnified Logging Systemの一部であり、
アプリケーションからのログを一元管理する
アプリのパフォーマンス影響が最小限となるよう
設計されており、Xcode 15から利用可能
メリット [print]との違い
・Appleによる統一的な設計によりパフォーマンスがよい
・サブシステム/カテゴリで分類でき、フィルタリングが容易
・ログレベル(OSLogType)を分類可能
簡易アプリではprintで事足りるが、本格的なアプリや大規模アプリの場合は
OSLogを使用するとよい印象
使用方法
Loggerの作成
// インスタンス作成
let logger = Logger(subsystem: "com.app.hogehoge", category: "Logger")
subsystemにはアプリケーションのバンドル識別子を、
categoryにはログメッセージのカテゴリを指定します
これにより、Xcodeのコンソールでログをフィルタリングしやすくなります
ログ出力
// ログレベル:debugのログを出力
logger.debug("debug test.")
ログレベルに沿って各APIを叩きます
ログレベル一覧
・default (notice): 特に重要ではない一般的なログ
・info: トラブルシューティングに役立つ情報
・debug: 開発中のデバッグ用メッセージ
・warning: 非致命的な失敗を報告するための警告
・error: 重大なエラーや失敗を報告するためのメッセージ
・fault: システムレベルのエラーを記録するためのメッセージ
パフォーマンス向上する上での注意点
・APIを独自関数でラップ
これが一番パフォーマンスに影響すると思われる
ログメッセージをコンパイル時に解析する等の最適化は、
Logger APIを独自関数でラップすると損なわれてしまう
・永続化するログレベルの多用
ログレベルの中には永続化(ディスクに書き込まれる)ものがあり、
多用するとパフォーマンスが落ちる
・永続化するもの
error, fault, default
開発中に多用する箇所はコスト低いdebug,traceを使い、
リリース時には間引く
infoはデフォルトでは永続化されないが、永続化に設定できる
・静的なログメッセージを渡す
OSLogに渡すメッセージは静的文字列であることが推奨される
動的なメソッドをdescriptionで渡すのをなるべく避ける
ファイル名やメソッド名を出力させたい場合は#function, #file
のような特殊リテラル式
を使うとよい
※特殊リテラル式はコンパイル時に静的文字列へ変換されるため
・動的なログメッセージのコスト最小化
上記で致し方なく動的なメッセージを渡す場合は高コストな処理
でないかを確認すべきである
処理に時間がかかる関数や大きなデータ構造を直接渡すことをさけ、
必要なデータのみを抽出して渡すようにする
・カテゴリを分けすぎない(100個以上)
基本的でOSLogはスレッドセーフのため、複数のLoggerからログを
同時に出力しても問題ないように作られているが、さすがに100個以上は
推奨されていないらしい
・ログの量と頻度
ループ内や、1秒間に何度も呼ばれるような関数内でのログ出力は避ける
どうしても入れる場合はサンプリング/スロットリング(間引き)をおこなう