Skip to main content
ClaudeWave
Skill0 estrellas del repoactualizado yesterday

octoperf-real-browser-probe

This skill enables hybrid load testing by pairing JMeter HTTP virtual users with a single Playwright real-browser probe to measure user-perceived metrics like page load time, rendering performance, and Core Web Vitals during load tests. Use it when you need to validate both server-side performance and client-side user experience simultaneously, especially for JavaScript-heavy applications where HTTP metrics alone miss frontend rendering costs.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/OctoPerf/octoperf-claude-plugins /tmp/octoperf-real-browser-probe && cp -r /tmp/octoperf-real-browser-probe/plugins/octoperf/skills/octoperf-real-browser-probe ~/.claude/skills/octoperf-real-browser-probe
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# OctoPerf — Real-browser probe alongside JMeter load

## The pattern

JMeter HTTP virtual users are great for server-side metrics (response
time, throughput, error rate) but they don't reflect what a real user
*perceives*: page load, JS execution, rendering, layout shifts, Core
Web Vitals. A **real-browser probe** is a single Playwright VU that
runs the same user journey through an actual Chromium during the load
test — measuring UX while the JMeter pool keeps the server busy.

Commercial equivalents (the LLM will recognise these terms): NeoLoad
*RealBrowser User*, LoadRunner *TruClient*, Gatling *Browser User*,
k6 *browser* module, BlazeMeter *Real Browser Users*. The pattern is
also known as **synthetic browser probe** or **end-user experience
monitoring during load test**.

## When this applies

The user has:

- A working OctoPerf JMeter Virtual User (validated clean) that they
  want to load-test.
- The need for **user-perceived metrics** during the test, not just
  server-side HTTP metrics — typically because the front-end is
  JS-heavy (SPA, React/Vue/Angular) and HTTP timings miss the
  client-side render cost.
