mcpField
S
sap-unused-code

sap-unused-code

github.com/arc-mcp开发239252 次安装2 天前更新
代码仓库

关于 sap-unused-code

sap-unused-code 是用于 SAP 自定义代码退役审查的技能,结合 SCMON/SUSG 运行数据与静态引用分析,对限定范围内的对象分类。它要求先提供包、命名空间、对象清单或意图,且不会删除代码。

主要功能

  1. 01结合运行时数据与静态引用
  2. 02按四类结果分类对象
  3. 03支持 SCMON 与 SUSG 数据
  4. 04要求明确审计范围
  5. 05提供对象级使用计数

适用场景

  1. 01评估特定包中的自定义代码是否可退役
  2. 02筛查指定命名空间内未运行的对象
  3. 03结合静态调用关系审查删除候选项

MCP 相关

此技能通过 ARC-1 访问 SAP 系统,使用 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 系统中生成“列出所有未使用代码”的报告,会返回数万行,毫无用处。用户必须至少提供以下一项:

  • 包(例如,Z_FI_CUSTOM)——仅分析此包中的对象
  • 命名空间前缀(例如,Z_SALES_*、/ACME/*)——仅分析匹配此模式的对象
  • 对象列表——以逗号分隔的待检查名称
  • 意图说明——例如,“查找 90 天内未运行过的 FI-GL 中的 Z 报表”——按目的缩小范围

如果用户未提供任何一项,请先询问。例如:

你要审计哪个包或命名空间?例如:“Z_REPORTING 包”、“所有以 Z_FI_ 开头的 Z* 对象”,或“我准备删除的这 15 个报表”。

这比看起来更复杂的原因(提出方案前请先阅读)

SAP 有两个相关的监控系统。请先确认你要使用哪一个:

系统说明数据存放位置延迟数据保留期限
SCMON(ABAP 调用监控器)每次调用的原始计数器SCMON_DATA + SCMON_PROG + SCMON_SUB + SCMON_RDATA 表激活期间实时滚动保留约 7 天
SUSG(使用统计生成器)基于 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 会拒绝汇总。在开发/测试系统中,这会导致数据管道频繁中断。

三种选项(根据系统状态选择)

选项 A(首选)——通过 ARC-1 直接联接 SCMON 表

只要 SCMON 曾在系统上激活过,此选项即可立即使用,无论是否运行过 SUSG 汇总。

-- "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 的四类分类;便于确定优先级
使用位置检查是,针对未在运行时观察到的对象静态引用是有效信号
报告粒度按对象列出计数;前 20 项 + 摘要可按需提供完整列表

前提条件

请预先检查以下事项。如果有任何一项缺失,请停止并告知用户。

  1. ARC-1 服务器上已设置 SAP_ALLOW_FREE_SQL=true(否则 SAPQuery 会被阻止——它会运行 FreeSQL)。如有需要,请咨询管理员。
  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")

如果两者都没有返回数据,则尚未进行数据收集。请引导用户查看下一节,然后停止。

如果客户还没有 SCMON/SUSG 数据

告知他们:

  1. SAP GUI:事务码 SCMON → 激活监控器 → 让它运行 N 天(7 天是常见的最低时长)
  2. 事务码 SCMONL 显示时间片状态;SCMOND 显示原始数据
  3. 如需永久保存数据:将 SCMON_COLLECT 设为每日作业,然后运行 SUSG_COLLECT_FROM_SCMON
  4. 数据开始流入后,重新运行此技能

第 1 步:探测要使用的选项

运行上述两个 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 前缀的对象。(SCMON/SUSG 无法直接捕获表、CDS 视图和接口以“在运行时被调用”的方式使用。)

2b. 命名空间 / 前缀

SAPSearch 只接受单个 objectType 筛选条件——对每种运行时类型分别调用一次,然后合并结果:

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

如果 LIKELY_UNUSED 对象的所有调用方都是 UNUSED,则可传递删除该对象。只要有一个活跃调用方,就不能删除。

6d. 后续选项
  • “想以树形结构查看静态引用图吗?”(→ 链式调用 SAPNavigate where-used)
  • “想先对 USED 对象进行 clean-core 检查,再考虑未使用的对象吗?”(→ sap-clean-core-atc)
  • “想查看 USED 对象的文档吗?”(→ 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,并接受会损失一个汇总周期
SAP_ALLOW_FREE_SQL=false管理员策略要么申请放宽限制,要么退回到 SAPRead(type="TABLE_CONTENTS", name="SCMON_DATA", maxRows=…)(也会被 SAP_ALLOW_DATA_PREVIEW=false 阻止;无论如何都不能进行联接)——报告质量会大幅下降
访问 SCMON_* / SUSG_* 表时返回 403缺少 S_TABU_NAM 授权用户需要获得授权;在申请中列出相关表
范围返回超过 500 个候选对象用户的筛选条件过于宽泛拒绝;请用户缩小范围(500 个对象的删除清单无法实际执行)

注意事项

运行时数据无法告诉你的内容
  • 覆盖缺口:每年年末运行一次的报告不会出现在一周的 SCMON 数据中。务必结合观察窗口与对象的预期使用频率进行判断。
  • 死代码检测 ≠ 代码消除:UNUSED 对象可能是应急/灾难恢复代码、仅在考试期间使用的代码,或由观察窗口期间未运行的计划作业调用。删除前请与业务负责人核实。
  • 动态调用:CALL FUNCTION IN BACKGROUND、使用动态程序名的 SUBMIT,或通过 RTTI 调用的 CALL METHOD,可能无法在 SCMON 中归因到正确的 PROGNAME。无法避免出现一些误判为 UNUSED 的对象。
此技能不会执行的操作
  • 不删除。 仅生成报告。删除必须由人工决定,最好通过传输请求和 CTS 完成。
  • 不合并跨系统数据(DEV + QAS + PRD 的使用情况)。这需要导出每个系统的数据;此技能一次只读取一个系统。
  • 不提供已弃用但仍在使用的代码的替代建议。 如需此功能,请使用 sap-clean-core-atc。
  • 不导入 XML(选项 C)。如果客户只有 SUSG XML 转储文件,则需要使用离线解析器。
何时使用此技能
  • 为自定义代码退役项目确定范围
  • 迁移前——不要迁移未使用的内容
  • 项目结束后的清理——移除为已回滚功能编写的代码
  • 需要死代码清单的许可证/合规性审查
  • **与 sap-clean-core-atc 结合使用:**迁移 USED Level-A 代码,审计 USED Level-C/D 代码,彻底删除 UNUSED 代码

评论

支持 Markdown