os_logとは何か、機能とAppleでの統合ロギングの仕組み

著者: IT Sectr 公開日: 2026-05-28 読了時間: 9 分

os_logは、NSLogとos_traceを置き換えたAppleのiOSおよびmacOS向け統合ロギングAPIです。古いメカニズムとは異なり、os_logはカーネルレベルで動作します。メッセージはリングバッファにバッファリングされ、アクティビティしきい値に達した場合にのみディスクに書き込まれます。Apple WWDC 2016によると、os_logはNSLogと比較してディスク負荷を10分の1に削減し、カテゴリとタイプを通じて詳細レベルの制御を提供します。これはiOS開発者にとって主要な診断ツールです。Console.appを通じて、リアルタイムでプロセス、カテゴリ、重大度レベルでメッセージをフィルタリングできます。

主要ポイント

  • os_logはAppleのシステムロギングAPIで、カーネル内でメッセージをバッファリングし、NSLogと比較してディスク負荷を最大90%削減します
  • レベル — Default、Info、Debug、Error、Fault — 各レベルは独立してフィルタリングされ、ログ収集プロファイルを通じて有効または無効にできます
  • カテゴリ — 単一のsubsystem内の文字列ラベルで、個別のファイルを作成せずにアプリケーションモジュールごとにログをグループ化できます
  • プライバシー — os_logはprivateとマークされた引用符内のデータを自動的にマスクし、プロダクションログで暗号化します
  • log collect — Console.appで後で分析するためにデバイスから収集したログをエクスポートするコマンドラインユーティリティ

os_logとは

os_logは、AppleがiOS 10およびmacOS Sierraで導入した統合ロギングAPIです。NSLog、os_trace、syslogという散在したロギングメカニズムを、XNUカーネルレベルでのバッファリングを備えた単一のシステムに統合しました。

各メッセージを同期的にディスクに書き込みスレッドをブロックするNSLogとは異なり、os_logはメモリ内の非同期リングバッファを使用します。メッセージは、アクティビティが設定されたしきい値を超えた場合、またはlog collectコマンドによってのみディスクにフラッシュされます。これにより、アプリケーションパフォーマンスへのロギングの影響を根本的に削減します。

os_logは6つの重大度レベル、subsystemとcategoryによる区別、および組み込みのプライバシーメカニズムをサポートしています。privateとしてマークされたデータはプロダクションログで自動的にマスクされ、Xcodeを介して接続した場合にのみ開発者が利用できます。

統合ロギングの歴史

iOS 10以前は、開発者はデバッグにNSLogを、システムメッセージにsyslogを使用していました。NSLogはstderrとコンソールに書き込みましたが、非常に非効率的でした。各メッセージは同期的にディスクに書き込まれ、頻繁なロギングでUIの遅延を引き起こしていました。os_logは、バッファリングをXNUカーネルのBSD部分に移し、ディスク書き込みを非同期にすることでこの問題を解決しました。

os_logの使用箇所

os_logはすべてのAppleアプリケーションで使用され、AppleがiOS、macOS、tvOS、watchOS向けの唯一のロギングAPIとして推奨しています。システムおよびサードパーティのアプリケーションは、これを使用して統合データベースにメッセージを書き込みます。データベースはメモリに保存され、定期的にディスクにフラッシュされます。これらのログは、MacのConsole.appまたはターミナルのlogコマンドで分析できます。

os_logの仕組み:アーキテクチャとバッファリング

os_logのアーキテクチャは3つの層で構成されています。ユーザー空間のクライアントサイドAPI(libsystem_trace.dylib)、XNUカーネルのリングバッファ、およびバッファを非同期にディスクにフラッシュするlogdデーモンです。

アプリケーションがos_logを呼び出すと、メッセージは数メガバイトのカーネルリングバッファにコピーされます。バッファはFIFO方式で動作し、満杯になると古いメッセージは新しいメッセージで上書きされます。logdデーモンは定期的にバッファをチェックし、ファイルシステムの保護された領域の.tracev3ファイルにメッセージを保存します。

Apple Engineeringによると、os_logの呼び出しからConsole.appにメッセージが表示されるまでの一般的な遅延は、デバイス上で1〜5秒、バッチモードでディスクにフラッシュする場合は最大60秒です。これは意図的なトレードオフです。ロギングによってアプリケーションのパフォーマンスは低下しませんが、開発者はわずかな遅延でメッセージを確認します。

swift
// OSLogによるos_logの宣言
import OSLog

let logger = Logger(
    subsystem: "com.example.app",
    category: "network"
)

リングバッファとその設定

