mcpField
S
sap-unused-code

sap-unused-code

github.com/arc-mcp開発239252 回インストール2 日前に更新
リポジトリ

sap-unused-code について

sap-unused-code は、SCMON/SUSG の実行データと静的参照を組み合わせ、対象を分類する SAP カスタムコード退役審査用スキルです。パッケージ、名前空間、オブジェクト一覧、または目的による範囲指定が必要で、コードの削除は行いません。

主な機能

  1. 01実行データと静的参照の併用
  2. 02オブジェクトを4分類で判定
  3. 03SCMON または SUSG データの利用
  4. 04明示的な監査範囲の指定
  5. 05オブジェクトごとの実行数表示

活用シーン

  1. 01特定パッケージのカスタムコード退役を評価
  2. 02名前空間内で実行記録のないオブジェクトを確認
  3. 03静的呼び出し元も含めて削除候補を審査

MCP 対応

このスキルは ARC-1 を介して SAP にアクセスし、クエリ、検索、読み取り、参照ナビゲーション機能を使って分析します。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/arc-mcp/arc-1 --skill sap-unused-code

インストール後、Claude Code で/sap-unused-codeを入力して読み込まれたか確認します。

詳細

SAP 未使用コードの検出

実行時に一度も呼び出されていない Z/Y カスタムオブジェクトを特定します。これは、信頼性の高いカスタムコード廃止プロジェクトの前提条件です。SAP のコールモニター(SCMON)の実行時使用データと、静的な使用箇所検索を組み合わせ、各オブジェクトを UNUSED / LIKELY_UNUSED / USED / INDETERMINATE に分類します。

⚠ 必須:スコープと目的

