JMeter + InfluxDB + Grafana

9 min read

The HTML dashboard tells you what happened after the test is over. InfluxDB and Grafana tell you what is happening while the test runs. For a five-minute smoke test, post-test analysis is fine. For a two-hour soak test or a distributed load test with ten worker nodes, watching performance degrade in real time — and stopping the test before it damages production data — is essential.

How the stack fits together

Real-Time Observability
  • – Sends metrics every ~5 seconds
  • – Per-sampler: count, avg, p90/p95/p99
  • – Global: active threads, error rate
  • – InfluxDB line protocol over HTTP
  • – Time-series database
  • – Stores JMeter metrics with timestamps
  • – Supports InfluxQL queries
  • – Retains data after test completes
  • – Queries InfluxDB in real time
  • – Renders live charts per panel
  • – Import community dashboards (ID 5496)
  • – Alert on thresholds during test
  • Telegraf agent on app server –
  • CPU, memory, disk I/O to same InfluxDB –
  • Correlate JMeter load with server strain –
  • Diagnose bottleneck: app or infra –

Standing up InfluxDB and Grafana with Docker

The fastest local setup uses Docker Compose:

# docker-compose.yml
version: '3.8'
services:
  influxdb:
    image: influxdb:1.8
    ports:
      - "8086:8086"
    environment:
      - INFLUXDB_DB=jmeter
      - INFLUXDB_HTTP_AUTH_ENABLED=false
    volumes:
      - influxdb-data:/var/lib/influxdb
 
  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    depends_on:
      - influxdb
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana-data:/var/lib/grafana
 
volumes:
  influxdb-data:
  grafana-data:
docker compose up -d

InfluxDB is now accepting writes on http://localhost:8086. Grafana is available at http://localhost:3000 (login: admin / admin).

Configuring the JMeter Backend Listener

Add a Backend Listener to your test plan at Thread Group or Test Plan level:

Right-click → Add → Listener → Backend Listener

Set the Backend Listener implementation field to:

org.apache.jmeter.visualizers.backend.influxdb.InfluxdbBackendListenerClient

Then configure the parameters (shown as a table of key-value pairs in the editor):

ParameterValue
influxdbUrlhttp://localhost:8086/write?db=jmeter
applicationSecureBank
measurementjmeter
summaryOnlyfalse
samplersRegex.*
percentiles90;95;99
testTitleLoad Test — Staging
eventTags(leave blank)

Key parameters explained:

summaryOnly: false — sends per-sampler metrics, not just the total. Set to true only if you want aggregated metrics without per-endpoint breakdown.

samplersRegex: .* — matches all sampler labels. Use a regex to filter to specific samplers if your test plan has many low-level sub-requests you do not want to graph individually.

percentiles: 90;95;99 — which percentile values JMeter computes and sends. Computing percentiles adds CPU overhead; 90;95;99 is the standard set.

Connecting Grafana to InfluxDB

  1. Open Grafana at http://localhost:3000
  2. Go to Connections → Data sources → Add data source
  3. Select InfluxDB
  4. Configure:
    • URL: http://influxdb:8086 (use the Docker service name, not localhost, when running in Docker)
    • Database: jmeter
    • HTTP Method: GET
  5. Click Save & Test — should show "Data source is working"

Importing the community dashboard

The JMeter community has published several Grafana dashboard templates. The most widely used:

  • Dashboard ID 5496 — "Apache JMeter Dashboard" — comprehensive layout with response times, throughput, active threads, error rate, and per-sampler breakdown
  • Dashboard ID 11084 — updated variant for newer InfluxDB schemas

Import:

  1. Dashboards → Import
  2. Enter 5496 in the "Import via grafana.com" field
  3. Click Load
  4. Select your InfluxDB data source from the dropdown
  5. Click Import

The dashboard opens. Start your JMeter test. Within seconds, panels start populating with live data.

What to watch during a test