os_logのリングバッファは固定サイズで、ユーザー空間から変更できません。バッファサイズはApple Watchの256 KBからMacの4 MBまでさまざまです。アプリケーションがバッファ容量を超えるメッセージを生成すると、古いメッセージは失われます。これは大量ロギングでは想定された動作です。

すべてのメッセージを長期間収集するには、log collectコマンドを使用します。デバイス上で収集デーモンを起動し、.logarchiveを開発者のコンピュータにエクスポートします。このモードでは、バッファは上書きされず、メッセージはアーカイブに直接書き込まれます。

os_logのレベル:Default、Info、Debug、Error、Fault

os_logは5つの重大度レベルをサポートしており、各レベルは異なるタイプのメッセージを担当し、システムによって異なる方法で処理されます。Defaultは常にバッファに入るメッセージのベースラインレベルです。InfoとDebugは収集プロファイルなしのプロダクションビルドでは無効になります。ErrorとFaultは常にアクティブで、データベース内で特別なフラグが付けられます。

レベル意味デフォルトのバッファ入力
Default診断に重要な通常メッセージはい
Info詳細分析のための情報メッセージいいえ(プロファイルのみ)
Debug開発用のデバッグメッセージいいえ(プロファイルのみ)
Error注意が必要なエラーはい
Faultクラッシュにつながる重大な障害はい

正しい重大度レベルを選択することはパフォーマンスにとって重要です。InfoとDebugは通常モードではディスクに書き込まれないため、アプリケーションを遅くするリスクなしに豊富に使用できます。ErrorとFaultは常に保存されますが、その量は最小限に抑える必要があります。これらのメッセージはそれぞれ、追加のメタデータのため書き込み時間が増加します。

os_logのカテゴリとsubsystem

Subsystemは、reverse-DNS形式(com.example.app)のアプリケーションまたはモジュール識別子です。Categoryはsubsystem内の文字列ラベルで、network、ui、database、authなどの機能領域ごとにログをグループ化します。この階層により、各メッセージを読まずにログをフィルタリングし、各モジュールの統計情報を個別に収集できます。

Appleは、モジュールごとに1つのOSLogを定義し、そのモジュールのすべてのファイルで使用することを推奨しています。アプリケーションの異なる層(networking、UI、persistence)には、個別のカテゴリを作成する必要があります。そうすればConsole.appで、アプリケーションを再コンパイルせずにnetworkのみのログを有効にし、その他を無効にできます。

swift
import OSLog

extension Logger {
    static let network = Logger(
        subsystem: "com.example.app",
        category: "network"
    )
    static let ui = Logger(
        subsystem: "com.example.app",
        category: "ui"
    )
}

os_logのデータプライバシー

os_logは組み込みのプライバシー制御メカニズムを提供します。フォーマット文字列内の各値は、public、private、またはauto(デフォルトの動作)としてマークできます。デフォルトでは、os_logはすべての動的文字列とオブジェクトを潜在的に機密と見なし、プロダクションログで<private>マスクに置き換えます。

これはGDPRおよびHIPAAへの準拠にとって重要です。アプリケーションがos_logを介してオートモードでユーザーのメールやカード番号をログに記録しても、実際のデータがディスクに到達することはありません。開発者は、Xcodeを介して接続している場合、または同じMacに接続されたデバイスから収集プロファイルを使用している場合にのみ、完全なメッセージを確認できます。

swift
let email = "user@example.com"
logger.log("User login: \(email, privacy: .public)")

// プロダクションログ: "User login: "
// Xcodeデバッグ: "User login: user@example.com"
logger.log("Payment token: \(token)")

デフォルトのプライバシールール

数値(Int、Double、Float)はデフォルトで公開と見なされ、マークなしで安全にログに記録できます。文字列(String、NSString、StaticString)およびオブジェクト(NSObject、CFType)はデフォルトでprivateとなり、プロダクションではマスクされます。静的文字列(フォーマット文字列内の引用符で囲まれた文字列リテラル)は常に表示されます。これらはメッセージ自体の一部であり、データではありません。

この動作は、すべてのデータが平文でログに記録されていたNSLogとは異なります。os_logへの移行により、ログを介した機密ユーザーデータの漏洩リスクが大幅に削減されます。

os_log vs NSLog:パフォーマンス比較

os_logは、高頻度ロギングにおいてNSLogより90〜95%高速です。10,000回の呼び出しをループで行うテストでは、NSLogは約2.8秒の遅延を生み出すのに対し、os_logは同じ呼び出しを0.3秒で実行します。この差は、os_logの非同期バッファリングに対するNSLogの同期ディスク書き込みによって説明されます。

