Skip to content

Commit a86fa2e

Browse files
authored
Various improvements (#88)
* Update K6 scripts to call all APIs * Remove SQL scripts and add new K6 scripts to populate database (VehicleInventoryService was overwriting SQL scripts on startup). * Update READMEs * Init and populate DB with some basic data * Update copyrights Testing: ``` OverheadTests > runAllTestConfigurations() > all STANDARD_OUT ---------------------------------------------------------- Run at Thu Feb 29 23:45:51 UTC 2024 all : Compares all DistroConfigs 5 users, 5000 iterations ---------------------------------------------------------- DistroConfig : noneapp_signals_disabledapp_signals_no_tracesapp_signals_traces Run duration : 00:10:04 00:10:02 00:10:02 00:10:02 Avg. CPU (user) % : 0.0 0.0 0.0 0.0 Max. CPU (user) % : 0.0 0.0 0.0 0.0 Avg. mch tot cpu % : 0.0 0.0 0.0 0.0 Startup time (ms) : 4011 5014 5016 5013 Total allocated MB : 0.00 0.00 0.00 0.00 Thread switch rate : 0.0 0.0 0.0 0.0 GC time (ms) : 0 0 0 0 GC pause time (ms) : 0 0 0 0 Req. mean (ms) : 104.11 105.04 106.39 104.71 Req. p95 (ms) : 389.89 389.92 389.93 389.90 Iter. mean (ms) : 1458.85 1471.86 1490.91 1467.22 Iter. p95 (ms) : 1520.01 1540.09 1629.93 1540.02 Net read avg (bps) : 0.00 0.00 0.00 0.00 Net write avg (bps) : 0.00 0.00 0.00 0.00 Peak threads : 0 0 0 0 Gradle Test Executor 41 finished executing tests. > Task :test Finished generating test XML results (0.696 secs) into: /workplace/thp/python-sdk/aws-otel-python-instrumentation/performance-tests/build/test-results/test Generating HTML test report... Finished generating test html results (0.73 secs) into: /workplace/thp/python-sdk/aws-otel-python-instrumentation/performance-tests/build/reports/tests/test Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0. You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins. For more on this, please refer to https://docs.gradle.org/8.6/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation. BUILD SUCCESSFUL in 41m 9s 3 actionable tasks: 1 executed, 2 up-to-date ``` By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
1 parent dbd89b5 commit a86fa2e

31 files changed

+154
-1122
lines changed

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/_instrumentation_patch.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
# SPDX-License-Identifier: Apache-2.0
3+
# Modifications Copyright The OpenTelemetry Authors. Licensed under the Apache License 2.0 License.
34
import importlib
45

56
from opentelemetry.instrumentation.botocore.extensions import _KNOWN_EXTENSIONS
@@ -76,6 +77,7 @@ def patch_extract_attributes(self, attributes: _AttributeMapT):
7677
_SqsExtension.extract_attributes = patch_extract_attributes
7778

7879

80+
# The OpenTelemetry Authors code
7981
def _lazy_load(module, cls):
8082
"""Clone of upstream opentelemetry.instrumentation.botocore.extensions.lazy_load
8183
@@ -89,6 +91,9 @@ def loader():
8991
return loader
9092

9193

94+
# END The OpenTelemetry Authors code
95+
96+
9297
class _S3Extension(_AwsSdkExtension):
9398
def extract_attributes(self, attributes: _AttributeMapT):
9499
bucket_name = self._call_context.params.get("Bucket")

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/aws_opentelemetry_configurator.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
# SPDX-License-Identifier: Apache-2.0
3+
# Modifications Copyright The OpenTelemetry Authors. Licensed under the Apache License 2.0 License.
34
import os
45
from logging import Logger, getLogger
56
from typing import ClassVar, Dict, Type
@@ -84,6 +85,9 @@ def _configure(self, **kwargs):
8485
_initialize_components()
8586

8687

88+
# The OpenTelemetry Authors code
89+
# Long term, we wish to contribute this to upstream to improve initialization customizability and reduce dependency on
90+
# internal logic.
8791
def _initialize_components():
8892
trace_exporters, metric_exporters, log_exporters = _import_exporters(
8993
_get_exporter_names("traces"),
@@ -146,6 +150,9 @@ def _init_tracing(
146150
set_tracer_provider(trace_provider)
147151

148152

153+
# END The OpenTelemetry Authors code
154+
155+
149156
def _exclude_urls_for_instrumentations():
150157
urls_to_exclude_instr = "SamplingTargets,GetSamplingRules"
151158
requests_excluded_urls = os.environ.pop("OTEL_PYTHON_REQUESTS_EXCLUDED_URLS", "")

performance-tests/README.md

Lines changed: 28 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,35 @@
88
- [Setup and Usage](#setup-and-usage)
99
- [Visualization](#visualization)
1010

11-
This directory will contain tools and utilities
12-
that help us to measure the performance overhead introduced by
13-
the distro and to measure how this overhead changes over time.
11+
This directory will contain tools and utilities that help us to measure the performance overhead introduced by the distro and to measure how this overhead changes over time.
1412

15-
The overhead tests here should be considered a "macro" benchmark. They serve to measure high-level
16-
overhead as perceived by the operator of a "typical" application. Tests are performed on a Java 11
17-
distribution from [Eclipse Temurin](https://projects.eclipse.org/projects/adoptium.temurin).
13+
The overhead tests here should be considered a "macro" benchmark. They serve to measure high-level overhead as perceived by the operator of a "typical" application. Tests are performed on Python 3.10.
1814

1915
## Process
2016

21-
There is one dynamic test here called [OverheadTests](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/benchmark-overhead/src/test/java/io/opentelemetry/OverheadTests.java).
22-
The `@TestFactory` method creates a test pass for each of the [defined configurations](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/benchmark-overhead/src/test/java/io/opentelemetry/config/Configs.java).
23-
Before the tests run, a single collector instance is started. Each test pass has one or more distroConfigs and those are tested in series.
24-
For each distro defined in a configuration, the test runner (using [testcontainers](https://www.testcontainers.org/)) will:
17+
There is one dynamic test here called OverheadTests. The `@TestFactory` method creates a test pass for each of the defined configurations. Before the tests run, a single collector instance is started. Each test pass has one or more distroConfigs and those are tested in series. For each distro defined in a configuration, the test runner (using [testcontainers](https://www.testcontainers.org/)) will:
2518

2619
1. create a fresh postgres instance and populate it with initial data.
27-
2. create a fresh instance of [spring-petclinic-rest](https://github.com/spring-petclinic/spring-petclinic-rest) instrumented with the specified distroConfig
28-
3. measure the time until the petclinic app is marked "healthy" and then write it to a file.
29-
4. if configured, perform a warmup phase. During the warmup phase, a bit of traffic is generated in order to get the application into a steady state (primarily helping facilitate jit compilations). Currently, we use a 30 second warmup time.
30-
5. start a JFR recording by running `jcmd` inside the petclinic container
31-
6. run the [k6 test script](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/benchmark-overhead/k6/basic.js) with the configured number of iterations through the file and the configured number of concurrent virtual users (VUs).
32-
7. after k6 completes, petclinic is shut down
33-
8. after petclinic is shut down, postgres is shut down
20+
2. create a fresh instance of vehicle inventory service instrumented with the specified distroConfig, and image service (not currently instrumented)
21+
3. measure the time until the app is marked "healthy" and then write it to a file.
22+
4. if configured, perform a warmup phase. During the warmup phase, a bit of traffic is generated in order to get the application into a steady state (primarily helping facilitate jit compilations).
23+
5. start a profiling recording by running a script that relies on psutils inside the application container
24+
6. run a k6 test script with the configured number of iterations through the file and the configured number of concurrent virtual users (VUs).
25+
7. after k6 completes, application is shut down
26+
8. after application is shut down, postgres is shut down
3427

3528
And this repeats for every distro configured in each test configuration.
3629

3730
After all the tests are complete, the results are collected and committed back to the `/results` subdirectory as csv and summary text files.
3831

3932
## What do we measure?
4033

41-
For each test pass, we record the following metrics in order to compare distroConfigs and determine
42-
relative overhead.
34+
For each test pass, we record the following metrics in order to compare distroConfigs and determine relative overhead.
35+
36+
// WIP: This list will change once we finalize the profiling script.
4337

4438
| metric name | units | description |
45-
| ------------------------ | ------ | ---------------------------------------------------------------------------- |
39+
|--------------------------| ------ |------------------------------------------------------------------------------|
4640
| Startup time | ms | How long it takes for the spring app to report "healthy" |
4741
| Total allocated mem | bytes | Across the life of the application |
4842
| Heap (min) | bytes | Smallest observed heap size |
@@ -56,10 +50,10 @@ relative overhead.
5650
| Peak threads | # | Highest number of running threads in the VM, including distroConfig threads |
5751
| Network read mean | bits/s | Average network read rate |
5852
| Network write mean | bits/s | Average network write rate |
59-
| Average JVM user CPU | % | Average observed user CPU (range 0.0-1.0) |
60-
| Max JVM user CPU | % | Max observed user CPU used (range 0.0-1.0) |
53+
| Average user CPU | % | Average observed user CPU (range 0.0-1.0) |
54+
| Max user CPU | % | Max observed user CPU used (range 0.0-1.0) |
6155
| Average machine tot. CPU | % | Average percentage of machine CPU used (range 0.0-1.0) |
62-
| Total GC pause nanos | ns | JVM time spent paused due to GC |
56+
| Total GC pause nanos | ns | time spent paused due to GC |
6357
| Run duration ms | ms | Duration of the test run, in ms |
6458

6559
## Config
@@ -74,41 +68,25 @@ Each config contains the following:
7468
- totalIterations - the number of passes to make through the k6 test script
7569
- warmupSeconds - how long to wait before starting conducting measurements
7670

77-
Currently, we test:
78-
79-
- no distro versus latest released distro
80-
- no distro versus latest snapshot
81-
- latest release vs. latest snapshot
82-
8371
Additional configurations can be created by submitting a PR against the `Configs` class.
8472

8573
### DistroConfigs
8674

87-
An distroConfig is defined in code as a name, description, optional URL, and optional additional
88-
arguments to be passed to the JVM (not including `-javaagent:`). New distroConfigs may be defined
89-
by creating new instances of the `Distro` class. The `AgentResolver` is used to download
90-
the relevant distroConfig jar for an `Distro` definition.
91-
92-
## Automation
93-
94-
The tests are run nightly via github actions. The results are collected and appended to
95-
a csv file, which is committed back to the repo in the `/results` subdirectory.
75+
An distroConfig is defined in code as a name, description, flag for instrumentation. and optional additional arguments to be passed to the application container. New distroConfigs may be defined by creating new instances of the `Distro` class. The `AgentResolver` is used to download the relevant distroConfig jar for an `Distro` definition.
9676

9777
## Setup and Usage
9878

99-
The tests require docker to be running. Simply run `OverheadTests` in your IDE.
79+
Pre-requirements:
80+
* Have `docker` installed and running - verify by running the `docker` command.
81+
* Export AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, and S3_BUCKET environment variables.
10082

101-
Alternatively, you can run the tests from
102-
the command line with gradle:
103-
104-
```
105-
cd benchmark-overhead
83+
Steps:
84+
* From `aws-otel-python-instrumentation` dir, execute:
85+
```sh
86+
./scripts/build_and_install_distro.sh
87+
./scripts/set-up-performance-tests.sh
88+
cd performance-tests
10689
./gradlew test
107-
10890
```
10991

110-
## Visualization
111-
112-
None yet. Help wanted! Our goal is to have the results and a rich UI running in the
113-
`gh-pages` branch similar to [earlier tools](https://breedx-splk.github.io/iguanodon/web/).
114-
Please help us make this happen.
92+
The last step can be run or you can run from IDE (after setting environment variables appropriately).

performance-tests/k6/basic.js

Lines changed: 0 additions & 43 deletions
This file was deleted.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import http from "k6/http";
2+
import {check} from "k6";
3+
4+
const baseUri = 'http://vehicle-service:8001/vehicle-inventory/';
5+
// Fake ID to trigger 400's.
6+
const badId = 1000;
7+
8+
export default function() {
9+
/**
10+
* Calls all Vehicle Inventory Service APIs.
11+
*
12+
* Note that there are no modifications to the database - all POSTs and DELETEs will fail.
13+
* This ensures the database does not grow over time. Data is initially added in setUp.js.
14+
*/
15+
16+
invokeApi("oops", "GET", 404)
17+
invokeApi("", "GET", 200)
18+
invokeApi("", "POST", 400)
19+
invokeApi("1", "GET", 200)
20+
invokeApi(`${badId}`, "DELETE", 404)
21+
invokeApi("make/Toyota", "GET", 200)
22+
invokeApi("1/image", "GET", 200)
23+
invokeApi("image/toy_rav_24.png", "GET", 200)
24+
invokeApi("image/", "POST", 404)
25+
invokeApi("history/", "GET", 200)
26+
invokeApi("history/", "POST", 400)
27+
invokeApi("history/1", "GET", 200)
28+
invokeApi(`history/${badId}`, "DELETE", 404)
29+
invokeApi("history/1/vehicle", "GET", 200)
30+
31+
function invokeApi(path, method, status) {
32+
const url = `${baseUri}${path}`;
33+
let response;
34+
switch(method) {
35+
case "GET":
36+
response = http.get(url);
37+
break;
38+
case "POST":
39+
response = http.post(url, JSON.stringify({"badKey": "badValue"}));
40+
break;
41+
case "DELETE":
42+
response = http.del(url);
43+
break;
44+
}
45+
check(response, {
46+
[`${method} ${path} response ${status}`] : (response) => response.status === status
47+
});
48+
}
49+
};

performance-tests/k6/setUp.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import http from "k6/http";
2+
import {check} from "k6";
3+
4+
const baseUri = 'http://vehicle-service:8001/vehicle-inventory/';
5+
6+
export default function() {
7+
postVehicle({'id': 1,'make': 'Toyota', 'model': 'Rav4', 'year': 2024, 'image_name': 'toy_rav_24.png'});
8+
postVehicle({'id': 2,'make': 'Toyota', 'model': 'Rav4', 'year': 2023, 'image_name': 'toy_rav_23.png'});
9+
postVehicle({'id': 3,'make': 'Honda', 'model': 'Odyssey', 'year': 2022, 'image_name': 'hon_ody_22.png'});
10+
postVehicle({'id': 4,'make': 'Honda', 'model': 'Odyssey', 'year': 2024, 'image_name': 'hon_ody_24.png'});
11+
12+
postVehicleHistory({'id': 1, 'purchase_date': '2024-01-29', 'purchase_price': 55999, 'vehicle_id': 1});
13+
postVehicleHistory({'id': 2, 'purchase_date': '2024-02-29', 'purchase_price': 54999, 'vehicle_id': 1});
14+
postVehicleHistory({'id': 3, 'purchase_date': '2023-12-14', 'purchase_price': 13999, 'vehicle_id': 3});
15+
16+
function postVehicle(body) {
17+
const response = http.post(baseUri, JSON.stringify(body));
18+
check(response, {
19+
[`POST vehicle response 200`] : (response) => response.status === 200
20+
});
21+
}
22+
23+
function postVehicleHistory(body) {
24+
const response = http.post(`${baseUri}history/`, JSON.stringify(body));
25+
check(response, {
26+
[`POST vehicle history response 200`] : (response) => response.status === 200
27+
});
28+
}
29+
};

performance-tests/src/test/java/io/opentelemetry/OverheadTests.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*
22
* Copyright The OpenTelemetry Authors
33
* SPDX-License-Identifier: Apache-2.0
4+
* Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
45
*/
56

67
package io.opentelemetry;
@@ -96,6 +97,8 @@ void runAppOnce(TestConfig config, DistroConfig distroConfig) throws Exception {
9697
vehicleInventoryService.start();
9798
writeStartupTimeFile(distroConfig, start);
9899

100+
populateDatabase();
101+
99102
if (config.getWarmupSeconds() > 0) {
100103
// doWarmupPhase(config, vehicleInventoryService);
101104
}
@@ -167,6 +170,16 @@ private void doWarmupPhase(TestConfig testConfig, GenericContainer<?> vehicleInv
167170
System.out.println("Warmup complete.");
168171
}
169172

173+
private void populateDatabase() {
174+
GenericContainer<?> k6 =
175+
new GenericContainer<>(DockerImageName.parse("loadimpact/k6"))
176+
.withNetwork(NETWORK)
177+
.withCopyFileToContainer(MountableFile.forHostPath("./k6"), "/app")
178+
.withCommand("run", "/app/setUp.js")
179+
.withStartupCheckStrategy(new OneShotStartupCheckStrategy());
180+
k6.start();
181+
}
182+
170183
private void writeStartupTimeFile(DistroConfig distroConfig, long start) throws IOException {
171184
long delta = System.currentTimeMillis() - start;
172185
Path startupPath = namingConventions.local.startupDurationFile(distroConfig);

performance-tests/src/test/java/io/opentelemetry/config/Configs.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*
22
* Copyright The OpenTelemetry Authors
33
* SPDX-License-Identifier: Apache-2.0
4+
* Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
45
*/
56

67
package io.opentelemetry.config;

performance-tests/src/test/java/io/opentelemetry/config/TestConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*
22
* Copyright The OpenTelemetry Authors
33
* SPDX-License-Identifier: Apache-2.0
4+
* Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
45
*/
56

67
package io.opentelemetry.config;

performance-tests/src/test/java/io/opentelemetry/containers/CollectorContainer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*
22
* Copyright The OpenTelemetry Authors
33
* SPDX-License-Identifier: Apache-2.0
4+
* Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
45
*/
56

67
package io.opentelemetry.containers;

0 commit comments

Comments
 (0)