Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
261 changes: 195 additions & 66 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,99 +1,228 @@
# jmeter-backend-azure

[![Build and publish](https://github.com/adrianmo/jmeter-backend-azure/actions/workflows/maven.yml/badge.svg)](https://github.com/adrianmo/jmeter-backend-azure/actions/workflows/maven.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE.txt)
[![JMeter Version](https://img.shields.io/badge/JMeter-5.4.1%2B-blue)](https://jmeter.apache.org/)
[![Latest Release](https://img.shields.io/github/v/release/adrianmo/jmeter-backend-azure)](https://github.com/adrianmo/jmeter-backend-azure/releases)

A JMeter plug-in that enables you to send test results to Azure Application Insights.
> A JMeter Backend Listener plugin that streams test results in real time to **Azure Application Insights**.

---

## Table of Contents

- [Overview](#overview)
- [Requirements](#requirements)
- [Installation](#installation)
- [Option A: JMeter Plugins Manager](#option-a-jmeter-plugins-manager)
- [Option B: Manual Installation](#option-b-manual-installation)
- [Configuration](#configuration)
- [Parameters](#parameters)
- [Custom Properties](#custom-properties)
- [Metrics Reference](#metrics-reference)
- [Visualization](#visualization)
- [Building from Source](#building-from-source)
- [Contributing](#contributing)
- [License](#license)

---

## Overview

### Description

JMeter Backend Azure is a JMeter plugin enabling you to send test results to an Azure Application Insights.

The following test results metrics are exposed by the plugin.

- TestStartTime
- SampleStartTime
- SampleEndTime
- ResponseCode
- Duration
- URL
- SampleLabel
- SampleCount
- ErrorCount
- Bytes
- SentBytes
- ConnectTime
- IdleTime
- ThreadName
- GrpThreads
- AllThreads
- (Optional) aih.{ResponseHeader}
- (Optional) ResponseData
- (Optional) SampleData

### Plugin installation

Once you have built or downloaded the plugin JAR file from the [releases](https://github.com/adrianmo/jmeter-backend-azure/releases) section,
move the JAR to your `$JMETER_HOME/lib/ext`.
**JMeter Backend Azure** is a JMeter plugin that implements the [Backend Listener](https://jmeter.apache.org/usermanual/component_reference.html#Backend_Listener) interface to forward sampler results to [Azure Application Insights](https://docs.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview) during a test run.

```bash
mv target/jmeter.backendlistener.azure-VERSION.jar $JMETER_HOME/lib/ext/
This enables you to:

- Monitor test execution **in real time** via the Live Metrics Stream
- Store and query all request telemetry in Application Insights **Logs (Analytics)**
- Filter, split, and visualize performance data using **Azure Monitor Workbooks** or **Dashboards**
- Attach custom dimension properties (e.g., environment, build version) to every telemetry record

---

## Requirements

| Requirement | Version |
|---|---|
| Apache JMeter | 5.4.1 or later |
| Java | 8 or later |
| Azure Application Insights | Any active instance |

---

## Installation

### Option A: JMeter Plugins Manager

> Available at [https://jmeter-plugins.org/](https://jmeter-plugins.org/)

1. Install the [JMeter Plugins Manager](https://jmeter-plugins.org/wiki/PluginsManager/) JAR into `$JMETER_HOME/lib/ext/` if not already present.
2. Open JMeter → **Options** → **Plugins Manager**.
3. In the **Available Plugins** tab, search for **`Azure Backend Listener`**.
4. Check the plugin and click **Apply Changes and Restart JMeter**.

> If the plugin does not appear yet, use the manual installation method below and check [https://jmeter-plugins.org/](https://jmeter-plugins.org/) for the latest availability.

### Option B: Manual Installation

1. Download the latest JAR from the [Releases](https://github.com/adrianmo/jmeter-backend-azure/releases) page:
```
jmeter.backendlistener.azure-<VERSION>.jar
```

2. Copy the JAR to your JMeter extensions directory:
```bash
mv jmeter.backendlistener.azure-<VERSION>.jar $JMETER_HOME/lib/ext/
```

3. Restart JMeter. The plugin will be loaded automatically.

---

## Configuration

In your Test Plan, add a Backend Listener:

**Right-click Thread Group** → **Add** → **Listener** → **Backend Listener**

Set the **Backend Listener implementation** to:

```
io.github.adrianmo.jmeter.backendlistener.azure.AzureBackendClient
```

Then, restart JMeter and the plugin should be loaded.
### Parameters

### JMeter configuration
| Parameter | Description | Required | Default |
|---|---|---|---|
| `connectionString` | The [Connection String](https://docs.microsoft.com/en-us/azure/azure-monitor/app/sdk-connection-string?tabs=java) of your Application Insights instance (e.g., `InstrumentationKey=...;IngestionEndpoint=...`) | **Yes** | _(empty)_ |
| `testName` | Name used to identify and filter this test run in Application Insights | **Yes** | `jmeter` |
| `liveMetrics` | When `true`, enables the [Live Metrics Stream](https://docs.microsoft.com/en-us/azure/azure-monitor/app/live-stream) for real-time monitoring | No | `true` |
| `samplersList` | Semicolon-separated (`;`) list of sampler names to include. If empty, all samplers are collected | No | _(empty)_ |
| `useRegexForSamplerList` | When `true`, treats `samplersList` as a regular expression pattern | No | `false` |
| `responseHeaders` | Semicolon-separated (`;`) list of response header names to capture as `aih.<header>` properties | No | _(empty)_ |
| `logResponseData` | Controls when response body is captured as `ResponseData`. Options: `Always`, `OnFailure`, `Never` | No | `OnFailure` |
| `logSampleData` | Controls when sample (request) data is captured as `SampleData`. Options: `Always`, `OnFailure`, `Never` | No | `OnFailure` |
| `instrumentationKey` | ⚠️ **Deprecated** — use `connectionString` instead. The bare Instrumentation Key of your Application Insights instance | No | _(empty)_ |

To make JMeter send test result metrics to Azure Application Insights, in your **Test Pan**, right click on
**Thread Group** > Add > Listener > Backend Listener, and choose `io.github.adrianmo.jmeter.backendlistener.azure.AzureBackendClient` as `Backend Listener Implementation`.
Then, in the Parameters table, configure the following attributes.
*Example configuration in JMeter:*

| Attribute | Description | Required |
|---|---|---|
| *connectionString* | The [Connection String](https://docs.microsoft.com/en-us/azure/azure-monitor/app/sdk-connection-string?tabs=java) of your Application Insights instance | Yes |
| *testName* | Name of the test. This value is used to differentiate metrics across test runs or plans in Application Insights and allow you to filter them. | Yes |
| *liveMetrics* | Boolean to indicate whether or not real-time metrics are enabled and available in the [Live Metrics Stream](https://docs.microsoft.com/en-us/azure/azure-monitor/app/live-stream). Defaults to `true`. | No |
| *samplersList* | Optional list of samplers separated by a semi-colon (`;`) that the listener will collect and send metrics to Application Insights. If the list is empty, the listener will not filter samplers and send metrics from all of them. Defaults to an empty string. | No |
| *useRegexForSamplerList* | If set to `true` the `samplersList` will be evaluated as a regex to filter samplers. Defaults to `false`. | No |
| *responseHeaders* | Optional list of response headers separated by a semi-colon (`;`) that the listener will collect and send values to Application Insights. | No |
| *logResponseData* | This value indicates whether or not the response data should be captured. Options are `Always`, `OnFailure`, or `Never`. The response data will be captured as a string into the _ResponseData_ property. Defaults to `OnFailure`. | No |
| *logSampleData* | Boolean to indicate whether or not the sample data should be captured. Options are `Always`, `OnFailure`, or `Never`. The sample data will be captured as a string into the _SampleData_ property. Defaults to `OnFailure`. | No |
| *instrumentationKey* | The Instrumentation Key of your Application Insights instance. <br>⚠️ **Deprecated**: use *connectionString* instead. | No |
![Screenshot of configuration](docs/configuration.png "Screenshot of JMeter Backend Listener configuration")

*Example of configuration:*
### Custom Properties

![Screenshot of configuration](docs/configuration.png "Screenshot of JMeter configuration")
Any parameter whose name starts with `ai.` is forwarded to Application Insights as a **custom dimension** on every telemetry record. This is useful for tagging test data with contextual information.

#### Custom properties
**Example:**

You can add custom data to your metrics by adding properties starting with `ai.`, for example, you might want to provide information related to your environment with the property `ai.environment` and value `staging`.
| Parameter Name | Value |
|---|---|
| `ai.environment` | `staging` |
| `ai.buildVersion` | `1.4.2` |
| `ai.team` | `platform` |

### Visualization
These appear as filterable custom dimensions in the Application Insights **Requests** table.

Test result metrics are available in the **requests** dimension of your Application Insights instance.
In the image you can see an example of how you can visualize the duration of the requests made during your test run.
---

![Request duration](docs/requestduration.png "Screenshot of test requests duration")
## Metrics Reference

Each sampler result is sent as a `request` telemetry item to Application Insights with the following properties:

| Property | Description |
|---|---|
| `name` | Value of `testName` parameter — used to identify the test run |
| `TestStartTime` | Timestamp when the JMeter test started |
| `SampleStartTime` | Timestamp when the individual sample started |
| `SampleEndTime` | Timestamp when the individual sample ended |
| `ResponseCode` | HTTP response code (or sampler-specific code) |
| `Duration` | Elapsed time in milliseconds |
| `URL` | Request URL |
| `SampleLabel` | Sampler label / transaction name |
| `SampleCount` | Number of samples in this result |
| `ErrorCount` | Number of errors |
| `Bytes` | Bytes received |
| `SentBytes` | Bytes sent |
| `ConnectTime` | Connection time in milliseconds |
| `IdleTime` | Idle time in milliseconds |
| `ThreadName` | JMeter thread name |
| `GrpThreads` | Number of active threads in the thread group |
| `AllThreads` | Total active threads across all thread groups |
| `aih.<HeaderName>` | _(Optional)_ Value of a captured response header (one property per header in `responseHeaders`) |
| `ResponseData` | _(Optional)_ Response body, truncated to 1024 characters. Controlled by `logResponseData` |
| `SampleData` | _(Optional)_ Sample (request) data, truncated to 1024 characters. Controlled by `logSampleData` |

Additionally, if you enabled `liveMetrics` in the configuration, you can watch your test performance in real-time in the Live Metrics Stream blade.
---

![Live Metrics Stream](docs/livemetrics.png "Screenshot of live metrics stream")
## Visualization

## Contributing
### Application Insights Logs

Query your results in **Application Insights → Logs** using the `requests` table:

```kusto
requests
| where timestamp > datetime("2024-01-01T00:00")
| where name == "my-test-run"
| project timestamp, url, duration, resultCode, customDimensions
| order by timestamp asc
```

![Request duration chart](docs/requestduration.png "Example: request duration over time in Application Insights")

Feel free to contribute by forking and making pull requests, or simply by suggesting ideas through the
[Issues](https://github.com/adrianmo/jmeter-backend-azure/issues) section.
### Live Metrics Stream

### Build
When `liveMetrics` is set to `true`, open **Application Insights → Live Metrics** during your test to see request rate, response times, and failure rate updated every second.

You can make changes to the plugin and build your own JAR file to test changes. To build the artifact,
execute below Maven command. Make sure `JAVA_HOME` is set properly.
![Live Metrics Stream](docs/livemetrics.png "Example: Live Metrics Stream during an active JMeter test")

---

## Building from Source

Requirements: Java 8+, Maven 3.x, `JAVA_HOME` set.

```bash
# Clone the repository
git clone https://github.com/adrianmo/jmeter-backend-azure.git
cd jmeter-backend-azure

# Run tests
mvn test

# Build the plugin JAR (output in target/)
mvn clean package
```

The built JAR will be at:

```
target/jmeter.backendlistener.azure-<VERSION>.jar
```

Copy it to `$JMETER_HOME/lib/ext/` and restart JMeter.

### Continuous Integration

The GitHub Actions workflow ([`.github/workflows/maven.yml`](.github/workflows/maven.yml)) runs on every push and pull request to `master`. When a GitHub Release is published, the workflow automatically builds the versioned JAR and attaches it to the release.

---

## Contributing

Contributions are welcome! You can:

- Report bugs or request features via [Issues](https://github.com/adrianmo/jmeter-backend-azure/issues)
- Fork the repository and open a [Pull Request](https://github.com/adrianmo/jmeter-backend-azure/pulls)

Please ensure all tests pass (`mvn test`) before submitting a PR.

---

## License

This project is licensed under the [MIT License](LICENSE.txt).

---

This plugin is inspired in the [Elasticsearch](https://github.com/delirius325/jmeter-elasticsearch-backend-listener) and [Kafka](https://github.com/rahulsinghai/jmeter-backend-listener-kafka) backend listener plugins.
> This plugin is inspired by the [Elasticsearch](https://github.com/delirius325/jmeter-elasticsearch-backend-listener) and [Kafka](https://github.com/rahulsinghai/jmeter-backend-listener-kafka) backend listener plugins.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.adrianmo</groupId>
<artifactId>jmeter.backendlistener.azure</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>0.3.0</version>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>A JMeter plug-in that enables you to send test results to Azure Monitor.</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,15 @@ private void trackRequest(String name, SampleResult sr) {

if (logResponseData == DataLoggingOption.Always ||
(logResponseData == DataLoggingOption.OnFailure && !sr.isSuccessful())) {
String rawResponseData = sr.getResponseDataAsString();
String responseData;
if (sr.getResponseDataAsString().length() > MAX_DATA_LENGTH) {
if (rawResponseData == null) {
responseData = "[NULL RESPONSE BODY]";
} else if (rawResponseData.length() > MAX_DATA_LENGTH) {
log.warn("Response data is too long, truncating it to {} characters", MAX_DATA_LENGTH);
responseData = sr.getResponseDataAsString().substring(0, MAX_DATA_LENGTH) + "...[TRUNCATED]";
responseData = rawResponseData.substring(0, MAX_DATA_LENGTH) + "...[TRUNCATED]";
} else {
responseData = sr.getResponseDataAsString();
responseData = rawResponseData;
}
properties.put("ResponseData", responseData);
}
Expand Down