Skip to content

Commit 94d2c0f

Browse files
authored
Intercept metrics in test runner (open-telemetry#13891)
1 parent 2490a17 commit 94d2c0f

File tree

20 files changed

+687
-47
lines changed

20 files changed

+687
-47
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ derby.log
5757
hs_err_pid*
5858
replay_pid*
5959
.attach_pid*
60+
**/.telemetry*
6061

6162
!java-agent/benchmark/releases/*.jar
6263

docs/instrumentation-list.yaml

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,46 @@ libraries:
5454
- com.alibaba:druid:(,)
5555
library:
5656
- com.alibaba:druid:1.0.0
57+
metrics:
58+
- name: db.client.connections.usage
59+
description: The number of connections that are currently in state described
60+
by the state attribute.
61+
type: LONG_SUM
62+
unit: connections
63+
attributes:
64+
- name: pool.name
65+
type: STRING
66+
- name: state
67+
type: STRING
68+
- name: db.client.connections.pending_requests
69+
description: The number of pending requests for an open connection, cumulative
70+
for the entire pool.
71+
type: LONG_SUM
72+
unit: requests
73+
attributes:
74+
- name: pool.name
75+
type: STRING
76+
- name: db.client.connections.max
77+
description: The maximum number of open connections allowed.
78+
type: LONG_SUM
79+
unit: connections
80+
attributes:
81+
- name: pool.name
82+
type: STRING
83+
- name: db.client.connections.idle.min
84+
description: The minimum number of idle open connections allowed.
85+
type: LONG_SUM
86+
unit: connections
87+
attributes:
88+
- name: pool.name
89+
type: STRING
90+
- name: db.client.connections.idle.max
91+
description: The maximum number of idle open connections allowed.
92+
type: LONG_SUM
93+
unit: connections
94+
attributes:
95+
- name: pool.name
96+
type: STRING
5797
apache:
5898
- name: apache-shenyu-2.4
5999
source_path: instrumentation/apache-shenyu-2.4
@@ -831,7 +871,7 @@ libraries:
831871
services.
832872
type: map
833873
default: ''
834-
- name: otel.instrumentation.jdbc.capture-query-parameters
874+
- name: otel.instrumentation.jdbc.experimental.capture-query-parameters
835875
description: |
836876
Sets whether the query parameters should be captured as span attributes named <code>db.query.parameter.&lt;key&gt;</code>. Enabling this option disables the statement sanitization.<p>WARNING: captured query parameters may contain sensitive information such as passwords, personally identifiable information or protected health info.
837877
type: boolean
@@ -1910,6 +1950,22 @@ libraries:
19101950
target_versions:
19111951
javaagent:
19121952
- io.vertx:vertx-redis-client:[4.0.0,)
1953+
- name: vertx-sql-client-5.0
1954+
source_path: instrumentation/vertx/vertx-sql-client/vertx-sql-client-5.0
1955+
minimum_java_version: 11
1956+
scope:
1957+
name: io.opentelemetry.vertx-sql-client-5.0
1958+
target_versions:
1959+
javaagent:
1960+
- io.vertx:vertx-sql-client:[5.0.0,)
1961+
- name: vertx-http-client-5.0
1962+
source_path: instrumentation/vertx/vertx-http-client/vertx-http-client-5.0
1963+
minimum_java_version: 11
1964+
scope:
1965+
name: io.opentelemetry.vertx-http-client-5.0
1966+
target_versions:
1967+
javaagent:
1968+
- io.vertx:vertx-core:[5.0.0,)
19131969
- name: vertx-web-3.0
19141970
source_path: instrumentation/vertx/vertx-web-3.0
19151971
scope:
@@ -1918,19 +1974,19 @@ libraries:
19181974
javaagent:
19191975
- io.vertx:vertx-web:[3.0.0,)
19201976
- name: vertx-sql-client-4.0
1921-
source_path: instrumentation/vertx/vertx-sql-client-4.0
1977+
source_path: instrumentation/vertx/vertx-sql-client/vertx-sql-client-4.0
19221978
scope:
19231979
name: io.opentelemetry.vertx-sql-client-4.0
19241980
target_versions:
19251981
javaagent:
1926-
- io.vertx:vertx-sql-client:[4.0.0,)
1982+
- io.vertx:vertx-sql-client:[4.0.0,5)
19271983
- name: vertx-http-client-4.0
19281984
source_path: instrumentation/vertx/vertx-http-client/vertx-http-client-4.0
19291985
scope:
19301986
name: io.opentelemetry.vertx-http-client-4.0
19311987
target_versions:
19321988
javaagent:
1933-
- io.vertx:vertx-core:[4.0.0,)
1989+
- io.vertx:vertx-core:[4.0.0,5)
19341990
- name: vertx-rx-java-3.5
19351991
source_path: instrumentation/vertx/vertx-rx-java-3.5
19361992
scope:
@@ -2051,6 +2107,10 @@ internal:
20512107
source_path: instrumentation/opentelemetry-api/opentelemetry-api-1.32
20522108
scope:
20532109
name: io.opentelemetry.opentelemetry-api-1.32
2110+
- name: opentelemetry-api-1.50
2111+
source_path: instrumentation/opentelemetry-api/opentelemetry-api-1.50
2112+
scope:
2113+
name: io.opentelemetry.opentelemetry-api-1.50
20542114
- name: opentelemetry-api-1.42
20552115
source_path: instrumentation/opentelemetry-api/opentelemetry-api-1.42
20562116
scope:

instrumentation-docs/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
plugins {
22
id("otel.java-conventions")
3+
id("otel.nullaway-conventions")
34
}
45

56
otelJava {

instrumentation-docs/collect.sh

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/bin/bash
2+
3+
instrumentations=(
4+
"alibaba-druid-1.0:javaagent:test"
5+
)
6+
7+
# Initialize an empty string to hold the Gradle tasks
8+
gradle_tasks=""
9+
10+
# Iterate over each instrumentation
11+
for instrumentation in "${instrumentations[@]}"; do
12+
# Extract the parts of the instrumentation
13+
IFS=':' read -r -a parts <<< "$instrumentation"
14+
module="${parts[0]}"
15+
version="${parts[1]}"
16+
type="${parts[2]}"
17+
suffix="${parts[3]}"
18+
19+
# Assemble the path to the instrumentation
20+
path="instrumentation/$module/$version"
21+
22+
# Remove any occurrence of /javaagent/ or /library/ from the path
23+
path=$(echo "$path" | sed -e 's/\/javaagent//g' -e 's/\/library//g')
24+
25+
# Debugging: Print the path being checked
26+
echo "Checking path: $path/.telemetry"
27+
28+
# Check if the .telemetry directory exists and remove it if it does
29+
if [ -d "$path/.telemetry" ]; then
30+
echo "Removing directory: $path/.telemetry"
31+
rm -rf "$path/.telemetry"
32+
else
33+
echo "Directory does not exist: $path/.telemetry"
34+
fi
35+
36+
# Append the Gradle task to the gradle_tasks string with a colon between type and suffix if suffix is non-empty
37+
if [ -n "$suffix" ]; then
38+
gradle_tasks+=":instrumentation:$module:$version:$type:$suffix"
39+
else
40+
gradle_tasks+=":instrumentation:$module:$version:$type"
41+
fi
42+
done
43+
44+
# rerun-tasks is used to force re-running tests that might be cached
45+
echo Running: ./gradlew "$gradle_tasks" -PcollectMetadata=true --rerun-tasks
46+
./gradlew "$gradle_tasks" -PcollectMetadata=true --rerun-tasks
47+
./gradlew :instrumentation-docs:runAnalysis
48+
49+
# Remove all .telemetry directories recursively from the project root
50+
echo "Searching for and removing all .telemetry directories..."
51+
find . -type d -name ".telemetry" -exec rm -rf {} +

instrumentation-docs/readme.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,36 @@ Run the analysis to update the instrumentation-list.yaml:
88

99
`./gradlew :instrumentation-docs:runAnalysis`
1010

11+
### Metric collection
12+
13+
Until this process is ready for all instrumentations, each module will be modified to include a
14+
system property feature flag configured for when the tests run:
15+
16+
```kotlin
17+
tasks {
18+
test {
19+
systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false")
20+
...
21+
}
22+
}
23+
```
24+
25+
Then, prior to running the analyzer, run the following command to generate `.telemetry` files:
26+
27+
`./gradlew test -PcollectMetadata=true`
28+
29+
Then run the doc generator
30+
31+
`./gradlew :instrumentation-docs:runAnalysis`
32+
33+
or use the helper script that will run only the currently supported tests (recommended):
34+
35+
```bash
36+
./instrumentation-docs/collect.sh
37+
```
38+
39+
This script will also clean up all `.telemetry` files after the analysis is done.
40+
1141
## Instrumentation Hierarchy
1242

1343
An "InstrumentationModule" represents a module that that targets specific code in a
@@ -70,6 +100,8 @@ public class SpringWebInstrumentationModule extends InstrumentationModule
70100
* configurations settings
71101
* List of settings that are available for the instrumentation module
72102
* Each setting has a name, description, type, and default value
103+
* metrics
104+
* List of metrics that the instrumentation module collects, including the metric name, description, type, and attributes
73105

74106
## Methodology
75107

@@ -107,3 +139,14 @@ name is determined by the instrumentation module name: `io.opentelemetry.{instr
107139

108140
We will implement gatherers for the schemaUrl and scope attributes when instrumentations start
109141
implementing them.
142+
143+
### Metrics
144+
145+
In order to identify what metrics are emitted from instrumentations, we can hook into the
146+
`InstrumentationTestRunner` class and collect the metrics generated during runs. We can then
147+
leverage the `afterTestClass()` in the Agent and library test runners to then write this information
148+
into temporary files. When we analyze the instrumentation modules, we can read these files and
149+
generate the metrics section of the instrumentation-list.yaml file.
150+
151+
The data is written into a `.telemetry` directory in the root of each instrumentation module. This
152+
data will be excluded from git and just generated on demand.

instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/InstrumentationAnalyzer.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.fasterxml.jackson.core.JsonProcessingException;
1111
import com.fasterxml.jackson.databind.exc.ValueInstantiationException;
1212
import io.opentelemetry.instrumentation.docs.internal.DependencyInfo;
13+
import io.opentelemetry.instrumentation.docs.internal.EmittedMetrics;
1314
import io.opentelemetry.instrumentation.docs.internal.InstrumentationModule;
1415
import io.opentelemetry.instrumentation.docs.internal.InstrumentationType;
1516
import io.opentelemetry.instrumentation.docs.utils.FileManager;
@@ -84,6 +85,14 @@ List<InstrumentationModule> analyze() throws JsonProcessingException {
8485
throw e;
8586
}
8687
}
88+
89+
String emittedMetrics = fileManager.getMetrics(module.getSrcPath());
90+
if (emittedMetrics != null) {
91+
EmittedMetrics metrics = YamlHelper.emittedMetricsParser(emittedMetrics);
92+
if (metrics != null && metrics.getMetrics() != null) {
93+
module.setMetrics(metrics.getMetrics());
94+
}
95+
}
8796
}
8897
return modules;
8998
}
@@ -92,6 +101,10 @@ void analyzeVersions(List<String> files, InstrumentationModule module) {
92101
Map<InstrumentationType, Set<String>> versions = new HashMap<>();
93102
for (String file : files) {
94103
String fileContents = fileManager.readFileToString(file);
104+
if (fileContents == null) {
105+
continue;
106+
}
107+
95108
DependencyInfo results = null;
96109

97110
if (file.contains("/javaagent/")) {

instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/DependencyInfo.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
package io.opentelemetry.instrumentation.docs.internal;
77

88
import java.util.Set;
9+
import javax.annotation.Nullable;
910

1011
/**
1112
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
1213
* any time.
1314
*/
14-
public record DependencyInfo(Set<String> versions, Integer minJavaVersionSupported) {}
15+
public record DependencyInfo(Set<String> versions, @Nullable Integer minJavaVersionSupported) {}

0 commit comments

Comments
 (0)