# Etl Generator

> Run a target program under a CPU-sampling profiler and produce an ETL trace file for later performance analysis. Keywords - collect ETL, profile a program, generate etl, capture CPU trace, record ETL.

- Skill: `qualcomm/etl-generator` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add qualcomm/etl-generator`
- Raw SKILL.md: https://api.skillmd.com/api/skills/qualcomm/etl-generator/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Data & Analytics
- Author: qualcomm (https://skillmd.com/u/qualcomm)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/qualcomm/etl-generator

---


> ⚠️ Kernel CPU sampling requires an **elevated (Administrator) shell**. If the
> current agent harness (Codex, Claude Code, etc.) or its terminal is not running
> as Administrator, stop before ETL collection and tell the user to restart the
> harness from an elevated terminal. Do not attempt a workaround.
>
> ⚠️ Do NOT use xperf / WPR / WPA to collect. Use the bundled PerfView `run`
> flow below — it produces a merged, self-contained `.etl` that the
> `perf-sampling-parser` skill can parse directly.

# ETL Generator

Launch a program under PerfView's CPU sampler, wait for it to exit, and write a
merged `.etl` trace. This is the **capture** step that feeds the analysis
skills:

```
etl-generator  →  perf-sampling-parser  →  perf-optimizer
 (this skill)      (per-process CPU +      (root-cause +
                    speedscope export)      source optimization)
```

## Path Conventions

- `<skill_dir>`: directory containing this SKILL.md, derived from the path used
  to read this file.
- Collection script: `<skill_dir>/scripts/collect_etl.py`.
- PerfView is **not shipped here**: the script reuses the copy inside the
  sibling `perf-sampling-parser/scripts/PerfView.exe`. If that sibling is
  absent, pass `--perfview <path>` explicitly.

## Inputs

- **Required**: path to the program (`.exe`) to run and profile.
- **Optional**: arguments to pass to the program (`--args`).
- **Optional**: output `.etl` path (`--out`, default `<program_dir>/<stem>.etl`).
- **Optional**: working directory for the program (`--cwd`).

## Output

- A merged `.etl` file (default next to the program). This is a self-contained
  trace ready for `perf-sampling-parser`.

## Preconditions (check before running)

1. **Elevated shell.** Before collecting, confirm the current terminal is
   Administrator. On Windows PowerShell, use:

   ```powershell
   ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
   ```

   If it returns `False`, stop immediately. Tell the user to open an elevated
   terminal (`Start` -> search `PowerShell` or `Command Prompt` -> **Run as
   administrator**), start the agent harness from that elevated terminal
   (`codex`, `claude`, or their normal command), and resume from profiling with
   the same project/workload arguments. Do not continue to ETL collection,
   parsing, optimization, or any later profiling-dependent step from the
   non-elevated session.
2. **Program exits on its own.** PerfView `run` stops collecting when the target
   process exits. For a long-running / server program, either give it a
   workload that terminates, or warn the user that `--timeout-sec` will force a
   stop (which may leave the program killed).

## Steps

### Step 1: Collect the ETL

```bash
python "<skill_dir>/scripts/collect_etl.py" "<program.exe>" --args "<program args>" --out "<etl_path>"
```

- Blocks until the target program exits (or `--timeout-sec`, default 600s).
- Success marker: stdout contains `DONE ... OK` and ends with
  `[collect_etl] DONE — ETL written to: <path>`.
- On failure, the script prints the first 50 lines of
  `<etl_dir>/temp/pfv_collect_log.txt`; relay them to the user.

### Step 2: Hand off to analysis

Report the absolute `.etl` path. The natural next step is the
`perf-sampling-parser` skill (or `perf-optimizer`, which will invoke
`perf-sampling-parser` for you when given an `.etl`).

## Notes

- **Merged ETL**: the script passes `/Merge:true` so module and symbol-index
  information is folded into the single `.etl`. This makes the trace portable
  and lets the parser resolve modules without the original machine state.
- **No zip**: `/Zip:false` keeps a raw `.etl` (the parser expects `.etl`/`.etlx`,
  not `.etl.zip`).
- **Buffer size**: `/BufferSizeMB:256` reduces the chance of dropped CPU samples
  on busy machines; raise it for very hot, many-core workloads.
- **What is captured**: CPU stacks (the kernel `PROFILE` sampled-profile events)
  plus image/process/thread events — enough for per-process CPU attribution and
  call-stack flame graphs. It does not enable heap or context-switch tracing.