このスキルは、フィルターが指定されていない場合は実行されません。 ECC システム全体を対象に「未使用コードをすべて一覧表示する」レポートを作成すると、数万行が返され、役に立ちません。ユーザーは、次のいずれかを少なくとも 1 つ指定する必要があります。

  • パッケージ(例:Z_FI_CUSTOM)— このパッケージ内のオブジェクトのみを分析します
  • 名前空間プレフィックス(例:Z_SALES_*、/ACME/*)— パターンに一致するオブジェクトのみを対象にします
  • オブジェクトリスト — チェックする名前をカンマ区切りで指定します
  • 目的の説明 — 例:「過去 90 日間に実行されていない FI-GL の Z レポートを見つける」—目的で絞り込みます

いずれも指定されていない場合は、質問してください。確認の質問例:

監査するパッケージまたは名前空間を教えてください。例:「Z_REPORTING パッケージ」、「Z_FI_ で始まるすべての Z*」、または「削除を予定しているこの 15 個のレポート」。

見た目以上に難しい理由(計画を提案する前にお読みください)

SAP には、関連する監視システムが 2 つあります。どちらを扱っているかを理解してください。

システム概要データの保存場所遅延データの保持期間
SCMON(ABAP Call Monitor)呼び出しごとの生カウンターSCMON_DATA + SCMON_PROG + SCMON_SUB + SCMON_RDATA テーブル有効時はリアルタイム約 7 日間のローリング保存
SUSG(Usage Statistics Generator)SCMON の日次集計SUSG_DATA + SUSG_PROG + SUSG_RDATA + SUSG_SUB + SUSG_ADMIN テーブル(または CDS ビュー SUSG_I_DATA、SUSG_I_RDATA、SUSG_I_ODATA)バッチスケジュールに依存(デフォルトは毎日約 02:30)数か月から数年間

重要な制約: レコード数のしきい値に達すると、SCMON は自動的に無効になります(SCMON_CONF_SET_MAX_NUM_SLICES)。集計対象期間に SCMON が無効だった場合、SUSG は集計を拒否します。開発/テストシステムでは、このためパイプラインが頻繁に停止します。

3 つの選択肢(システムの状態に応じて選択)

オプション A(推奨)— ARC-1 経由で SCMON テーブルを直接結合

SUSG の集計が実行されたかどうかにかかわらず、SCMON が一度でも有効になったシステムならすぐに利用できます。

-- "Which programs actually ran?"
SELECT p~PROGNAME, p~OBJECT, p~OBJ_NAME, SUM( d~COUNTER ) AS EXECS
FROM SCMON_DATA AS d INNER JOIN SCMON_PROG AS p ON d~TRIGID = p~PROGID
WHERE <filter>
GROUP BY p~PROGNAME, p~OBJECT, p~OBJ_NAME
ORDER BY EXECS DESCENDING
-- "Which transactions/reports triggered anything?"
SELECT s~ROOTNAME, s~ROOTTYPE, SUM( d~COUNTER ) AS EXECS
FROM SCMON_DATA AS d INNER JOIN SCMON_SUB AS s ON d~SUBID = s~SUBID
GROUP BY s~ROOTNAME, s~ROOTTYPE

列に関する注意(SAP の命名は逆になっています):

  • SCMON_DATA.TRIGID → SCMON_PROG.PROGID(名前とは異なり、実行されたプログラム)
  • SCMON_DATA.SUBID → SCMON_SUB.SUBID(トリガーの起点。開始元となったトランザクション/レポート)

メリット: バッチを待つ必要がなく、スライスをローテーションする手間もなく、今日すぐに実行できます。
デメリット: 保持期間が短く(約 7 日間)、「過去 6 か月間に実行されたか」といった質問には役立ちません。

オプション B — CDS ビュー経由の集計済み SUSG

顧客が SUSG を適切にスケジュールしている場合に使用します(通常、本番システムでは設定されています)。

-- Same question, longer window
SELECT PROGNAME, OBJ_TYPE, OBJ_NAME, SUM( COUNTER ) AS EXECS, MAX( LAST_USED ) AS LAST_SEEN
FROM SUSG_I_DATA
WHERE <filter>
GROUP BY PROGNAME, OBJ_TYPE, OBJ_NAME

事前結合済みの CDS ビュー:SUSG_I_DATA、SUSG_I_RDATA、SUSG_I_ODATA。いずれも @AccessControl.authorizationCheck: #NOT_REQUIRED です。

メリット: より長い履歴(数か月分)があり、事前に結合されているため SQL が簡潔で、公式にサポートされているデータです。
デメリット: SUSG バッチの実行が必要です(実行されるまでは SUSG の行数は 0)。対象期間中に SCMON が無効になっていた場合は、何も機能しません。

オプション C — SUSG XML の手動エクスポート(最終手段のみ)

顧客がすでにトランザクション SUSG を実行し、5 つの XML ファイル(ADMIN0001.xml、PROG0001.xml、DATA*.xml、RDATA*.xml、SUB0001.xml)をエクスポートしている場合、このスキルでローカルに解析できます。これは Kiro の方法であり、最後の手段にしてください。SAP GUI での人手による操作と、オフラインでのファイル受け渡しが必要です。

このスキルには XML パーサーは含まれていません。ユーザーがオプション C を希望する場合は、Kiro の parse-susg.py を使用するか、ローカルの Python スクリプトを作成するよう伝えてください。ARC-1 では対応できません。

スマートデフォルト(黙って適用し、質問しない)

設定デフォルト根拠
オプションの選択まず SCMON の稼働状況を確認し、ライブデータがあれば A、なければ B を使用しますほとんどのシステムには、どちらか一方があります
出力の分類UNUSED / LIKELY_UNUSED / USED / INDETERMINATEKiro の 4 種類の分類です。優先順位付けに役立ちます
使用箇所の確認はい。実行時に確認されなかったオブジェクトが対象です静的参照も有効なシグナルです
レポートの詳細度オブジェクトごとに件数を表示し、上位 20 件と概要を示しますご要望があれば全件を表示できます

前提条件

事前に確認してください。不足している項目があれば、処理を停止してユーザーに伝えてください。

  1. ARC-1 サーバーで SAP_ALLOW_FREE_SQL=true が設定されていること(設定されていない場合、FreeSQL を実行する SAPQuery はブロックされます)。必要に応じて管理者に確認してください。
  2. ユーザーが SCMON_DATA、SCMON_PROG、SCMON_SUB、SCMON_RDATA に対する S_TABU_NAM 権限を持っていること(オプション B の場合は、同等の SUSG テーブルが対象です)。
  3. SCMON が過去に一度でも有効化されていること(オプション A)、または SUSG の集計が実行済みであること(オプション B)。次のクエリで確認します。
SAPQuery(sql="SELECT COUNT(*) AS CNT FROM SCMON_DATA")
SAPQuery(sql="SELECT COUNT(*) AS CNT FROM SUSG_I_DATA")

どちらも 0 行の場合、データ収集が行われていません。次のセクションをユーザーに案内して、処理を停止してください。

顧客に SCMON/SUSG データがまだない場合

次のように伝えてください。

  1. SAP GUI でトランザクション SCMON を実行し、モニターを有効化して、N 日間稼働させます(最低 7 日間が一般的です)。
  2. トランザクション SCMONL ではスライスの状態を、SCMOND では生データを確認できます。
  3. データを永続的に保持するには、SCMON_COLLECT を日次ジョブとしてスケジュールし、その後に SUSG_COLLECT_FROM_SCMON を実行します。
  4. データ収集が始まったら、このスキルを再実行します。

ステップ 1:使用するオプションを確認する

上記の 2 つの COUNT クエリを実行します。判定表は次のとおりです。

SCMON_DATA の件数SUSG_I_DATA の件数使用するオプション
> 0> 0A(データが新しく、リアルタイムです)。ただし、より長期間の履歴には B も使用できることを伝えます
> 00A(SUSG による集計がまだ行われていません)
0> 0B(SCMON のデータは期限切れですが、SUSG に履歴があります)
00停止します。 SCMON を有効化するようユーザーに伝え、推測で進めないでください。

ステップ 2:対象範囲を列挙する

ユーザーが指定したフィルター入力に基づいて処理します。

2a. パッケージ
SAPRead(type="DEVC", name="<package>")

実行時の型(PROG、CLAS、FUGR、FUNC)のうち、Z/Y で始まるオブジェクトだけを残します。(テーブル、CDS ビュー、インターフェースは、SCMON/SUSG が直接捕捉する「実行時に呼び出される」オブジェクトではありません。)

2b. 名前空間/プレフィックス

SAPSearch では objectType フィルターを 1 つだけ指定できるため、実行時の型ごとに呼び出して結果を統合します。

SAPSearch(query="<prefix>*", objectType="PROG")
SAPSearch(query="<prefix>*", objectType="CLAS")
SAPSearch(query="<prefix>*", objectType="FUGR")
2c. オブジェクトリスト

指定された名前をそのまま使用します。

これを セット S(候補リスト)と呼びます。

ステップ 3:実行時の使用状況をクエリする

オプション A(SCMON の直接結合)

セット S から WHERE 句を作成します。SAP FreeSQL にはクエリ長の制限があるため、|S| > 100 の場合は分割します。

SELECT p~PROGNAME, p~OBJECT, p~OBJ_NAME, SUM( d~COUNTER ) AS EXECS
FROM SCMON_DATA AS d INNER JOIN SCMON_PROG AS p ON d~TRIGID = p~PROGID
WHERE p~OBJ_NAME IN ( 'ZCL_FOO', 'ZR_BAR', ... )   -- or  p~OBJ_NAME LIKE 'Z_FI_%'
GROUP BY p~PROGNAME, p~OBJECT, p~OBJ_NAME

トリガー側も確認します(Z オブジェクトの中には、内部呼び出し元としてではなく、トランザクション/RFC としてのみ実行されるものがあります)。

SELECT s~ROOTNAME, s~ROOTTYPE, SUM( d~COUNTER ) AS EXECS
FROM SCMON_DATA AS d INNER JOIN SCMON_SUB AS s ON d~SUBID = s~SUBID
WHERE s~ROOTNAME IN ( ... )

結果を統合します。セット U(実行時に使用されたオブジェクトとその件数)を作成します。

オプション B(SUSG)
SELECT PROGNAME, OBJ_TYPE, OBJ_NAME, SUM( COUNTER ) AS EXECS, MAX( LAST_USED ) AS LAST_SEEN
FROM SUSG_I_DATA
WHERE <scope filter>
GROUP BY PROGNAME, OBJ_TYPE, OBJ_NAME

セット U を作成し、LAST_SEEN タイムスタンプも含めます。

ステップ 4:U に含まれないオブジェクトの静的な使用箇所を確認する

S に含まれていて U に含まれていない各オブジェクトについて、次を実行します。

SAPNavigate(action="references", type="<type>", name="<name>")

(references は ARC-1 の使用箇所検索アクションで、内部で SAP の使用箇所検索 API を呼び出します。)

セット W(ソース内から参照されている静的参照オブジェクト。観測期間中に実行されていなくても、何らかのコードから呼び出されています)を作成します。

ステップ 5:分類する

最初に一致した分類を適用します。

オブジェクトの該当先分類意味
U(実行時に 1 回以上実行)USED本番環境で実行されています。保持してください
W(ソース内で参照されているが、U には含まれない)LIKELY_UNUSED静的な呼び出し元はありますが、観測期間中に実行されたものはありません
U にも W にも該当しないUNUSED削除候補として有力です
S には含まれるが、システム上にオブジェクトが存在しない(例:SAPSearch で解決できなかった)INDETERMINATE手動で確認してください

ステップ 6:レポートを出力する

6a. 見出し
Unused Code Audit — <scope>
Data source: SCMON (2,843 rows, window: 2026-04-12 → 2026-04-19)   ← Option A
  — or —
Data source: SUSG (Aggregated 2026-01-01 → 2026-04-19, 128 days)    ← Option B

Scope:         42 objects
  USED:          18  (43%)  — safe to keep
  LIKELY_UNUSED: 12  (29%)  — still has static callers; investigate
  UNUSED:        10  (24%)  — deletion candidates
  INDETERMINATE:  2   (5%)  — manual review
6b. UNUSED テーブル(削除候補)
Object                  Type  Package           Last change (TR)
ZR_OLD_FI_POSTING       PROG  Z_FI_CUSTOM       2024-02-15 (MARIAN / A4HK900042)
ZCL_LEGACY_HELPER       CLAS  Z_FI_CUSTOM       2023-11-03 (MARIAN / A4HK900031)
...

「最終変更」は SAPRead(type="VERSIONS") から取得します。古く、かつ未使用のオブジェクトが最も安全に削除できます。

6c. 呼び出し元のヒントを含む LIKELY_UNUSED テーブル

LIKELY_UNUSED オブジェクトごとに、参照しているオブジェクトを示します。

ZCL_OLD_SALES_UTILS  (CLAS)
  Called by:  ZR_SALES_JOB (PROG — also UNUSED — cascade delete)
              ZCL_ACTIVE_HANDLER (CLAS — USED at runtime) ← blocks deletion

呼び出し元がすべて UNUSED の LIKELY_UNUSED オブジェクトは、依存関係をたどって削除できます。アクティブな呼び出し元が 1 つでもあれば、削除はできません。

6d. 次のステップの選択肢
  • 「静的参照グラフをツリー形式で表示しますか?」(→ SAPNavigate where-used を連続実行)
  • 「未使用オブジェクトに取りかかる前に、使用中のオブジェクトをクリーンコアチェックしますか?」(→ sap-clean-core-atc)
  • 「使用中のオブジェクトのドキュメントを表示しますか?」(→ sap-object-documenter)
  • 「これをレビュー済みの S/4HANA 移行ドシエにして、HTML/CSV/グラフ形式で出力しますか?」(→ sap-migration-dossier)
  • 「UNUSED オブジェクトの削除を始めますか?」→ 手動で行ってください。このスキルは何も削除しません。ユーザーが SAPWrite または移送を通じて削除します。

エラー処理

症状根本原因対処方法
SCMON_DATA の件数 = 0、SUSG_I_DATA の件数 = 0モニタリングが一度も有効化されていない停止し、SCMON を有効化するようユーザーに案内します(上記の手順を参照)
SCMON にデータがあるが、すべて SLICEID=1 で SUSG は 0スライスがまだ切り替わっていない。SUSG は未クローズのスライスを集計できないオプション A(直接)を使用して SUSG をスキップするか、SA38 から SCMON_COLLECT_ALL を実行してから SUSG_COLLECT_FROM_SCMON を実行します
SUSG_LOG に「SCMON not active」と表示されるSCMON が自動的に無効化された(レコード数のしきい値に到達)SCMON_CONF_SET_MAX_NUM_SLICES でしきい値を引き上げ、SCMON を再有効化します。集計サイクルが 1 回失われたことは受け入れてください
SAP_ALLOW_FREE_SQL=false管理者ポリシー制限の緩和を依頼するか、SAPRead(type="TABLE_CONTENTS", name="SCMON_DATA", maxRows=…) に切り替えます(SAP_ALLOW_DATA_PREVIEW=false の場合もブロックされます。どちらの場合も結合はできません)。レポートの品質は大きく低下します
SCMON_*/SUSG_* テーブルで 403S_TABU_NAM 認可が不足しているユーザーに認可の割り当てを依頼し、申請に対象テーブルを記載します
対象範囲から 500 件を超える候補が返されるユーザーのフィルター範囲が広すぎる拒否し、対象を絞るようユーザーに依頼します(500 件のオブジェクト削除リストは実行に移せません)

注意事項

ランタイムデータからはわからないこと
  • カバレッジの欠落:年末に毎年実行されるレポートは、1 週間分の SCMON データには現れません。観測期間とオブジェクトの想定使用頻度を常に考慮してください。
  • デッドコード検出 ≠ コード削除:UNUSED オブジェクトは、緊急時/災害復旧用のコード、試験期間中のみ使用するコード、または観測期間中に実行されなかったスケジュールジョブから呼び出されるコードである可能性があります。削除前に業務担当者に確認してください。
  • 動的呼び出し:CALL FUNCTION IN BACKGROUND、動的なプログラム名を指定する SUBMIT、または RTTI 経由の CALL METHOD では、SCMON が正しい PROGNAME に帰属させられない場合があります。誤って UNUSED と判定されるケースを完全になくすことはできません。
このスキルで行わないこと
  • 削除は行いません。 レポートのみを作成します。削除は人が判断し、できれば移送と CTS を通じて行う必要があります。
  • システム間の統合は行いません(DEV + QAS + PRD の使用状況)。各システムからのエクスポートが必要です。このスキルは一度に 1 つのシステムのみを読み取ります。
  • 非推奨だが使用中のコードに対する置き換え案の提示は行いません。 その場合は sap-clean-core-atc を使用してください。
  • XML のインポートは行いません(オプション C)。顧客が SUSG の XML ダンプのみを持っている場合は、オフラインパーサーが必要です。
このスキルを使用する場面
  • カスタムコードの廃止プロジェクトの対象範囲を定めるとき
  • 移行前:使用していないものは移行しない
  • プロジェクト後の整理:ロールバックされた機能向けに作成したコードを削除するとき
  • デッドコードの一覧が必要なライセンス/コンプライアンスレビュー
  • sap-clean-core-atc と組み合わせる場合: 使用中のレベル A コードを移行し、使用中のレベル C/D コードを監査し、UNUSED コードを完全に削除します

コメント