- Optionally, an SLA framed around browser metrics (e.g. "TTFB < 200 ms
  AND LCP < 2.5 s under 50 concurrent users").

If the user just wants HTTP load (no UX measurement) → stick to
`run_scenario` on the JMeter VU. If the user wants *only* browser
testing without a load backdrop → just create the Playwright VU
without the JMeter one.

## Steps

### 1. Decide: direct translation vs codegen capture

Read the source JMeter VU's action tree:

```
mcp__octoperf__get_virtual_user(virtualUserId)
```

Classify the flow:

| Flow shape                                                                   | Path                                                                       |
|------------------------------------------------------------------------------|----------------------------------------------------------------------------|
| Linear navigation + simple forms (≤ 20 HTTP actions)                         | Step 2 (direct translation)                                                |
| Auth widgets, OAuth popups, file uploads, iframe-heavy SPA, JS-driven canvas | Step 2-bis (`playwright codegen`)                                          |
| Mixed: most simple, a few complex steps                                      | Direct translation, leave `// TODO codegen` markers for the complex blocks |

Direct translation is fast (no manual capture) but **brittle on
dynamic UIs**: a single-page app that doesn't change the URL between
clicks will defeat `page.goto(...)`. When in doubt, codegen.

### 2. Direct translation (JMeter → Playwright spec)

Walk the JMeter action tree and emit one Playwright statement per
action. Translation rules:

| JMeter element                                | Playwright equivalent                                                      |
|-----------------------------------------------|----------------------------------------------------------------------------|
| `HttpRequestAction` GET                       | `await page.goto(url)`                                                     |
| `HttpRequestAction` POST (form-urlencoded)    | `page.fill('input[name="x"]', value)` + `page.click('input[type=submit]')` |
| `HttpRequestAction` POST (JSON / multipart)   | `page.evaluate(() => fetch(...))` OR rebuild via real DOM interactions     |
| `${variable}` (JMeter CSV/Counter/Random)     | JS variable, `process.env.X`, or Playwright fixture                        |
| `ResponseAssertion` (BODY contains/not)       | `await expect(page.locator('body')).toContainText(...)`                    |
| `ThinktimeConstant`                           | `await page.waitForTimeout(ms)` (use sparingly)                            |
| `JSESSIONID` correlation rule                 | **Delete** — the browser handles cookies natively                          |
| Stripes `_sourcePage` / `__fp` correlation    | **Delete** — the browser submits the live form                             |
| `__VIEWSTATE` correlation                     | **Delete** — same                                                          |
| `LoopContainerAction` (N iterations)          | `for (let i = 0; i < N; i++) { ... }`                                      |
| `IfContainerAction` (condition)               | `if (cond) { ... }`                                                        |

**Most correlation rules become noise** in the Playwright translation
— the real browser submits the live form, sends the real cookies, and
echoes the real hidden inputs. Strip them. Keep only correlations that
extract a value the *user* visibly types (rare).

Minimal Playwright project layout — **keep it config-less**:

```
playwright-probe/
├── package.json
└── tests/
    └── user-journey.spec.ts
```

Why no `playwright.config.ts`? OctoPerf's importer treats every `.ts` /
`.js` file as a `PlaywrightSpecAction`, **including the config file**.
The engine then invokes the config as a test sampler at run time —
which fails (no `test()` defined) and inflates the failure count.

Disabling the config-as-spec (via `patch_virtual_user`,
`/children/<i>/enabled = false`) is a workaround, but it has a
second-order consequence: the config file is no longer written to
disk at run time → `use.baseURL` is lost → `page.goto('/')` becomes
`Cannot navigate to invalid URL`. The cleanest fix is to **skip the
config entirely** and put what you need in the spec:

- Use **absolute URLs** everywhere: `page.goto('https://target/path')`, never `page.goto('/path')`.
- Set headless / timeouts via `test.use({ ... })` at the top of the spec, not via `playwright.config.ts`.

Example spec (translated from a petstore-like JMeter VU):

```ts
import { test, expect } from '@playwright/test';

test('petstore browse + login probe', async ({ page }) => {
  const username = process.env.PETSTORE_USER ?? 'j2ee';
  const password = process.env.PETSTORE_PASSWORD ?? 'j2ee'
octoperf-async-pollingSkill

Use whenever an OctoPerf operation runs asynchronously and the LLM has to wait for it to settle — `validate_virtual_user`, `run_scenario`, `export_bench_report_pdf`, the async correlation tasks behind `apply_correlations_to_virtual_user`, or any tool that returns a `taskId` / `benchResultId` instead of the final result. Defines the cadence, the terminal conditions, and the anti-patterns so the LLM does not tight-loop the MCP server or sleep blindly for the full expected duration.

octoperf-auto-correlationSkill

Use when an OctoPerf Virtual User imported from a HAR/Postman/JMX recording fails its validation run because dynamic values (session tokens, CSRF, signed URLs, anti-forgery inputs, auth challenges) captured at recording time are stale on replay. Triggers on requests for "auto-correlation", "correlate the VU", "fix replay errors", "401/403 on replay after import", "tokens don't match", "signature mismatch in load test". Walks the LLM through framework preset selection, async polling, and regex-rule fallback. Requires the OctoPerf MCP server to be connected.

octoperf-bench-reportsSkill

Use when reading or interpreting an OctoPerf bench report — picking the right `get_report_*_values` tool for a given widget, understanding the difference between flat and trend reports, decoding semantic gotchas (Hits vs Hits CONTAINER, 304 cache hits skewing throughput, Playwright per-step row types, etc.). Triggers on "what's the right tool for this widget", "explain this metric", "how do I read this trend report", "what does parallelRunsSupported mean", "why is the Network row 24ms while page.goto is 364ms", "DELTA computeType". Complements `octoperf-scenario-diagnosis` — that skill walks the diagnosis workflow, this one is the widget-by-widget reading guide. Requires the OctoPerf MCP server.

octoperf-export-bench-report-pdfSkill

Use when the user asks to "export the report as PDF", "print the bench report", "get a PDF of report X", "share a PDF with stakeholders", or any variation that calls for a static artefact of an OctoPerf benchReport. Walks the LLM through the three-step async chain (submit print task → poll → download presigned URL). Requires the OctoPerf MCP server to be connected.

octoperf-scenario-diagnosisSkill

Use when an OctoPerf load-test scenario has completed (or is running) and the user wants to understand why it failed, underperformed, or behaved unexpectedly. Triggers on "the load test failed", "why are response times so high", "high error rate in the scenario", "diagnose this bench", "the run looks bad". Walks the LLM through reading global metrics, narrowing scope, comparing against validation, and surfacing the right next step (re-validate, tune scenario, fix infra). Requires the OctoPerf MCP server and a `benchResultId` to investigate.

octoperf-schedulingSkill

Use when scheduling an OctoPerf scenario to run at a specific time (one-shot) or on a recurring cadence (cron), or when listing / pausing / resuming / deleting an existing schedule. Triggers on "schedule the scenario for tomorrow morning", "run this every weekday at 8am", "every night at midnight", "pause the cron job", "delete the schedule", "show scheduled jobs". Covers the unusual cron format (Unix 5-field UTC, NOT Quartz), the timezone conversion gymnastics, the pre-flight rule (a misconfigured scenario will fire failing runs forever until disabled), and the full job lifecycle. Requires the OctoPerf MCP server.

octoperf-validation-triageSkill

Use when an OctoPerf Virtual User validation run has produced many failing actions and the user needs to diagnose them efficiently without reading every single failure serially. Triggers on "the validation is red", "lots of errors after import", "VU validation failed, what's wrong", "triage these failures", "why is my virtual user failing". Groups failures by category, drills into one representative per group, and proposes the matching MCP-tool fix. Requires the OctoPerf MCP server.