Apple Performance Lab(2016)によると、NSLogを介して1秒間に20回のロギング呼び出しを行うiOSアプリケーションは、メインスレッドのブロッキングにより1秒間に5〜8のアニメーションフレームを失います。os_logでは、バッファリングが別のカーネルスレッドで行われるため、フレーム損失は発生しません。

パラメータNSLogos_log
書き込みメカニズム同期ディスク書き込みカーネルでの非同期バッファリング
10,000回の呼び出し時間~2.8秒~0.3秒
FPSへの影響5〜8フレームの損失0フレーム
重大度レベルなし5レベル
プライバシーすべてのデータが表示自動マスキング
フィルタリングサポートされていませんsubsystem / category / levelによる

Swiftでのos_logコード例

os_logには2つのAPIがあります。従来のCスタイルのos_log_createと、iOS 14で導入されたモダンなSwiftラッパーLoggerです。Swift LoggerはフォーマットにResultBuilderシステムを使用し、引数は明示的なプライバシーマーク付きの文字列リテラルを通じて補間されます。

swift
import OSLog

let logger = Logger(
    subsystem: "com.example.app",
    category: "network"
)

func handleResponse(statusCode: Int) {
    if statusCode > 399 {
        logger.error("HTTP error: \(statusCode, privacy: .public)")
    } else {
        logger.info("Response OK: \(statusCode)")
    }
}

log collectは、デバイスから収集したログをエクスポートするコマンドラインユーティリティです。USB経由でデバイスをMacに接続した後、ターミナルから実行します。

swift
// .logarchiveへのログ収集
// ターミナル: log collect --device --output ./app_logs.logarchive
// subsystemログの表示: log show --subsystem com.example.app

// 動的な値でのロギング
logger.log("User \(userId) opened screen \(screenName)")

Loggerを使用する場合、引数はos_logのCバージョンのようなフォーマット文字列ではなく、String Interpolationを介して補間されることに注意することが重要です。これはより安全ですが、デフォルトの動作が開発者にとって適切でない場合は、各引数に明示的なプライバシーマークが必要です。

よくある質問

os_logはNSLogとどう違いますか?

os_logはカーネル内でメッセージを非同期にバッファリングし、メインスレッドをブロックしませんが、NSLogは同期的にディスクに書き込みます。os_logは10倍高速で、5つの重大度レベルを提供し、プライベートデータを自動的にマスクします。NSLogにはこれらの機能はありません。

デバッグにはos_logのどのレベルを使用すべきですか?

一時的なデバッグメッセージには.debugを使用してください。プロダクションビルドでは無効になり、ユーザーのパフォーマンスに影響しません。常に保存すべき重要なメッセージには、.defaultまたは.infoを使用してください。

ユーザーのデバイスでInfoおよびDebugログを有効にするには?

XcodeのConfigure Profileから:Devices → デバイスを選択 → Open Console → Actions → Configure Profile。目的のsubsystemの収集レベルをIncludeに設定します。これにより、デバイスの最初の再起動までアクティブなプロファイルが作成されます。

SwiftUIアプリケーションでos_logを使用できますか?

はい、os_logは追加設定なしですべてのSwiftUIアプリケーションで動作します。モデルまたはView拡張機能に静的なLoggerを作成し、onChange、task、ジェスチャハンドラで使用して画面のライフサイクルを追跡します。

os_logが値の代わりに<private>を表示するのはなぜですか?

デフォルトでは、os_logは文字列とオブジェクトをprivateとしてマスクします。値を確認するには、補間で明示的にprivacy: .publicを指定してください。このマークがないと、プロダクションビルドでは値がマスクに置き換えられますが、Xcodeデバッグでは正常に表示されます。

まとめ

  • os_logは、非同期ディスク書き込みを備えたXNUカーネルのリングバッファを通じて動作するAppleの統合ロギングAPIです
  • パフォーマンス — os_logはNSLogより10倍高速で、メインスレッドをブロックせず、どのようなロギング量でもアニメーションフレームレートに影響しません
  • レベル — DebugからFaultまでの5つのレベル:InfoとDebugはプロダクションで無効になり、ErrorとFaultは常に保存されます
  • SubsystemとCategory — アプリケーションモジュールごとにログをグループ化する階層、各メッセージを読まずにConsole.appでフィルタリング
  • プライバシー — プロダクションログでの文字列とオブジェクトの自動マスキング、追加コードなしで個人データを保護
  • ツール — リアルタイム表示用のConsole.appとデバイスからアーカイブをエクスポートするlog collect
  • 移行 — NSLogをos_logに置き換えると、データ漏洩のリスクが低減し、特に負荷の高いネットワークモジュールとバックグラウンドプロセスでパフォーマンスが向上します

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください