開発部 iOS 担当の金森です。

突然ですが iOS でのログ出力ってどのようにされていますか?
ObjC から触っている方は NSLog を、 Swift からなら print を使っているという方が多いのではないでしょうか。
もちろんそれでも「ログ出力」という目的は果たせていますし、ユーザに迷惑がかかるようなことはあまりないでしょう(出力し過ぎで速度低下を招かなければ)。

ただ、実は iOS でのログ出力にはいくつか方法があり、中でも WWDC2016 で発表された統合ログ環境を利用することでちょっぴり幸せになれるかもしれません。
今回はいくつかのログ出力方法についてと、統合ログ環境の概要について説明していきます。

対象読者

iOS 開発者であり、ログ出力のこと嫌いじゃないと思っている方
(Swift で開発をしていることは必須ではないです)

この記事でわかること

  • ログ出力方法の種類
  • 統合ログ環境の概要

ログ出力方法の種類

iOS でのログ出力方法にはいくつか種類があり、出力先や用途も異なります。

API
出力先
説明
standard output
与えられた要素のテキスト表現を標準出力に出力します。
standard output
基本的には print と同じですが、テキスト表現への変換方法が異なります。
Apple System Log
NSLogv を簡単に呼べるようにしたものです。
Apple System Log
エラーメッセージを出力します。
出力先は ASL ですが、エラー出力にも同時に表示されます。
なお、直接呼ぶのではなく、 NSLog を使うことが推奨されています。
system logger
システムロガーへの出力を行うための API です。
(Swift では vsyslog() を利用することになります。)
Apple System Log
Apple System Log に対してログ出力するための API です。
エラーレベルが Notice 以上であれば標準出力にも表示されます。
syslog API からの置き換えを目的としたものでしたが、 iOS10 以降からは unified logging system へ統合されます(従って、ASL API は Deprecated になっています)。
os_log
(objc) ← objc の方が説明が豊富
unified logging system
既存の logging API (NSLog / ASL / syslog) に代わる統合ログ環境です。
iOS10+ でビルドした場合に自動的に利用されます。
コンソール.app で確認するとタイプ/サブシステム/カテゴリといった情報で区別しやすくなっており便利です。

print v.s. NSLog

統合ログ環境について紹介する前に、よく使われる print と NSLog について触れておきます。
Xcode での開発中ならどちらもコンソールに表示されており、それほど違いを感じることはありません。
ただし、 NSLog はあくまでも エラーメッセージ なので、リリース後は表示したくないと思ってもログを見ればべろべろ吐き出されているのが確認できてしまいます。しかも NSLog は比較的性能が悪いため若干悪影響を与えてしまいます。

じゃあ print を使えばいいよね、という気がしますが、こちらは標準出力のみが対象となるため、デバイス接続時にコンソールでログを見ると表示されません。

そのため、私としては以下をおすすめします。
  • 開発中にログが確認出来れば良い
    • print を採用
  • サンプル作成など
    • NSLog を採用
  • リリース後も開発情報とエラー情報とで出し分けたい
    • 統合ログ環境向け API を採用

統合ログ環境

WWDC2016 で発表され、新しく導入されたロガーおよびツール全般を指します。

概要

統合ログ環境は以下のような特徴を持ちます。
  • 効率・性能のよい API (os_log) を提供(ASL を含む Legacy API の置きかえ)
  • 問題解決をしやすくする様々な機能を持つ
    • 複数のログレベルによる細やかな制御
    • 組み込みのプライバシー保護の仕組み
    • アクティビティトレースとの統合など
  • 新しい Console.app により接続中のデバイスのログデータを確認可能
  • コマンドラインツール(log / logger)からも操作が可能

利用可能な環境

該当SDK以降でビルドすれば自動的に適用されます。
  • iOS10
  • macOS10.12
  • watchOS3.0
  • tvOS10.0
また、NSLog, ASL API, Syslog については適用と同時に統合ログ環境へのリダイレクトが行われます( print は対象外)。

参照


利用例

API サンプル

新 API (os_log) を利用したログ出力のサンプルコードです。
※ iOS10 以降でないと使えないことに注意
if #available(iOS 10.0, *) {
    let osLog = OSLog(subsystem: "inc.eq.LogSample", category: "General")
    os_log("%@", log: osLog, type: .default, text)
} else {
    ..
}
  • subsystem : 識別子(逆ドメインで OK)
  • category : ログの分類(UI / Network / etc)

コンソール表示


[アプリケーション] - [ユーティリティ] - コンソール.app を起動します。

コンソールが起ち上がったらデバイスを選択

右上の検索窓で条件を指定し、

[いずれか ∨] の項目をそれぞれ適切なものを選択


これで、ログ一覧に期待するものだけが絞り込まれて表示されます。

新 API における注意事項

統合ログ環境向けの新 API は ASL からの置き換えとしていますが、
セッションにあった説明によると「検索機能は公開していない」ということです。


そのため、プログラム的にログの内容を取得することが現状出来ません(2017/09 時点でも提供されていないようです)。

まとめ

統合ログ環境を使うことで、ログレベルの分類やカテゴリ指定と コンソール.app の検索機能とが合わさり格段にログを追いかけやすくなったのは間違い無いでしょう。
今後の開発においてログ出力を適切にしていくのなら、この統合ログ環境を活用されることを強くおすすめします。

ただ、開発中だとしてもアドホック配信した先のログを取得したい、とか、デバイス上でログ確認したい、という需要がある場合はログを自前で記録する仕組みを作る必要があります。
だったら最初から SwiftyBeaver のようなログツールを使った方がいいのでは?
と思ってしまうわけですが、そういうものを入れなくても使える標準機能というのは手軽でいいですよね。ということで今回は終わりにします。

コメントの投稿