Skip to content

ログの分析

kazunokoが記録するJSON形式のログファイルは、単純なUnixコマンドを組み合わせることで、効率的に分析できます。

このガイドでは、実践的なログ分析コマンドを紹介します。


推奨ツール

ログ分析には複数のツールの組み合わせがあります。 用途に応じて選択してください。

標準的な組み合わせ(互換性重視)

# grep + jq + sort/uniq
grep '"ERROR"' ~/Library/Logs/kazunoko/kazunoko.json | \
  jq 'select(.record.level.name == "ERROR")'

特徴:

  • すべてのUnix系システムで動作
  • jqの豊富な機能を活用可能
  • 学習リソースが豊富

インストール:

# macOS
brew install jq

# Linux
sudo apt-get install jq

# 既にインストール済みの場合が多い

高速な組み合わせ(パフォーマンス重視)

# rg + jaq + sort/uniq(最も高速)
rg '"ERROR"' ~/Library/Logs/kazunoko/kazunoko.json | \
  jaq 'select(.record.level.name == "ERROR")'

特徴:

  • rg(ripgrep):grepより約10倍高速
  • jaqjqより約5倍高速(Rust製)
  • 100万行以上のログ処理に最適

インストール:

# macOS
brew install ripgrep jaq

# Linux
sudo apt-get install ripgrep jaq

# Windows (Chocolatey)
choco install ripgrep jaq

ツール比較表

テキスト検索ツール

ツール 速度 インストール 互換性
grep 中程度 プリインストール 標準
rg 🚀 非常に高速 別途 標準

JSON処理ツール

ツール 実装 速度 インストール 互換性
jq C 中程度 別途 標準
jaq Rust 🚀 非常に高速 別途 jq互換

テキスト処理ツール(awk系)

ツール 実装 速度 インストール 互換性
awk C 高速 プリインストール POSIX標準
mawk C 🚀 非常に高速 別途 awk互換
uawk Rust 🚀🚀 極めて高速 別途 awk互換

awk代替ツールのインストール:

# macOS
brew install mawk uawk

# Linux
sudo apt-get install mawk uawk

# uawk(Cargo経由)
cargo install uawk

このガイドでの記載方針

  • 基本例:標準的なツール(jq)を使用
  • 高速化セクションrgjaqの使用例を紹介
  • 軽量化セクションawkの使用例を紹介

ログファイルの場所

ログファイルの保存先は以下の通りです。

OS パス
macOS ~/Library/Logs/kazunoko/kazunoko.json
Linux ~/.local/share/kazunoko/logs/kazunoko.json
Windows %APPDATA%\kazunoko\logs\kazunoko.json

複数のログファイルがある場合(日付ごと)は、特定のファイルを指定します。

# 特定のログファイルを分析
jq ... ~/Library/Logs/kazunoko/kazunoko.2025-12-28_01-45-55_765160.json

ログの構造

kazunokoのログはJSON Lines形式です。各行は以下の構造を持っています。

{
  "text": "Starting monitor TUI\n",
  "record": {
    "level": {
      "name": "INFO",
      "no": 20
    },
    "time": {
      "repr": "2025-12-28 01:45:55.767572+09:00",
      "timestamp": 1766853955.767572
    },
    "function": "main",
    "module": "monitor",
    "file": {
      "name": "monitor.py",
      "path": "/path/to/monitor.py"
    },
    "line": 538,
    "message": "Starting monitor TUI"
  }
}

重要なフィールド:

  • .record.level.name - ログレベル(DEBUG, INFO, SUCCESS, WARNING, ERROR)
  • .record.time.repr - タイムスタンプ
  • .record.function - 関数名
  • .record.module - モジュール名
  • .text - ログメッセージ

基本的な分析コマンド

ファイルサイズの確認

大きなファイルの場合、tailで最新部分だけを分析することをおススメします。

# ログファイルのサイズ確認
du -h ~/Library/Logs/kazunoko/kazunoko.json

ログレベル別の件数集計

jq -r '.record.level.name' ~/Library/Logs/kazunoko/kazunoko.json | \
  sort | uniq -c | sort -rn

出力例(実測値):

 520589 DEBUG
 506377 WARNING
    731 INFO
    168 SUCCESS
      8 ERROR

解釈:

  • 合計 約103万件のログ
  • DEBUG(約50%)と WARNING(約49%)で大半を占める
  • エラーは8件のみ

関数別のログ件数

jq -r '.record.function' ~/Library/Logs/kazunoko/kazunoko.json | \
  sort | uniq -c | sort -rn | head -20

関数ごとのログ出力量を把握できます。

出力例(実測値):

506404 receive_response
506374 _read_event
 13330 _get_response
   497 main
   399 send_command
   274 _on_event_received
   231 setup
    86 thresholds
    58 __init__
    56 detect_port
    44 parse_thresholds
    28 connect
    22 render
    10 process_existing_files
    10 on_mount
    10 _read_new_lines
     8 _load_events
     8 _load_available_commands
     7 action_update_display
     5 action_quit

解釈:

  • receive_response()_read_event()で約98%のログを占める
  • これらはイベント受信のホットパス(頻繁に実行される部分)
  • 他の関数は相対的にログが少ない

モジュール別のログ件数

jq -r '.record.module' ~/Library/Logs/kazunoko/kazunoko.json | \
  sort | uniq -c | sort -rn

どのモジュールが最も活発かが分かります。

出力例(実測値):

506929 device
506605 measure
 13362 mock
   469 get_runs
   356 monitor
    86 command
    44 parser
    18 get_events
     3 formatter
     1 cli

