Skip to content

Commit 99d8307

Browse files
committed
Add support for basic metadata.yaml file
1 parent c7676bd commit 99d8307

File tree

11 files changed

+123
-60
lines changed

11 files changed

+123
-60
lines changed

docs/contributing/writing-instrumentation.md

+16-38
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ instrumentation ->
5858
build.gradle.kts
5959
testing
6060
build.gradle.kts
61+
metadata.yaml
6162
```
6263

6364
The top level `settings.gradle.kts` file would contain the following (please add in alphabetical order):
@@ -68,6 +69,15 @@ include("instrumentation:yarpc-1.0:library")
6869
include("instrumentation:yarpc-1.0:testing")
6970
```
7071

72+
### Instrumentation metadata.yaml (Experimental)
73+
74+
Each module can contain a `metadata.yaml` file that describes the instrumentation. This information
75+
is then used when generating the [instrumentation-list.yaml](../instrumentation-list.yaml) file.
76+
The schema for `metadata.yaml` is still in development and may change in the future. See the
77+
[instrumentation-docs readme](../../instrumentation-docs/readme.md) for more information and the
78+
latest schema.
79+
80+
7181
### Instrumentation Submodules
7282

7383
When writing instrumentation that requires submodules for different versions, the name of each
@@ -215,10 +225,10 @@ library instrumentation test, there will be code calling into the instrumentatio
215225
javaagent instrumentation test it will generally use the underlying library API as is and just rely
216226
on the javaagent to apply all the necessary bytecode changes automatically.
217227

