|
| 1 | +# Azure Load Testing client library for Java |
| 2 | + |
| 3 | +Azure Load Testing provides client library in Java to the user by which they can interact natively with Azure Load Testing service. Azure Load Testing is a fully managed load-testing service that enables you to generate high-scale load. The service simulates traffic for your applications, regardless of where they're hosted. Developers, testers, and quality assurance (QA) engineers can use it to optimize application performance, scalability, or capacity |
| 4 | + |
| 5 | +This package contains Microsoft Azure Developer LoadTesting client library. |
| 6 | + |
| 7 | +## Documentation |
| 8 | + |
| 9 | +Various documentation is available to help you get started |
| 10 | + |
| 11 | +<!-- - [Source code][source_code] --> |
| 12 | +- [API reference documentation][api_reference_doc] |
| 13 | +- [Product Documentation][product_documentation] |
| 14 | + |
| 15 | +## Getting started |
| 16 | + |
| 17 | +### Prerequisites |
| 18 | + |
| 19 | +- [Java Development Kit (JDK)][jdk] with version 8 or above |
| 20 | +- [Azure Subscription][azure_subscription] |
| 21 | +- Azure Load Testing resource |
| 22 | + |
| 23 | +### Adding the package to your product |
| 24 | + |
| 25 | +[//]: # ({x-version-update-start;com.azure:azure-developer-loadtesting;current}) |
| 26 | +```xml |
| 27 | +<dependency> |
| 28 | + <groupId>com.azure</groupId> |
| 29 | + <artifactId>azure-developer-loadtesting</artifactId> |
| 30 | + <version>1.0.0-beta.1</version> |
| 31 | +</dependency> |
| 32 | +``` |
| 33 | +[//]: # ({x-version-update-end}) |
| 34 | + |
| 35 | +### Authentication |
| 36 | + |
| 37 | +[Azure Identity][azure_identity] package provides the default implementation for authenticating the client. |
| 38 | + |
| 39 | +By default, Azure Active Directory token authentication depends on correct configure of following environment variables. |
| 40 | + |
| 41 | +- `AZURE_CLIENT_ID` for Azure client ID. |
| 42 | +- `AZURE_TENANT_ID` for Azure tenant ID. |
| 43 | +- `AZURE_CLIENT_SECRET` or `AZURE_CLIENT_CERTIFICATE_PATH` for client secret or client certificate. |
| 44 | + |
| 45 | +In addition, Azure subscription ID can be configured via environment variable `AZURE_SUBSCRIPTION_ID`. |
| 46 | + |
| 47 | +With above configuration, `azure` client can be authenticated by following code: |
| 48 | + |
| 49 | +```java java-readme-sample-auth |
| 50 | +// ensure the user, service principal or managed identity used has Loadtesting Contributor role for the resource |
| 51 | +TokenCredential credential = new DefaultAzureCredentialBuilder() |
| 52 | + .build(); |
| 53 | +// create client using DefaultAzureCredential |
| 54 | +LoadTestingClient client = new LoadTestingClientBuilder() |
| 55 | + .credential(credential) |
| 56 | + .endpoint("<Enter Azure Load Testing Data-Plane URL>") |
| 57 | + .buildClient(); |
| 58 | +LoadTestAdministrationClient adminClient = client.getLoadTestAdministrationClient(); |
| 59 | +TestRunClient testRunClient = client.getLoadTestRunClient(); |
| 60 | +``` |
| 61 | + |
| 62 | +## Key concepts |
| 63 | + |
| 64 | +The following components make up the Azure Load Testing service. The Azure Load Test client library for Java allows you to interact with each of these components through the use of clients. There are two top-level clients which are the main entry points for the library |
| 65 | + |
| 66 | +- `LoadTestingClient` |
| 67 | + |
| 68 | +- `LoadTestingAsyncClient` |
| 69 | + |
| 70 | +The two clients have similar methods in them except the methods in the async client are async as well. |
| 71 | + |
| 72 | +The top-level clients have two sub-clients |
| 73 | + |
| 74 | +- `LoadTestAdministration` |
| 75 | + |
| 76 | +- `TestRun` |
| 77 | + |
| 78 | +These sub-clients are used for managing and using different components of the service. |
| 79 | + |
| 80 | +### Load Test Administration Client |
| 81 | + |
| 82 | +The `LoadTestAdministration` sub-clients is used to administer and configure the load tests, app components and metrics. |
| 83 | + |
| 84 | +#### Test |
| 85 | + |
| 86 | +A test specifies the test script, and configuration settings for running a load test. You can create one or more tests in an Azure Load Testing resource. |
| 87 | + |
| 88 | +#### App Component |
| 89 | + |
| 90 | +When you run a load test for an Azure-hosted application, you can monitor resource metrics for the different Azure application components (server-side metrics). While the load test runs, and after completion of the test, you can monitor and analyze the resource metrics in the Azure Load Testing dashboard. |
| 91 | + |
| 92 | +#### Metrics |
| 93 | + |
| 94 | +During a load test, Azure Load Testing collects metrics about the test execution. There are two types of metrics: |
| 95 | + |
| 96 | +1. Client-side metrics give you details reported by the test engine. These metrics include the number of virtual users, the request response time, the number of failed requests, or the number of requests per second. |
| 97 | + |
| 98 | +2. Server-side metrics are available for Azure-hosted applications and provide information about your Azure application components. Metrics can be for the number of database reads, the type of HTTP responses, or container resource consumption. |
| 99 | + |
| 100 | +### Test Run Client |
| 101 | + |
| 102 | +The `TestRun` sub-clients is used to start and stop test runs corresponding to a load test. A test run represents one execution of a load test. It collects the logs associated with running the Apache JMeter script, the load test YAML configuration, the list of app components to monitor, and the results of the test. |
| 103 | + |
| 104 | +### Data-Plane Endpoint |
| 105 | + |
| 106 | +Data-plane of Azure Load Testing resources is addressable using the following URL format: |
| 107 | + |
| 108 | +`00000000-0000-0000-0000-000000000000.aaa.cnt-prod.loadtesting.azure.com` |
| 109 | + |
| 110 | +The first GUID `00000000-0000-0000-0000-000000000000` is the unique identifier used for accessing the Azure Load Testing resource. This is followed by `aaa` which is the Azure region of the resource. |
| 111 | + |
| 112 | +The data-plane endpoint is obtained from Control Plane APIs. |
| 113 | + |
| 114 | +**Example:** `1234abcd-12ab-12ab-12ab-123456abcdef.eus.cnt-prod.loadtesting.azure.com` |
| 115 | + |
| 116 | +In the above example, `eus` represents the Azure region `East US`. |
| 117 | + |
| 118 | +## Examples |
| 119 | + |
| 120 | +### Creating a Load Test |
| 121 | + |
| 122 | +```java java-readme-sample-createTest |
| 123 | +LoadTestingClient client = new LoadTestingClientBuilder() |
| 124 | + .credential(new DefaultAzureCredentialBuilder().build()) |
| 125 | + .endpoint("<endpoint>") |
| 126 | + .buildClient(); |
| 127 | + |
| 128 | +// construct Test object using nested String:Object Maps |
| 129 | +Map<String, Object> testMap = new HashMap<String, Object>(); |
| 130 | +testMap.put("displayName", "Sample Display Name"); |
| 131 | +testMap.put("description", "Sample Description"); |
| 132 | + |
| 133 | +// loadTestConfig describes the number of test engines to generate load |
| 134 | +Map<String, Object> loadTestConfigMap = new HashMap<String, Object>(); |
| 135 | +loadTestConfigMap.put("engineInstances", 1); |
| 136 | +testMap.put("loadTestConfig", loadTestConfigMap); |
| 137 | + |
| 138 | +// environmentVariables are plain-text data passed to test engines |
| 139 | +Map<String, Object> envVarMap = new HashMap<String, Object>(); |
| 140 | +envVarMap.put("a", "b"); |
| 141 | +envVarMap.put("x", "y"); |
| 142 | +testMap.put("environmentVariables", envVarMap); |
| 143 | + |
| 144 | +// secrets are secure data sent using Azure Key Vault |
| 145 | +Map<String, Object> secretMap = new HashMap<String, Object>(); |
| 146 | +Map<String, Object> sampleSecretMap = new HashMap<String, Object>(); |
| 147 | +sampleSecretMap.put("value", "https://samplevault.vault.azure.net/secrets/samplesecret/f113f91fd4c44a368049849c164db827"); |
| 148 | +sampleSecretMap.put("type", "AKV_SECRET_URI"); |
| 149 | +secretMap.put("sampleSecret", sampleSecretMap); |
| 150 | +testMap.put("secrets", secretMap); |
| 151 | + |
| 152 | +// passFailCriteria define the conditions to conclude the test as success |
| 153 | +Map<String, Object> passFailMap = new HashMap<String, Object>(); |
| 154 | +Map<String, Object> passFailMetrics = new HashMap<String, Object>(); |
| 155 | +Map<String, Object> samplePassFailMetric = new HashMap<String, Object>(); |
| 156 | +samplePassFailMetric.put("clientmetric", "response_time_ms"); |
| 157 | +samplePassFailMetric.put("aggregate", "percentage"); |
| 158 | +samplePassFailMetric.put("condition", ">"); |
| 159 | +samplePassFailMetric.put("value", "20"); |
| 160 | +samplePassFailMetric.put("action", "continue"); |
| 161 | +passFailMetrics.put("fefd759d-7fe8-4f83-8b6d-aeebe0f491fe", samplePassFailMetric); |
| 162 | +passFailMap.put("passFailMetrics", passFailMetrics); |
| 163 | +testMap.put("passFailCriteria", passFailMap); |
| 164 | + |
| 165 | +// convert the object Map to JSON BinaryData |
| 166 | +BinaryData test = BinaryData.fromObject(testMap); |
| 167 | + |
| 168 | +// receive response with BinaryData content |
| 169 | +Response<BinaryData> testOutResponse = client.getLoadTestAdministrationClient().createOrUpdateTestWithResponse("test12345", test, null); |
| 170 | +System.out.println(testOutResponse.getValue().toString()); |
| 171 | +``` |
| 172 | + |
| 173 | +### Uploading .jmx file to a Load Test |
| 174 | + |
| 175 | +```java java-readme-sample-uploadTestFile |
| 176 | +LoadTestingClient client = new LoadTestingClientBuilder() |
| 177 | + .credential(new DefaultAzureCredentialBuilder().build()) |
| 178 | + .endpoint("<endpoint>") |
| 179 | + .buildClient(); |
| 180 | + |
| 181 | +// extract file contents to BinaryData |
| 182 | +BinaryData fileData = BinaryData.fromFile(new File("path/to/file").toPath()); |
| 183 | + |
| 184 | +// receive response with BinaryData content |
| 185 | +Response<BinaryData> fileUrlOut = client.getLoadTestAdministrationClient().uploadTestFileWithResponse("test12345", "file12345", "sample-file.jmx", fileData, null); |
| 186 | +System.out.println(fileUrlOut.getValue().toString()); |
| 187 | +``` |
| 188 | + |
| 189 | +### Running a Load Test |
| 190 | + |
| 191 | +```java java-readme-sample-runTest |
| 192 | +LoadTestingClient client = new LoadTestingClientBuilder() |
| 193 | + .credential(new DefaultAzureCredentialBuilder().build()) |
| 194 | + .endpoint("<endpoint>") |
| 195 | + .buildClient(); |
| 196 | + |
| 197 | +// construct Test Run object using nested String:Object Maps |
| 198 | +Map<String, Object> testRunMap = new HashMap<String, Object>(); |
| 199 | +testRunMap.put("testId", "test12345"); |
| 200 | +testRunMap.put("displayName", "SDK-Created-TestRun"); |
| 201 | + |
| 202 | +// convert the object Map to JSON BinaryData |
| 203 | +BinaryData testRun = BinaryData.fromObject(testRunMap); |
| 204 | + |
| 205 | +// receive response with BinaryData content |
| 206 | +Response<BinaryData> testRunOut = client.getLoadTestRunClient().createOrUpdateTestRunWithResponse("testrun12345", testRun, null); |
| 207 | +System.out.println(testRunOut.getValue().toString()); |
| 208 | + |
| 209 | +// wait for test to reach terminal state |
| 210 | +JsonNode testRunJson = null; |
| 211 | +String testStatus = null, startDateTime = null, endDateTime = null; |
| 212 | +while (testStatus == null || (testStatus != "DONE" && testStatus != "CANCELLED" && testStatus != "FAILED")) { |
| 213 | + testRunOut = client.getLoadTestRunClient().getTestRunWithResponse("testrun12345", null); |
| 214 | + // parse JSON and read status value |
| 215 | + try { |
| 216 | + testRunJson = new ObjectMapper().readTree(testRunOut.getValue().toString()); |
| 217 | + testStatus = testRunJson.get("status").asText(); |
| 218 | + } catch (JsonProcessingException e) { |
| 219 | + System.out.println("Error processing JSON response"); |
| 220 | + // handle error condition |
| 221 | + } |
| 222 | + |
| 223 | + // wait and check test status every 5 seconds |
| 224 | + try { |
| 225 | + Thread.sleep(5000); |
| 226 | + } catch (InterruptedException e) { |
| 227 | + // handle interruption |
| 228 | + } |
| 229 | +} |
| 230 | + |
| 231 | +startDateTime = testRunJson.get("startDateTime").asText(); |
| 232 | +endDateTime = testRunJson.get("endDateTime").asText(); |
| 233 | + |
| 234 | +// construct Test Run Client Metrics object using nested String:Object Maps |
| 235 | +Map<String, Object> clientMetricsMap = new HashMap<String, Object>(); |
| 236 | +List<String> requestSamplersList = new ArrayList<String>(); |
| 237 | +requestSamplersList.add("Homepage"); |
| 238 | +clientMetricsMap.put("requestSamplers", requestSamplersList); |
| 239 | + |
| 240 | +List<String> errorsList = new ArrayList<String>(); |
| 241 | +errorsList.add("500"); |
| 242 | +clientMetricsMap.put("errors", errorsList); |
| 243 | + |
| 244 | +List<String> percentilesList = new ArrayList<String>(); |
| 245 | +percentilesList.add("95"); |
| 246 | +clientMetricsMap.put("percentiles", percentilesList); |
| 247 | + |
| 248 | +clientMetricsMap.put("groupByInterval", "10s"); |
| 249 | +clientMetricsMap.put("startTime", startDateTime); |
| 250 | +clientMetricsMap.put("endTime", endDateTime); |
| 251 | + |
| 252 | +// convert the object Map to JSON BinaryData |
| 253 | +BinaryData clientMetrics = BinaryData.fromObject(clientMetricsMap); |
| 254 | + |
| 255 | +// fetch client metrics |
| 256 | +Response<BinaryData> clientMetricsOut = client.getLoadTestRunClient().getTestRunClientMetricsWithResponse("testrun12345", clientMetrics, null); |
| 257 | +System.out.println(clientMetricsOut.getValue().toString()); |
| 258 | +``` |
| 259 | + |
| 260 | +## Troubleshooting |
| 261 | + |
| 262 | +Azure SDKs for Java offer a consistent logging story to help aid in troubleshooting application errors and expedite |
| 263 | +their resolution. The logs produced will capture the flow of an application before reaching the terminal state to help |
| 264 | +locate the root issue. View the [logging][logging] wiki for guidance about enabling logging. |
| 265 | + |
| 266 | +## Next steps |
| 267 | + |
| 268 | +Azure Loading Testing Java SDK samples are available to you in the SDK's GitHub repository. These samples provide example code for additional scenarios commonly encountered. |
| 269 | +<!-- See [Azure Load Testing samples][sample_code]. --> |
| 270 | + |
| 271 | +## Contributing |
| 272 | + |
| 273 | +For details on contributing to this repository, see the [contributing guide](https://github.com/Azure/azure-sdk-for-java/blob/main/CONTRIBUTING.md). |
| 274 | + |
| 275 | +1. Fork it |
| 276 | +1. Create your feature branch (`git checkout -b my-new-feature`) |
| 277 | +1. Commit your changes (`git commit -am 'Add some feature'`) |
| 278 | +1. Push to the branch (`git push origin my-new-feature`) |
| 279 | +1. Create new Pull Request |
| 280 | + |
| 281 | +<!-- LINKS --> |
| 282 | +<!-- [source_code]: https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/loadtesting/azure-developer-loadtesting/src --> |
| 283 | +<!-- [sample_code]: https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/loadtesting/azure-developer-loadtesting/src/samples --> |
| 284 | +[api_reference_doc]: https://docs.microsoft.com/rest/api/loadtesting/ |
| 285 | +[product_documentation]: https://azure.microsoft.com/services/load-testing/ |
| 286 | +[jdk]: https://docs.microsoft.com/java/azure/jdk/ |
| 287 | +[azure_subscription]: https://azure.microsoft.com/free/ |
| 288 | +[azure_identity]: https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/identity/azure-identity |
| 289 | +[logging]: https://github.com/Azure/azure-sdk-for-java/wiki/Logging-in-Azure-SDK |
0 commit comments