解釈:

  • devicemeasureモジュールで約98%のログを占める
  • これらはデバイス通信とイベント計測のコア機能
  • mockモジュールはテスト・シミュレーション時に活躍
  • cliモジュールはログが極わずか(エラーがない時は出力が少ない)

問題診断コマンド

エラーの詳細確認

jq 'select(.record.level.name == "ERROR")' ~/Library/Logs/kazunoko/kazunoko.json | \
  jq '{time: .record.time.repr, function: .record.function, message: .text}'

出力例:

{
  "time": "2025-12-28 01:46:42.123456+09:00",
  "function": "receive_response",
  "message": "Connection timeout"
}

ワーニングメッセージの種類別集計

jq -r 'select(.record.level.name == "WARNING") | .text' ~/Library/Logs/kazunoko/kazunoko.json | \
  sort | uniq -c | sort -rn | head -20

頻出するワーニングを把握できます。

特定のメッセージを検索

# 「timeout」を含むログを抽出
jq 'select(.text | contains("timeout"))' ~/Library/Logs/kazunoko/kazunoko.json

# 「EventTimeout」エラーのみ
jq 'select(.record.level.name == "ERROR" and .text | contains("EventTimeout"))' ~/Library/Logs/kazunoko/kazunoko.json

時系列で確認

最新のエラーを時系列順に表示:

jq -r 'select(.record.level.name == "ERROR") | "\(.record.time.repr): \(.text)"' ~/Library/Logs/kazunoko/kazunoko.json

大きなログファイルの効率的な分析

ログファイルが数GB以上の場合、全ファイルをメモリに読み込むと遅くなります。 以下の方法で効率化できます。

方法1:最新部分だけを分析

# 最新の10000行だけを分析
tail -10000 ~/Library/Logs/kazunoko/kazunoko.json | \
  jq -r '.record.level.name' | \
  sort | uniq -c | sort -rn

方法2:rg で高速フィルター(推奨)

# ERROR を含む行だけを抽出してから jq で処理(高速)
rg '"ERROR"' ~/Library/Logs/kazunoko/kazunoko.json | \
  jq 'select(.record.level.name == "ERROR") | .record.function' | \
  sort | uniq -c | sort -rn

rg(ripgrep)はgrepより高速で、大きなログファイルの処理に適しています。

インストール方法:

# macOS
brew install ripgrep

# Linux
sudo apt-get install ripgrep

# Windows (Chocolatey)
choco install ripgrep

方法3:awk で高速フィルター

# WARNING と ERROR だけを抽出(JSON解析なし)
awk '/"WARNING"|"ERROR"/ {print}' ~/Library/Logs/kazunoko/kazunoko.json | \
  jq -r '.record.level.name' | \
  sort | uniq -c | sort -rn

awkは古典的で軽量。すべてのUnix系システムにプリインストール済みです。

方法4:mawk で超高速フィルター

# mawk(C最適化版)+ jq で処理
mawk '/"ERROR"/ {print}' ~/Library/Logs/kazunoko/kazunoko.json | \
  jq -r '.record.level.name' | \
  sort | uniq -c | sort -rn

mawkawkと互換性を保ちながら、約3倍高速です。

方法5:uawk で極めて高速フィルター

# uawk(Rust製awk)+ jaq(Rust製jq)で最高速
uawk '/"ERROR"/ {print}' ~/Library/Logs/kazunoko/kazunoko.json | \
  jaq -r '.record.level.name' | \
  sort | uniq -c | sort -rn

uawkawk互換のRust実装。もっとも高速です。

パフォーマンス参考値(100万行ログ処理):

  • awk: 約0.5秒
  • mawk: 約0.3秒
  • uawk: 約0.2秒

パイプラインの組み立て例

例1:エラーが発生した関数を特定

jq 'select(.record.level.name == "ERROR") | .record.function' \
  ~/Library/Logs/kazunoko/kazunoko.json | \
  sort | uniq -c | sort -rn

例2:ワーニングの多い関数を特定

jq 'select(.record.level.name == "WARNING") | .record.function' \
  ~/Library/Logs/kazunoko/kazunoko.json | \
  sort | uniq -c | sort -rn | head -10

例3:特定時間帯のログを抽出

# 2025-12-28 01:46 の間のログを抽出
jq 'select(.record.time.repr | startswith("2025-12-28 01:46"))' \
  ~/Library/Logs/kazunoko/kazunoko.json | \
  jq -r '.record.level.name' | \
  sort | uniq -c

例4:接続失敗の原因を特定

# 接続関連のエラーやワーニングを抽出
jq 'select(
  (.record.level.name == "ERROR" or .record.level.name == "WARNING") and
  (.text | contains("connection") or .text | contains("port") or .text | contains("timeout"))
) | {time: .record.time.repr, level: .record.level.name, message: .text}' \
  ~/Library/Logs/kazunoko/kazunoko.json

トラブルシューティング

jq コマンドが見つからない

# インストール(macOS)
brew install jq

# インストール(Linux)
sudo apt-get install jq

# インストール(Windows, chocolatey)
choco install jq

ログが空の場合

# ログファイルのサイズを確認
ls -lh ~/Library/Logs/kazunoko/

# 最新のログファイルを確認(日付で分かれている)
ls -lt ~/Library/Logs/kazunoko/ | head -5

大量のnullが出力される場合

.record.level の代わりに .record.level.name を使用してください。

# ❌ 間違い
jq '.level'

# ✅ 正解
jq '.record.level.name'

次のステップ