log-coverage-analyzer について
log-coverage-analyzerは、コードリポジトリのログを点検するスキルです。呼び出しチェーンの分岐やエラーリターンを確認し、高頻度関数のログリスクを検出してMarkdownレポートを作成します。
主な機能
- 01呼び出しチェーンの分岐ログ確認
- 02エラーリターンのLOGE確認
- 03高頻度関数のログリスク検出
- 04優先度別の不備分類
- 05修正案付きMarkdownレポート作成
活用シーン
- 01エラー経路のログ点検
- 02ネットワークコールバックの頻繁なログ確認
- 03複数段階処理の成功ログ監査
- 04ログ分析レポートの作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ openharmonyinsight/ openharmony-skills --skill log-coverage-analyzerインストール後、Claude Code で/log-coverage-analyzerを入力して読み込まれたか確認します。
詳細
このスキルは、コードリポジトリの包括的なログカバレッジ分析を実行します。呼び出しチェーン内のログ出力の不足を特定し、パフォーマンスに影響する可能性のある高頻度ログのリスクを検出します。
分析の原則
ログレベルの定義
| ログレベル | 動作 | 用途 |
|---|---|---|
| LOGE | 常に出力され、失われることはありません | 重大 - すべてのエラー戻りパスに必ず必要です |
| LOGI | 常に出力されますが、同じ箇所で高頻度に実行されると失われる場合があります | 重要 - 成功パス、主要な操作 |
| LOGD | デバッグスイッチが有効な場合のみ出力されます | 任意 - デバッグ情報のみ |
| LOGW | デバッグスイッチが有効な場合のみ出力されます | 任意 - 警告情報のみ |
分析の基本ルール
- ログカバレッジのルール:関数呼び出しチェーン内の各分岐に、LOGE または LOGI レベルのログ出力が必要です
- 高頻度リスクのルール:頻繁に呼び出される可能性のある関数(ループ、タイマー、コールバック、イベントハンドラー)に LOGE/LOGI ログがある場合、パフォーマンスリスクが生じます
- エラーパスのルール:すべてのエラー戻りパスに、LOGE ログ出力が必須です
- コンテキストのルール:すべてのログに、十分なコンテキスト情報(ID、状態、パラメーター)を含める必要があります
実行ワークフロー
ステップ 00:分析計画の作成
説明:分析を開始する前に詳細な計画を作成します
アクション:
TodoWriteツールを使用してタスクリストを作成します- 分析範囲を計画します:
- ソースファイルの検出とフィルタリング
- 関数呼び出しチェーンの抽出
- 分岐ごとのログカバレッジ分析
- 高頻度リスクの検出
- レポートの生成
出力:TodoWrite ツールを使用して分析計画を作成
ステップ 01:ソースファイルの検出
説明:リポジトリ内の関連するソースファイルをすべて検索します
アクション:
Globツールを使用して、言語パターンに基づきソースファイルを検索します:- C/C++:
**/*.cpp、**/*.cc、**/*.cxx、**/*.h、**/*.hpp - Java:
**/*.java - Python:
**/*.py - JavaScript/TypeScript:
**/*.js、**/*.ts - Go:
**/*.go - Rust:
**/*.rs
- C/C++:
- 指定されている場合はテストファイルを除外します(パターン:
**/test/**、**/tests/**、**/*_test.*) - ビルドディレクトリを除外します(パターン:
**/build/**、**/out/**、**/target/**)
出力:分析対象のソースファイル一覧
ステップ 02:ログパターンのスキャン
説明:すべてのソースファイルをスキャンして、ログマクロ/関数を検索します
アクション:
Grepツールを使用し、次のパターンでログステートメントを検索します:- 次を大文字・小文字を区別せずに検索します:
LOG[DEIW]、HILOG[DEIW]、ALOG[DEIW] - 次も検索します:
\.log[deiw]\(、Log\.[deiw]、LOG\.
- 次を大文字・小文字を区別せずに検索します:
- ファイルごとに出現回数を数えます
- ログレベルの分布を特定します
出力:ファイルごとのログ統計
ステップ 03:関数と呼び出しチェーンの抽出
説明:ソースファイルを解析して、関数定義と呼び出し関係を抽出します
アクション:
- 各ソースファイルについて:
- 関数定義を特定します(言語ごとに異なるパターン)
- すべての分岐を含む関数本体を抽出します
- 各関数内の関数呼び出しを特定します
- 呼び出しチェーンのグラフを構築します
- 分岐条件(if/else、switch/case、try/catch、早期リターン)をマッピングします
出力:呼び出し関係を含む関数一覧
ステップ 04:分岐ごとのログカバレッジ分析
説明:呼び出しチェーン内の各分岐で必要なログ出力が行われているか確認します
アクション:
- 呼び出しチェーン内の各関数について:
- すべての分岐を特定します:
- 早期リターン
- if/else 分岐
- switch/case 分岐
- try/catch ブロック
- エラー条件を伴うループ終了
- 各分岐で LOGE または LOGI が使用されているか確認します
- 必要なログ出力がない分岐に ログ不足 のフラグを付けます
- 特にエラー戻りパスで LOGE が使用されているか確認します
- すべての分岐を特定します:
不足の分類:
- 優先度:高:LOGE がないエラー戻りパス
- 優先度:中:複数段階の操作で LOGI がない成功パス
- 優先度:低:ログ出力がない分岐(重大ではない)
出力:場所を示したログ不足の一覧
ステップ 05:高頻度ログのリスクを検出する
説明:頻繁に呼び出される可能性がある LOGE/LOGI を含む関数を特定します
アクション:
- 高頻度関数のパターンを特定します:
- ネットワークデータのコールバック(
OnDataReceived、OnPacketReceived、OnMessage) - タイマーコールバック(
OnTimer、Tick、Update) - イベントハンドラー(
HandleEvent、ProcessEvent、OnEvent) - ループ処理(
ProcessItem、HandlePacket、SendData) - ストリーム処理(
ProcessStream、HandleFrame、EncodeFrame) - メッセージキューハンドラー(
OnMessage、Dispatch)
- ネットワークデータのコールバック(
- これらのパターンに該当し、LOGE/LOGI を含む関数について:
- 呼び出し頻度の可能性を分析します
- リスクレベルを分類します:高/中/低
- 高頻度リスクとしてフラグを付けます
リスク分類:
- 高リスク:データパスでパケット/フレームごとに LOGE/LOGI を出力
- 中リスク:メッセージングパスでメッセージごとに LOGI を出力
- 低リスク:ログを出力する頻度の低いコールバック
出力:高頻度リスクの一覧と該当箇所
ステップ 06:分析レポートを生成する
説明:すべての分析結果を含む包括的なレポートを作成します
アクション:
- 次の内容を含む Markdown レポートを生成します:
- 統計の概要
- ログの不足箇所と修正案
- 高頻度リスクと修正案
- 呼び出しチェーンの分析
- 詳細なコード例
Writeツールを使用して、レポートをlog-coverage-report-YYYYMMDD-HHmmss.mdに保存します
出力:完全な分析レポート
言語別パターン
C/C++
関数定義パターン:
[return_type] [class::]function_name([parameters]) {
[\w\s:*,]*\{
ログパターン:
LOG[DEIW]\(、HILOG[DEIW]\(、ALOG[DEIW]\(__android_log_printOHOS::HiviewDFX::HiLog::[Error|Warn|Info|Debug]
Java
関数定義パターン:
(public|private|protected)?(\s+static)?\s+\w+\s+\w+\s*\(.*\)\s*(throws\s+[\w\s,]+)?\s*\{
ログパターン:
Log\.[deiw]\(Logger\.(error|warn|info|debug)\(Timber\.[deiw]\(
Python
関数定義パターン:
def\s+\w+\s*\(.*\)\s*->?\s*.*:
ログパターン:
logger\.(error|warning|info|debug)\(logging\.(error|warning|info|debug)\(print\(
JavaScript/TypeScript
関数定義パターン:
function\s+\w+\s*\(.*\)\s*\{
|\w+\s*\([^)]*\)\s*(=>|\{)
ログパターン:
console\.(error|warn|info|log)\(logger\.(error|warn|info|debug)\(
修正の推奨事項
ログの不足箇所について
エラーの戻りパス(修正必須):
// BEFORE:
if (remote == nullptr) {
return ERR_NULL_OBJECT; // ❌ No LOGE
}
// AFTER:
if (remote == nullptr) {
HILOGE("FunctionName: remote is null, context=%{public}d", context);
return ERR_NULL_OBJECT;
}
成功パス(修正推奨):
// BEFORE:
int32_t CreateSession(...) {
// ... initialization code
return ERR_OK; // ❌ No LOGI on success
}
// AFTER:
int32_t CreateSession(...) {
// ... initialization code
HILOGI("CreateSession: success, sessionId=%{public}d, name=%{public}s", id, name);
return ERR_OK;
}
高頻度リスクについて
高頻度の LOGI を削除する:
// BEFORE:
void OnPacketReceived(int socketId, const void* data, uint32_t len) {
HILOGI("packet received: socket=%{public}d, len=%{public}u", socketId, len); // ⚠️ Per-packet
// ... process packet
}
// AFTER:
void OnPacketReceived(int socketId, const void* data, uint32_t len) {
// Removed per-packet LOGI
static std::atomic<uint64_t> packetCount{0};
if (++packetCount % 1000 == 1) {
HILOGI("Packet stats: count=%{public}llu, socket=%{public}d",
packetCount.load(), socketId);
}
// ... process packet
}
エラーにはスロットル付き LOGE を使用する:
// BEFORE:
void ProcessPacket(const Packet* pkt) {
if (pkt == nullptr) {
HILOGE("packet is null"); // ⚠️ Per-packet error
return;
}
}
// AFTER:
void ProcessPacket(const Packet* pkt) {
if (pkt == nullptr) {
static std::atomic<uint32_t> errorCount{0};
if (++errorCount % 100 == 1) {
HILOGE("ProcessPacket: null packet, count=%{public}u", errorCount.load());
}
return;
}
}
出力形式
================================================================================
Log Coverage Analysis Report
================================================================================
Repository: <repository_path>
Analysis Date: <timestamp>
Files Analyzed: <count>
## Summary Statistics
| Metric | Count |
|--------|-------|
| Total Source Files | <number> |
| Total Functions | <number> |
| Functions Analyzed | <number> |
| Log Deficiencies | <number> |
| High-Frequency Risks | <number> |
## Log Deficiencies
### [High/Medium/Low] Priority
**File**: `<file_path>`
**Function**: `<function_name>`
**Lines**: `<line_range>`
**Issue**: `<description>`
**Evidence**:
```cpp
<code snippet>
影響: <デバッグ/トラブルシューティングへの影響を説明>
修正:
<fixed code>
高頻度リスク
[高/中/低] リスク
ファイル:<file_path>
関数:<function_name>
行:<line_range>
リスク:<説明>
根拠:
<code snippet>
分析: <高頻度である理由を説明>
修正:
<fixed code with throttling/statistics>
呼び出しチェーンの分析
呼び出しチェーン:<chain_name>
<function_1>()
↓ [✓/✗/⚠️] <log_status>
<function_2>()
↓ [✓/✗/⚠️] <log_status>
<function_3>()
├─ [✓/✗/⚠️] branch_1
├─ [✓/✗/⚠️] branch_2
└─ [✓/✗/⚠️] branch_3
凡例:
- ✓ :必要な LOGE/LOGI あり
- ✗ :必要なログ出力なし
- ⚠️ :高頻度ログのリスクあり
推奨事項
直ちに実施する対応(P0)
<重要な項目の一覧>
フォローアップ対応(P1)
<優先度の高い項目の一覧>
長期的な改善(P2)
<改善案の一覧>
================================================================================
## Parameters
| Parameter | Required | Description |
|-----------|----------|-------------|
| `--path` | No | Repository path (default: current directory) |
| `--exclude-tests` | No | Exclude test files (default: true) |
| `--lang` | No | Language filter (cpp, java, python, js, all) |
| `--output` | No | Output report path |
## Usage Examples
現在のディレクトリを分析
/log-coverage-analyzer
特定のリポジトリを分析
/log-coverage-analyzer --path /path/to/repo
C++ コードのみを分析
/log-coverage-analyzer --lang cpp --path /path/to/repo
分析にテストファイルを含める
/log-coverage-analyzer --exclude-tests false
出力先をカスタマイズ
/log-coverage-analyzer --output /path/to/report.md
## Tips
- Use `Grep` with `output_mode: content` and `-B/-C` flags for context
- Use `Read` tool with `offset` and `limit` for large files
- For large repositories, focus on critical directories first
- High-frequency risks should be prioritized over minor log deficiencies
- Always include context (IDs, states, parameters) in LOGE messages