218-
You can use either JUnit 5 (recommended) or Spock to test the instrumentation. Start by creating an
219-
abstract class with an abstract method, for example `configure()`, that returns the instrumented
220-
object, such as a client, server, or the main class of the instrumented library. Then, depending on
221-
the chosen test library, go to the [JUnit](#junit) or [Spock](#spock) section.
228+
You can use JUnit 5 to test the instrumentation. Start by creating an abstract class with an
229+
abstract method, for example `configure()`, that returns the instrumented object, such as a client,
230+
server, or the main class of the instrumented library. See the [JUnit](#junit) section for more
231+
information.
222232

223233
After writing some tests, return to the `library` package and make sure it has
224234
a `testImplementation` dependency on the `testing` submodule. Then, create a test class that extends
@@ -281,37 +291,6 @@ You can use the `@RegisterExtension` annotation to make sure that the instrument
281291
picked up by JUnit. Then, return the same extension instance in the `testing()` method
282292
implementation so that it's used in all test scenarios implemented in the abstract class.
283293

284-
### Spock
285-
286-
The `testing-common` module contains some utilities that facilitate writing Spock instrumentation
287-
tests, such as the `InstrumentationSpecification` base class and the `LibraryTestTrait`
288-
and `AgentTestTrait` traits.
289-
290-
Consider the following abstract test class extending `InstrumentationSpecification`:
291-
292-
```groovy
293-
abstract class AbstractYarpcTest extends InstrumentationSpecification {
294-
295-
abstract Yarpc configure(Yarpc yarpc);
296-
297-
def "test something"() {
298-
// ...
299-
}
300-
}
301-
```
302-
303-
The `InstrumentationSpecification` class contains abstract methods that are implemented by one of
304-
our test traits in the actual test class. For example:
305-
306-
```groovy
307-
class LibraryYarpcTest extends AbstractYarpcTest implements LibraryTestTrait {
308-
309-
@Override
310-
Yarpc configure(Yarpc yarpc) {
311-
// register interceptor/listener etc
312-
}
313-
}
314-
```
315294

316295
## Writing Java agent instrumentation
317296

@@ -352,9 +331,8 @@ without the user knowing about the instrumentation.
352331

353332
Create a test that extends the base class you wrote earlier but does nothing in the `configure()`
354333
method. Unlike the library instrumentation, the javaagent instrumentation is supposed to work
355-
without any explicit user code modification. Depending on the testing framework, either use
356-
the `AgentInstrumentationExtension` or implement the `AgentTestingTrait`, and try running tests in
357-
this class. All tests should pass.
334+
without any explicit user code modification. Add an `AgentInstrumentationExtension` and try running
335+
tests in this class. All tests should pass.
358336

359337
Note that all the tests inside the `javaagent` module are run using the `agent-for-testing`
360338
javaagent, with the instrumentation being loaded as an extension. This is done to perform the same

docs/instrumentation-list.yaml

+4-1
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,13 @@ cassandra:
204204
- name: cassandra-3.0
205205
srcPath: instrumentation/cassandra/cassandra-3.0
206206
target_versions:
207-
javaagent: []
207+
javaagent:
208+
- com.datastax.cassandra:cassandra-driver-core:[3.0,4.0)
208209
clickhouse:
209210
instrumentations:
210211
- name: clickhouse-client-0.5
212+
description: Instruments the V1 ClickHouseClient, providing database client spans
213+
and metrics.
211214
srcPath: instrumentation/clickhouse-client-0.5
212215
target_versions:
213216
javaagent:

instrumentation-docs/readme.md

+20-5
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,36 @@ public class SpringWebInstrumentationModule extends InstrumentationModule
3939
}
4040
```
4141

42-
## Instrumentation meta-data
42+
## Instrumentation metadata
4343

4444
* name
4545
* Identifier for instrumentation module, used to enable/disable
4646
* Configured in `InstrumentationModule` code for each module
47-
* versions
48-
* List of supported versions by the module
49-
* type
50-
* List of instrumentation types, options of either `library` or `javaagent`
47+
* srcPath
48+
* Path to the source code of the instrumentation module
49+
* description
50+
* Short description of what the instrumentation does
51+
* target_versions
52+
* List of supported versions by the module, broken down by `library` or `javaagent` support
53+
5154

5255
## Methodology
5356

57+
### metadata.yaml file
58+
59+
Within each instrumentation source directory, a `metadata.yaml` file can be created to provide
60+
additional information about the instrumentation module.
61+
62+
As of now, the following fields are supported:
63+
64+
```yaml
65+
description: "Description of what the instrumentation does."
66+
```
67+
5468
### Versions targeted
5569

5670
We parse gradle files in order to determine the target versions.
5771

5872
- Javaagent versions are determined by the `muzzle` plugin configurations
5973
- Library versions are determined by the library dependency versions
74+
- when available, latestDepTestLibrary is used to determine the latest supported version

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

+9-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import io.opentelemetry.instrumentation.docs.utils.FileManager;
1111
import io.opentelemetry.instrumentation.docs.utils.InstrumentationPath;
12+
import io.opentelemetry.instrumentation.docs.utils.YamlHelper;
1213
import java.util.ArrayList;
1314
import java.util.HashMap;
1415
import java.util.HashSet;
@@ -53,8 +54,9 @@ public static List<InstrumentationEntity> convertToEntities(List<Instrumentation
5354
}
5455

5556
/**
56-
* Analyzes the given root directory to find all instrumentation paths and then analyze them. -
57-
* Extracts version information from each instrumentation's build.gradle file.
57+
* Analyzes the given root directory to find all instrumentation paths and then analyze them.
58+
* Extracts version information from each instrumentation's build.gradle file. Extracts
59+
* information from metadata.yaml files.
5860
*
5961
* @return a list of InstrumentationEntity objects with target versions
6062
*/
@@ -65,6 +67,11 @@ List<InstrumentationEntity> analyze() {
6567
for (InstrumentationEntity entity : entities) {
6668
List<String> gradleFiles = fileSearch.findBuildGradleFiles(entity.getSrcPath());
6769
analyzeVersions(gradleFiles, entity);
70+
71+
String metadataFile = fileSearch.getMetaDataFile(entity.getSrcPath());
72+
if (metadataFile != null) {
73+
entity.setMetadata(YamlHelper.metaDataParser(metadataFile));
74+
}
6875
}
6976
return entities;
7077
}

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

+13-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ public class InstrumentationEntity {
1313
private final String instrumentationName;
1414
private final String namespace;
1515
private final String group;
16+
17+
private InstrumentationMetaData metadata;
1618
private Map<InstrumentationType, Set<String>> targetVersions;
1719

1820
public InstrumentationEntity(
@@ -28,12 +30,22 @@ public InstrumentationEntity(
2830
String instrumentationName,
2931
String namespace,
3032
String group,
31-
Map<InstrumentationType, Set<String>> targetVersions) {
33+
Map<InstrumentationType, Set<String>> targetVersions,
34+
InstrumentationMetaData metadata) {
3235
this.srcPath = srcPath;
3336
this.instrumentationName = instrumentationName;
3437
this.namespace = namespace;
3538
this.group = group;
3639
this.targetVersions = targetVersions;
40+
this.metadata = metadata;
41+
}
42+
43+
public void setMetadata(InstrumentationMetaData metadata) {
44+
this.metadata = metadata;
45+
}
46+
47+
public InstrumentationMetaData getMetadata() {
48+
return metadata;
3749
}
3850

3951
public String getSrcPath() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.docs;
7+
8+
public class InstrumentationMetaData {
9+
10+
public InstrumentationMetaData() {}
11+
12+
public InstrumentationMetaData(String description) {
13+
this.description = description;
14+
}
15+
16+
private String description;
17+
18+
public String getDescription() {
19+
return description;
20+
}
21+
22+
public void setDescription(String description) {
23+
this.description = description;
24+
}
25+
}

instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/utils/FileManager.java

+8
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,14 @@ public List<String> findBuildGradleFiles(String instrumentationDirectory) {
102102
}
103103
}
104104

105+
public String getMetaDataFile(String instrumentationDirectory) {
106+
String metadataFile = instrumentationDirectory + "/metadata.yaml";
107+
if (Files.exists(Paths.get(metadataFile))) {
108+
return readFileToString(metadataFile);
109+
}
110+
return null;
111+
}
112+
105113
public String readFileToString(String filePath) {
106114
try {
107115
return Files.readString(Paths.get(filePath));

instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/utils/YamlHelper.java

+15-5
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
package io.opentelemetry.instrumentation.docs.utils;
77

88
import io.opentelemetry.instrumentation.docs.InstrumentationEntity;
9+
import io.opentelemetry.instrumentation.docs.InstrumentationMetaData;
910
import java.io.BufferedWriter;
1011
import java.util.ArrayList;
12+
import java.util.LinkedHashMap;
1113
import java.util.List;
1214
import java.util.Map;
1315
import java.util.TreeMap;
@@ -29,21 +31,25 @@ public static void printInstrumentationList(
2931
Map<String, Object> output = new TreeMap<>();
3032
groupedByGroup.forEach(
3133
(group, entities) -> {
32-
Map<String, Object> groupMap = new TreeMap<>();
34+
Map<String, Object> groupMap = new LinkedHashMap<>();
3335
List<Map<String, Object>> instrumentations = new ArrayList<>();
3436
for (InstrumentationEntity entity : entities) {
35-
Map<String, Object> entityMap = new TreeMap<>();
37+
Map<String, Object> entityMap = new LinkedHashMap<>();
3638
entityMap.put("name", entity.getInstrumentationName());
39+
40+
if (entity.getMetadata() != null && entity.getMetadata().getDescription() != null) {
41+
entityMap.put("description", entity.getMetadata().getDescription());
42+
}
43+
3744
entityMap.put("srcPath", entity.getSrcPath());
3845

3946
Map<String, Object> targetVersions = new TreeMap<>();
4047
if (entity.getTargetVersions() != null && !entity.getTargetVersions().isEmpty()) {
4148
entity
4249
.getTargetVersions()
4350
.forEach(
44-
(type, versions) -> {
45-
targetVersions.put(type.toString(), new ArrayList<>(versions));
46-
});
51+
(type, versions) ->
52+
targetVersions.put(type.toString(), new ArrayList<>(versions)));
4753
}
4854
entityMap.put("target_versions", targetVersions);
4955
instrumentations.add(entityMap);
@@ -60,5 +66,9 @@ public static void printInstrumentationList(
6066
yaml.dump(output, writer);
6167
}
6268

69+
public static InstrumentationMetaData metaDataParser(String input) {
70+
return new Yaml().loadAs(input, InstrumentationMetaData.class);
71+
}
72+
6373
private YamlHelper() {}
6474
}

instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/utils/YamlHelperTest.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import static org.assertj.core.api.Assertions.assertThat;
99

1010
import io.opentelemetry.instrumentation.docs.InstrumentationEntity;
11+
import io.opentelemetry.instrumentation.docs.InstrumentationMetaData;
1112
import io.opentelemetry.instrumentation.docs.InstrumentationType;
1213
import java.io.BufferedWriter;
1314
import java.io.StringWriter;
@@ -21,20 +22,24 @@
2122

2223
class YamlHelperTest {
2324
@Test
24-
public void testPrintInstrumentationList() throws Exception {
25+
void testPrintInstrumentationList() throws Exception {
2526
List<InstrumentationEntity> entities = new ArrayList<>();
2627
Map<InstrumentationType, Set<String>> targetVersions1 = new HashMap<>();
2728
targetVersions1.put(
2829
InstrumentationType.JAVAAGENT,
2930
new HashSet<>(List.of("org.springframework:spring-web:[6.0.0,)")));
3031

32+
InstrumentationMetaData metadata1 =
33+
new InstrumentationMetaData("Spring Web 6.0 instrumentation");
34+
3135
entities.add(
3236
new InstrumentationEntity(
3337
"instrumentation/spring/spring-web/spring-web-6.0",
3438
"spring-web-6.0",
3539
"spring",
3640
"spring",
37-
targetVersions1));
41+
targetVersions1,
42+
metadata1));
3843

3944
Map<InstrumentationType, Set<String>> targetVersions2 = new HashMap<>();
4045
targetVersions2.put(
@@ -46,7 +51,8 @@ public void testPrintInstrumentationList() throws Exception {
4651
"struts-2.3",
4752
"struts",
4853
"struts",
49-
targetVersions2));
54+
targetVersions2,
55+
null));
5056

5157
StringWriter stringWriter = new StringWriter();
5258
BufferedWriter writer = new BufferedWriter(stringWriter);
@@ -58,6 +64,7 @@ public void testPrintInstrumentationList() throws Exception {
5864
"spring:\n"
5965
+ " instrumentations:\n"
6066
+ " - name: spring-web-6.0\n"
67+
+ " description: Spring Web 6.0 instrumentation\n"
6168
+ " srcPath: instrumentation/spring/spring-web/spring-web-6.0\n"
6269
+ " target_versions:\n"
6370
+ " javaagent:\n"

instrumentation/cassandra/cassandra-3.0/javaagent/build.gradle.kts

+2-5
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,11 @@ plugins {
22
id("otel.javaagent-instrumentation")
33
}
44

5-
val cassandraDriverTestVersions = "[3.0,4.0)"
6-
75
muzzle {
8-
96
pass {
107
group.set("com.datastax.cassandra")
118
module.set("cassandra-driver-core")
12-
versions.set(cassandraDriverTestVersions)
9+
versions.set("[3.0,4.0)")
1310
assertInverse.set(true)
1411
}
1512

@@ -19,7 +16,7 @@ muzzle {
1916
name.set("Newest versions of Guava")
2017
group.set("com.datastax.cassandra")
2118
module.set("cassandra-driver-core")
22-
versions.set(cassandraDriverTestVersions)
19+
versions.set("[3.0,4.0)")
2320
// While com.datastax.cassandra uses old versions of Guava, users may depends themselves on newer versions of Guava
2421
extraDependency("com.google.guava:guava:27.0-jre")
2522
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
description: Instruments the V1 ClickHouseClient, providing database client spans and metrics.

0 commit comments

Comments
 (0)