内容
# filtrace
[](https://github.com/JeremyKuhne/filtrace/actions/workflows/ci.yml)
[](https://www.nuget.org/packages/KlutzyNinja.Filtrace)
[](https://www.nuget.org/packages/KlutzyNinja.Filtrace.Mcp)
[](LICENSE)
一款用于分析.NET CPU、内存分配、阻塞和时钟跟踪的小型、类似代理的CLI和MCP服务器。基于`Microsoft.Diagnostics.Tracing.TraceEvent`库;读取EventPipe(`.nettrace` / `.speedscope.json`)和ETW(`.etl`)捕获来自.NET和.NET Framework运行时。
## 安装
filtrace 针对 **.NET 10**。两个版本都发布在NuGet.org上:[`KlutzyNinja.Filtrace`](https://www.nuget.org/packages/KlutzyNinja.Filtrace)(`filtrace` CLI)和[`KlutzyNinja.Filtrace.Mcp`](https://www.nuget.org/packages/KlutzyNinja.Filtrace.Mcp)(MCP服务器)。
### CLI(全局工具)
作为.NET全局工具安装CLI需要.NET 10 SDK(`dotnet tool`随它一起提供):
```pwsh
dotnet tool install --global KlutzyNinja.Filtrace
filtrace cpu app.nettrace
```
更新或删除它:`dotnet tool update --global KlutzyNinja.Filtrace` 或 `dotnet tool uninstall --global KlutzyNinja.Filtrace`.
### MCP服务器
MCP服务器按需运行 - 没有安装步骤。将stdio服务器添加到代理的MCP配置中,`dnx`(捆绑在.NET 10 SDK中)获取`KlutzyNinja.Filtrace.Mcp`并启动它。有关确切的配置块和工具工作流程,请参阅[从AI代理使用filtrace](#使用filtrace从AI代理)。
### 从源代码
```pwsh
dotnet pack src/Filtrace/Filtrace.csproj -c Release
dotnet tool install --global --add-source ./artifacts/packages KlutzyNinja.Filtrace
```
## 使用filtrace
每个分析动词都接受一个跟踪路径,并打印一个密集的文本报告(或使用`--format json`的紧凑JSON);`collect`启动它记录的可执行文件。规范的调查是 **orient -> rank -> drill -> compare**:检查捕获,排名匹配的指标,钻取无窗口的CPU排名(如果需要),然后将可比较的跟踪或捕获清单与基线进行比较。
```pwsh
# 工作流程:orient,排名最热的帧,钻取一个,然后比较两个运行。
filtrace info app.nettrace # 0. orient: 格式,提供者,事件计数,符号率
filtrace cpu app.nettrace # 1. 什么是热的(自时间)
filtrace callers app.nettrace MyApp.Parse # 2. 调用热帧的函数
filtrace lines app.nettrace --symbols bin/Release/net10.0 # 3. 热源代码行
filtrace diff before.nettrace after.nettrace # 4. 两个运行之间发生了什么变化
filtrace batch BenchmarkDotNet.Artifacts/filtrace-runs/run/manifest.json
```
相同的分析核心作为一个_stdio_ MCP服务器公开:每个分析动词都有一个匹配的`trace_*`工具(共十七个 - `info` -> `trace_info`, `rank` -> `trace_rank`, `callers` -> `trace_callers`等),返回相同的信封形状和结果。捕获和维护动词(`collect`, `convert`, `clean`)仅限CLI,扩展ETW分析的`--all-processes`也是如此;MCP支持自动或命名进程范围。有关客户端配置和工具工作流程,请参阅[从AI代理使用filtrace](#使用filtrace从AI代理)。
### 动词
**Orient** - 在排名之前查看捕获内容(CLI对应`trace_info`工具):
| 动词 | 目的 | 示例 |
|---|---|---|
| `info` | 格式,样本数,符号解析率,支持的分析,以及每个分析的捕获/事件状态 | `filtrace info app.nettrace` |
**排名** - 按指标(`rank`上的`--metric`,或快捷动词)对堆栈进行排名:
| 动词 | 排名内容 | 示例 |
|---|---|---|
| `rank` | 任何指标(`cpu`,`alloc`,`exceptions`,`threadtime`,`contention`,`wait`,`activity`) | `filtrace rank app.nettrace --metric contention` |
| `cpu` | CPU自/包含时间 | `filtrace cpu app.nettrace --measure inclusive` |
| `alloc` | 按站点分配的字节 | `filtrace alloc app.nettrace --top 10` |
| `exceptions` | 异常类型按计数;包含视图显示抛出路径 | `filtrace exceptions app.nettrace` |
| `threadtime` | 墙时钟(运行+阻塞),Windows `.etl` | `filtrace threadtime app.etl` |
每个排名动词都接受`--root`(作用于帧子树)和`--benchmark`(将BenchmarkDotNet捕获范围限定在测量的工作负载上,超出框架)。可以读取多进程ETW `.etl`的动词 - `cpu`,`threadtime`,`rank`,`callers`,`lines`,`heatmap`,`tree`,`classify`和时间线概述 - 还接受`--process` / `--all-processes`(默认自动作用于最繁忙的进程树,按CPU样本计数排名);`alloc`和`exceptions`仅读取单进程`.nettrace`,因此它们没有进程选项。要查看多进程捕获中包含的内容,请运行`filtrace processes`(如下)。`rank`动词添加两个作用域:`--activity <name>`(在单个启动-停止请求/作业中采取的CPU样本)和`--time <start>,<end>`(毫秒从跟踪开始,任意边界可选;`.nettrace` / `.etl`上的任何指标),以聚焦于单个请求或延迟峰值附近的切片。Speedscope输入仅聚合 `--time`,并警告窗口被忽略。
```pwsh
filtrace cpu bdn.nettrace --benchmark # 仅[基准]代码
filtrace alloc bdn.nettrace --benchmark # 工作负载下的分配
filtrace processes machinewide.etl # 按权重列出每个进程
filtrace cpu machinewide.etl --process MyApp # 一个进程树
filtrace rank app.nettrace --time 1000,5000 # 仅限峰值窗口
```
**本机运行时符号。**托管帧(包括NGEN和ReadyToRun框架方法)免费从跟踪的CLR运行时解析。* unmanaged *运行时帧 - GC,JIT,`memset` / `memcpy`,写入屏障 - 需要来自Microsoft公共符号服务器的PDB,当您使用`--native-symbols`选择加入时,`cpu` / `rank`仅需(缓存存储在`--symbol-cache`下,默认为临时路径)。默认情况下它是关闭的,因此分析保持离线和确定性;第一次运行下载,后续运行命中缓存。
```pwsh
filtrace cpu app.etl --process MyApp --native-symbols # 命名GC/JIT/memcpy帧
```
**CPU钻取** - 跟随无窗口的CPU排名到详细信息:
| 动词 | 目的 | 示例 |
|---|---|---|
| `callers` | 帧的直接CPU调用者,或带有`--callees`的调用者/被调用者视图 | `filtrace callers app.nettrace MyApp.Parse --callees` |
| `lines` | 作用域方法的热点CPU源代码行 | `filtrace lines app.nettrace --symbols bin/Release/net10.0` |
| `heatmap` | 单个源代码文件的每行CPU热图 | `filtrace heatmap app.nettrace Parser.cs` |
| `tree` | 从根开始的自顶向下的CPU调用树 | `filtrace tree app.nettrace --max-depth 5` |
**库存** - 查看捕获的内容(可能为整个机器):
| 动词 | 目的 | 示例 |
|---|---|---|
| `processes` | 按CPU样本权重列出进程,以选择 `--process`目标 | `filtrace processes machinewide.etl` |
| `classify` | 按运行时工作类别(清零/复制/GC/...)汇总CPU时间 | `filtrace classify app.etl --native-symbols` |
**时间** - 查看发生的时间,然后将排名范围限定在繁忙窗口:
| 动词 | 目的 | 示例 |
|---|---|---|
| `timeline` | 每个存储桶的GC / CPU /异常/分配/JIT活动随时间变化 | `filtrace timeline app.nettrace --lanes gc,cpu` |
**比较和导出:
| 动词 | 目的 | 示例 |
|---|---|---|
| `diff` | 跟踪或配对清单的绝对/归一化CPU更改 | `filtrace diff before.nettrace after.nettrace` |
| `batch` | 跨每个捕获-清单案例的紧凑排名 | `filtrace batch run/manifest.json` |
| `export` | 编写火焰图(speedscope / chromium) | `filtrace export app.nettrace --format speedscope -o app.json` |
**结构化报告:
| 动词 | 目的 | 示例 |
|---|---|---|
| `gcstats` | GC计数,暂停,GC中花费的时间,诱导,堆 | `filtrace gcstats app.nettrace` |
| `jitstats` | JIT方法计数,编译时间,大小 | `filtrace jitstats app.nettrace` |
| `threadpool` | 工作线程调整和饥饿(负载慢,CPU空闲) | `filtrace threadpool app.nettrace` |
| `diskio` | 物理磁盘I/O按文件:字节和磁盘服务时间(ETW) | `filtrace diskio app.etl` |
| `events` | 查询原始事件,按名称/有效负载/pid/tid过滤,分页 | `filtrace events app.etl --payload ConnectionReset` |
**捕获**(Windows,提升)- 自己记录ETW `.etl`,无需外部记录器:
| 动词 | 目的 | 示例 |
|---|---|---|
| `collect` | 启动可执行文件并记录CPU /线程时间`.etl` | `filtrace collect --launch bin/Release/net10.0/MyApp.exe --output myapp.etl --metric threadtime` |
```pwsh
filtrace collect --launch bin/Release/net10.0/MyApp.exe --output myapp.etl # CPU
filtrace collect --launch dotnet --launch-args MyApp.dll --output tt.etl --metric threadtime
filtrace collect --launch MyApp.exe --output ring.etl --max-size-mb 512 # 有界环形缓冲区
```
对于EventPipe(`.nettrace`)捕获 - 跨平台,无需提升 - 使用一流的`dotnet-trace`(`dotnet tool install -g dotnet-trace`,然后`dotnet-trace collect -- <app>`);`collect`仅限ETW。
**文件操作** - 管理ETLX转换缓存TraceEvent在跟踪旁边保存:
| 动词 | 目的 | 示例 |
|---|---|---|
| `convert` | 提前生成ETLX缓存 | `filtrace convert app.nettrace` |
| `clean` | 删除ETLX缓存以强制重建 | `filtrace clean app.nettrace` |
ETLX转换按规范的跟踪路径跨线程和进程协调,使用唯一临时文件和原子发布。相同的跟踪MCP查询可以并行运行;`trace_info.etlxCacheState`和`convert`报告`hit`,`waited`,`converted`或`recovered`.
运行`filtrace <verb> --help`获取任何动词的完整选项集。
<!-- filtrace:begin agents-snippet -->
## 从AI代理使用filtrace
filtrace是为代理中间调查而构建的。有两种方法可以将它连接起来:
- **MCP服务器** - 添加stdio服务器,以便代理直接调用`trace_*`工具:
```json
{
"servers": {
"filtrace": {
"type": "stdio",
"command": "dnx",
"args": ["KlutzyNinja.Filtrace.Mcp", "--yes"]
}
}
}
```
- **CLI** - 安装全局工具(`dotnet tool install -g KlutzyNinja.Filtrace`)并让代理外壳执行`filtrace <verb>`。
无论哪种方式,规范的循环都是 **orient -> rank -> drill -> compare**:读取`trace_info`(CLI:`filtrace info`)首先;当符号解析率低于0.8时,检查其警告和未解析行。将该视为帧名称质量;在使用源代码行分析之前,检查`sourceResolution`以获取确切的PDB模块,映射采样的托管帧,搜索目录,最高未映射模块和`pdbIdentityMismatchModules`。不匹配意味着找到同名本地PDB,但其GUID或年龄与跟踪中的不同。一旦相关模块匹配,请使用`sourceMappedManagedMethodCount`与`sampledManagedMethodCount`确认采样的方桉点解析;`unmappedNamedManagedFrameCount`和`highestUnmappedMethods`公开剩余的`<no source>`影响。使用生成的BenchmarkDotNet子输出,如果外部构建PDB不匹配;根据适用情况,为CPU ETW运行时帧使用本机符号。按匹配问题的指标进行排名(cpu,alloc,exceptions,threadtime,contention,wait,activity);对于无窗口的CPU排名,钻取热点帧的调用者/行/树;将可比较的CPU跟踪与基线进行比较。
<!-- filtrace:end agents-snippet -->
## 布局
| 路径 | 目的 |
|---|---|
| `src/Filtrace.Core/` | 分析核心:跟踪读取器,堆栈源提供者,提供者无关的问题服务引擎。逻辑的唯一位置。 |
| `src/Filtrace/` | CLI主机,封装为`filtrace` .NET全局工具。 |
| `src/Filtrace.Mcp/` | Stdio MCP主机,单独打包为`dnx KlutzyNinja.Filtrace.Mcp`。 |
| `tests/Filtrace.Core.Tests/` | 单元+黄金文件合同测试。 |
| `tests/Filtrace.Parity.Tests/` | 与冻结的旧版神谕的数值一致性测试。 |
| `eval/` | 无头代理评估托管,任务,基线(M5)。 |
| `docs/` | 用于技能/ README/帮助(M4)的单一源工作流文本。 |
| `.agents/skills/filtrace/` | 随附的代理技能。 |
## 自包含
filtrace带有自己的`Directory.Build.props`,`Directory.Build.targets`,`Directory.Packages.props`,`global.json`和`.editorconfig`(`root = true`),因此构建完全自包含。其唯一的外部依赖是发布的`KlutzyNinja.Touki` NuGet包;它不引用其他项目。
## 构建和测试(独立)
```pwsh
cd filtrace
dotnet build filtrace.slnx
dotnet test filtrace.slnx
```