Active Threads panel — confirms your ramp-up is working as configured. If you see threads plateau before reaching the target, check the Thread Group configuration.

Throughput panel — requests per second. Watch for throughput stabilising after ramp-up. If throughput drops while threads stay constant, the server is saturating — response times are increasing and threads spend more time waiting.

Response time percentiles panel — the p95 and p99 lines climbing slowly under sustained load is the classic sign of a memory leak, connection pool exhaustion, or cache eviction. Flat lines mean stable performance.

Error rate panel — spikes here while response times spike usually mean server errors (5xx). Spikes in errors while response times drop usually mean fast failures (connection refused, 429 rate limiting).

Adding server metrics

To see CPU and memory alongside JMeter load, run Telegraf on your application server:

# /etc/telegraf/telegraf.conf (on app server)
[[outputs.influxdb]]
  urls = ["http://monitoring-host:8086"]
  database = "jmeter"
 
[[inputs.cpu]]
  percpu = false
  totalcpu = true
 
[[inputs.mem]]
 
[[inputs.disk]]
  ignore_fs = ["tmpfs", "devtmpfs"]

Telegraf writes cpu, mem, and disk measurements to the same InfluxDB database. In Grafana, add panels querying these measurements alongside the JMeter panels. Now you can see: at 200 VUs, response time started rising at the same moment CPU on the app server hit 85% — the bottleneck is compute, not the database or network.

InfluxDB 2.x

InfluxDB 1.8 uses InfluxQL and the write HTTP endpoint shown above. InfluxDB 2.x uses Flux query language and a different write endpoint with token authentication.

JMeter's built-in Backend Listener targets InfluxDB 1.x. For InfluxDB 2.x, either:

  • Run InfluxDB in 1.x compatibility mode (influxdb:2.x with DOCKER_INFLUXDB_INIT_MODE=upgrade)
  • Use a community JMeter plugin that supports InfluxDB 2.x API

⚠️ Common mistakes

  • Putting the Backend Listener inside a single sampler instead of at Thread Group or Test Plan level. A Backend Listener inside one sampler only receives data from that sampler. Place it at Thread Group level to collect from all samplers in the group, or at Test Plan level to collect from everything.
  • Leaving Backend Listener enabled in tests where InfluxDB is not running. If InfluxDB is unavailable, the Backend Listener's background HTTP thread fails on every push interval. The test continues running but logs are flooded with connection errors, which can mask real errors. Disable the Backend Listener (right-click → Disable) for runs where you do not need real-time dashboards.
  • Using influxdbUrl: http://localhost:8086 when JMeter runs in Docker. Inside a Docker container, localhost refers to the container itself — not the host machine. Use the Docker network name (http://influxdb:8086 if both containers are in the same Compose network) or the host machine's IP.

🎯 Practice task

Set up the full JMeter → InfluxDB → Grafana stack.

  1. Start Docker Compose with the configuration above. Verify InfluxDB responds: curl http://localhost:8086/ping should return HTTP 204.
  2. Add a Backend Listener to your test plan with the InfluxDB configuration. Run a 2-minute test with 10 users.
  3. In Grafana, add the InfluxDB data source and confirm the connection. Import dashboard ID 5496.
  4. Run the test again. Watch the dashboard populate in real time — observe the active threads panel match your Thread Group ramp-up, and the throughput panel stabilise after ramp-up completes.
  5. Stop the test after 30 seconds (click the Stop button in JMeter or Ctrl+C in CLI). Observe the Grafana charts freeze at the stop point. Re-start the test — observe a new data series beginning on the chart.
  6. Query InfluxDB directly to see the raw data: curl 'http://localhost:8086/query?db=jmeter&q=SELECT+mean("avg")+FROM+"jmeter"+GROUP+BY+time(10s)'. This shows the same data Grafana is graphing.

// tip to track lessons you complete and pick up where you left off across devices.