# Xdebug Profiling

> >-

- **Type:** Skill
- **Install:** `agentstack add skill-trebormc-drupal-ai-agents-xdebug-profiling`
- **Verified:** Pending review
- **Seller:** [trebormc](https://agentstack.voostack.com/s/trebormc)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [trebormc](https://github.com/trebormc)
- **Source:** https://github.com/trebormc/drupal-ai-agents/tree/main/.claude/skills/xdebug-profiling

## Install

```sh
agentstack add skill-trebormc-drupal-ai-agents-xdebug-profiling
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

## Environment

All commands run via `ssh web`. Xdebug output is stored
inside the web container at `/tmp/xdebug/`. **Use `$DDEV_DOCROOT` for paths.**

## Two Modes

| Mode | Use for | Output | Analysis |
|------|---------|--------|----------|
| **trace** | Debug errors, trace execution path | `.xt` files (function calls, args, returns) | Read trace, find error origin |
| **profile** | Performance bottlenecks, slow pages | `cachegrind.out.*` files | Find slowest/most-called functions |

## Setup (run once per session)

```bash
ssh web mkdir -p /tmp/xdebug

# Verify Xdebug is available — expected output: "xdebug"
ssh web php -m | grep -i xdebug
```

If the grep output is EMPTY, do not invent paths: ask the user to run `ddev xdebug on` on the HOST, then re-check.

After EVERY config change below, verify it took effect:

```bash
ssh web php -i | grep "xdebug.mode"
```

## Workflow A: Trace Mode (Debug Errors)

### Step 1: Enable trace

```bash
ssh web bash -c "
  PHP_VER=\$(php -r 'echo PHP_MAJOR_VERSION.\".\".PHP_MINOR_VERSION;')
  cat > /etc/php/\${PHP_VER}/fpm/conf.d/99-xdebug-custom.ini  /tmp/analyze-trace.php"  $f[5], 'start' => (float) $f[3], 'file' => $f[8] ?? '', 'line' => $f[9] ?? ''];
  }
  elseif ($f[2] === '1' && isset($entries[$f[1]])) {
    $d = (float) $f[3] - $entries[$f[1]]['start'];
    $n = $entries[$f[1]]['name'];
    if (!isset($calls[$n])) {
      $calls[$n] = ['count' => 0, 'total' => 0, 'file' => $entries[$f[1]]['file'], 'line' => $entries[$f[1]]['line']];
    }
    $calls[$n]['count']++;
    $calls[$n]['total'] += $d;
  }
}
uasort($calls, fn($a, $b) => $b['total']  $a['total']);
printf("%-45s %6s %10s %s\n", 'Function', 'Calls', 'Time(s)', 'Location');
echo str_repeat('-', 90) . "\n";
foreach (array_slice($calls, 0, 25) as $n => $d) {
  printf("%-45s %6d %10.4f %s:%s\n", substr($n, 0, 45), $d['count'], $d['total'], basename($d['file']), $d['line']);
}
EOF
```

**3b. Find the trace file and run the analyzer:**

```bash
ssh web ls -lt /tmp/xdebug/trace.*.xt | head -3
# Replace TRACE_FILE with the newest filename from the listing above:
ssh web php /tmp/analyze-trace.php /tmp/xdebug/TRACE_FILE
```

### Step 4: Search for errors/patterns in trace

```bash
ssh web grep -n "Exception\|Error\|fatal" /tmp/xdebug/TRACE_FILE | head -20
ssh web grep "query\|execute\|select" /tmp/xdebug/TRACE_FILE | head -30
```

## Workflow B: Profile Mode (Performance Analysis)

### Step 1: Enable profiler

```bash
ssh web bash -c "
  PHP_VER=\$(php -r 'echo PHP_MAJOR_VERSION.\".\".PHP_MINOR_VERSION;')
  cat > /etc/php/\${PHP_VER}/fpm/conf.d/99-xdebug-custom.ini  /dev/null 2>&1)
  callgrind_annotate --inclusive=yes /tmp/xdebug/CACHEGRIND_FILE | head -80
"

# Or: quick PHP analysis of top 20 expensive functions.
# First write the analyzer script ONCE (copy EXACTLY — quoted 'EOF' prevents expansion):
ssh web "cat > /tmp/analyze-cachegrind.php"  $cost) {
  printf("%-55s %12d\n", substr($fn, 0, 55), $cost);
}
EOF

# Then run it (replace CACHEGRIND_FILE with the newest filename from ls):
ssh web php /tmp/analyze-cachegrind.php /tmp/xdebug/CACHEGRIND_FILE
```

## Workflow C: CLI Debugging (No PHP-FPM restart needed)

```bash
# Trace a Drush command (XDEBUG_MODE env var = single-command, zero impact)
ssh web bash -c 'XDEBUG_MODE=trace php -d xdebug.start_with_request=yes -d xdebug.output_dir=/tmp/xdebug -d xdebug.trace_format=1 -d xdebug.collect_return=1 -d xdebug.trace_output_name=trace.%t.%p drush cr'

# Profile a Drush command
ssh web bash -c 'XDEBUG_MODE=profile php -d xdebug.start_with_request=yes -d xdebug.output_dir=/tmp/xdebug -d xdebug.profiler_output_name=cachegrind.out.%t.%p drush status'
```

## ALWAYS: Disable and Cleanup

```bash
# Disable Xdebug (CRITICAL — leaving it on kills performance)
ssh web bash -c "
  PHP_VER=\$(php -r 'echo PHP_MAJOR_VERSION.\".\".PHP_MINOR_VERSION;')
  rm -f /etc/php/\${PHP_VER}/fpm/conf.d/99-xdebug-custom.ini
  kill -USR2 \$(pgrep -o php-fpm)
"

# Clean up output files
ssh web rm -rf /tmp/xdebug/*
```

## Quick Reference

| Problem | Mode | Action |
|---------|------|--------|
| Page error / 500 / white screen | trace | Find exception/error in trace output |
| Slow page / timeout | profile | Find top expensive functions in cachegrind |
| Drush command fails / slow | CLI workflow | No FPM restart needed |
| See execution path for URL | trace | Read full function call tree |

- **Always disable Xdebug after debugging** — it adds 20-50% overhead
- Trace files can be 100MB+ — use `head` or `grep` to filter
- For Playwright: add `?XDEBUG_TRIGGER=1` to the URL in `browser_navigate`
- Replace `TRACE_FILE` / `CACHEGRIND_FILE` with actual filenames from `ls`

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [trebormc](https://github.com/trebormc)
- **Source:** [trebormc/drupal-ai-agents](https://github.com/trebormc/drupal-ai-agents)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-trebormc-drupal-ai-agents-xdebug-profiling
- Seller: https://agentstack.voostack.com/s/trebormc
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
