Skip to content

Commit a939b59

Browse files
authored
Intercept and collect spans in test runner (#14065)
1 parent cc28ab8 commit a939b59

File tree

24 files changed

+2031
-818
lines changed

24 files changed

+2031
-818
lines changed

docs/instrumentation-list.yaml

Lines changed: 762 additions & 657 deletions
Large diffs are not rendered by default.

instrumentation-docs/collect.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ readonly INSTRUMENTATIONS=(
2121
"apache-dbcp-2.0:javaagent:test"
2222
"apache-dbcp-2.0:javaagent:testStableSemconv"
2323
"apache-httpclient:apache-httpclient-5.0:javaagent:test"
24+
"apache-dubbo-2.7:javaagent:testDubbo"
2425
"c3p0-0.9:javaagent:test"
2526
"c3p0-0.9:javaagent:testStableSemconv"
2627
"clickhouse-client-0.5:javaagent:test"

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

Lines changed: 66 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,31 @@
55

66
package io.opentelemetry.instrumentation.docs;
77

8-
import static io.opentelemetry.instrumentation.docs.parsers.GradleParser.parseGradleFile;
9-
8+
import com.fasterxml.jackson.core.JsonProcessingException;
109
import com.fasterxml.jackson.databind.exc.ValueInstantiationException;
11-
import io.opentelemetry.instrumentation.docs.internal.DependencyInfo;
1210
import io.opentelemetry.instrumentation.docs.internal.EmittedMetrics;
11+
import io.opentelemetry.instrumentation.docs.internal.InstrumentationMetaData;
1312
import io.opentelemetry.instrumentation.docs.internal.InstrumentationModule;
1413
import io.opentelemetry.instrumentation.docs.internal.InstrumentationType;
15-
import io.opentelemetry.instrumentation.docs.parsers.MetricParser;
14+
import io.opentelemetry.instrumentation.docs.parsers.EmittedMetricsParser;
15+
import io.opentelemetry.instrumentation.docs.parsers.GradleParser;
16+
import io.opentelemetry.instrumentation.docs.parsers.ModuleParser;
17+
import io.opentelemetry.instrumentation.docs.parsers.SpanParser;
1618
import io.opentelemetry.instrumentation.docs.utils.FileManager;
1719
import io.opentelemetry.instrumentation.docs.utils.InstrumentationPath;
1820
import io.opentelemetry.instrumentation.docs.utils.YamlHelper;
1921
import java.io.IOException;
20-
import java.util.ArrayList;
2122
import java.util.HashMap;
22-
import java.util.HashSet;
2323
import java.util.List;
2424
import java.util.Map;
2525
import java.util.Set;
2626
import java.util.logging.Logger;
27+
import javax.annotation.Nullable;
2728

29+
/**
30+
* Analyzes instrumentation modules by extracting version information, metrics, spans, and metadata
31+
* from various source files.
32+
*/
2833
class InstrumentationAnalyzer {
2934

3035
private static final Logger logger = Logger.getLogger(InstrumentationAnalyzer.class.getName());
@@ -36,100 +41,74 @@ class InstrumentationAnalyzer {
3641
}
3742

3843
/**
39-
* Converts a list of {@link InstrumentationPath} into a list of {@link InstrumentationModule},
44+
* Analyzes all instrumentation modules found in the root directory.
4045
*
41-
* @param paths the list of {@link InstrumentationPath} objects to be converted
42-
* @return a list of {@link InstrumentationModule} objects with aggregated types
46+
* @return a list of analyzed {@link InstrumentationModule}
47+
* @throws IOException if file operations fail
4348
*/
44-
public static List<InstrumentationModule> convertToInstrumentationModules(
45-
String rootPath, List<InstrumentationPath> paths) {
46-
Map<String, InstrumentationModule> moduleMap = new HashMap<>();
47-
48-
for (InstrumentationPath path : paths) {
49-
String key = path.group() + ":" + path.namespace() + ":" + path.instrumentationName();
50-
if (!moduleMap.containsKey(key)) {
51-
moduleMap.put(
52-
key,
53-
new InstrumentationModule.Builder()
54-
.srcPath(sanitizePathName(rootPath, path.srcPath()))
55-
.instrumentationName(path.instrumentationName())
56-
.namespace(path.namespace())
57-
.group(path.group())
58-
.build());
59-
}
49+
public List<InstrumentationModule> analyze() throws IOException {
50+
List<InstrumentationPath> paths = fileManager.getInstrumentationPaths();
51+
List<InstrumentationModule> modules =
52+
ModuleParser.convertToModules(fileManager.rootDir(), paths);
53+
54+
for (InstrumentationModule module : modules) {
55+
enrichModule(module);
6056
}
6157

62-
return new ArrayList<>(moduleMap.values());
58+
return modules;
6359
}
6460

65-
private static String sanitizePathName(String rootPath, String path) {
66-
return path.replace(rootPath, "").replace("/javaagent", "").replace("/library", "");
61+
private void enrichModule(InstrumentationModule module) throws IOException {
62+
InstrumentationMetaData metaData = getMetadata(module);
63+
if (metaData != null) {
64+
module.setMetadata(metaData);
65+
}
66+
67+
module.setTargetVersions(getVersionInformation(module));
68+
module.setMetrics(MetricsProcessor.getMetrics(module, fileManager));
69+
module.setSpans(SpanParser.getSpans(module, fileManager));
6770
}
6871

69-
/**
70-
* Traverses the given root directory to find all instrumentation paths and then analyzes them.
71-
* Extracts version information from each instrumentation's build.gradle file, metric data from
72-
* files in the .telemetry directories, and other information from metadata.yaml files.
73-
*
74-
* @return a list of {@link InstrumentationModule}
75-
*/
76-
List<InstrumentationModule> analyze() throws IOException {
77-
List<InstrumentationPath> paths = fileManager.getInstrumentationPaths();
78-
List<InstrumentationModule> modules =
79-
convertToInstrumentationModules(fileManager.rootDir(), paths);
72+
@Nullable
73+
private InstrumentationMetaData getMetadata(InstrumentationModule module)
74+
throws JsonProcessingException {
75+
String metadataFile = fileManager.getMetaDataFile(module.getSrcPath());
76+
if (metadataFile == null) {
77+
return null;
78+
}
79+
try {
80+
return YamlHelper.metaDataParser(metadataFile);
81+
} catch (ValueInstantiationException e) {
82+
logger.severe("Error parsing metadata file for " + module.getInstrumentationName());
83+
throw e;
84+
}
85+
}
8086

81-
for (InstrumentationModule module : modules) {
82-
List<String> gradleFiles = fileManager.findBuildGradleFiles(module.getSrcPath());
83-
analyzeVersions(gradleFiles, module);
84-
85-
String metadataFile = fileManager.getMetaDataFile(module.getSrcPath());
86-
if (metadataFile != null) {
87-
try {
88-
module.setMetadata(YamlHelper.metaDataParser(metadataFile));
89-
} catch (ValueInstantiationException e) {
90-
logger.severe("Error parsing metadata file for " + module.getInstrumentationName());
91-
throw e;
92-
}
93-
}
87+
private Map<InstrumentationType, Set<String>> getVersionInformation(
88+
InstrumentationModule module) {
89+
List<String> gradleFiles = fileManager.findBuildGradleFiles(module.getSrcPath());
90+
return GradleParser.extractVersions(gradleFiles, module);
91+
}
92+
93+
/** Handles processing of metrics data for instrumentation modules. */
94+
static class MetricsProcessor {
9495

96+
public static Map<String, List<EmittedMetrics.Metric>> getMetrics(
97+
InstrumentationModule module, FileManager fileManager) {
9598
Map<String, EmittedMetrics> metrics =
96-
MetricParser.getMetricsFromFiles(fileManager.rootDir(), module.getSrcPath());
97-
98-
for (Map.Entry<String, EmittedMetrics> entry : metrics.entrySet()) {
99-
if (entry.getValue() == null || entry.getValue().getMetrics() == null) {
100-
continue;
101-
}
102-
module.getMetrics().put(entry.getKey(), entry.getValue().getMetrics());
103-
}
99+
EmittedMetricsParser.getMetricsFromFiles(fileManager.rootDir(), module.getSrcPath());
100+
101+
Map<String, List<EmittedMetrics.Metric>> result = new HashMap<>();
102+
metrics.entrySet().stream()
103+
.filter(MetricsProcessor::hasValidMetrics)
104+
.forEach(entry -> result.put(entry.getKey(), entry.getValue().getMetrics()));
105+
return result;
104106
}
105-
return modules;
106-
}
107107

108-
void analyzeVersions(List<String> files, InstrumentationModule module) {
109-
Map<InstrumentationType, Set<String>> versions = new HashMap<>();
110-
for (String file : files) {
111-
String fileContents = FileManager.readFileToString(file);
112-
if (fileContents == null) {
113-
continue;
114-
}
115-
116-
DependencyInfo results = null;
117-
118-
if (file.contains("/javaagent/")) {
119-
results = parseGradleFile(fileContents, InstrumentationType.JAVAAGENT);
120-
versions
121-
.computeIfAbsent(InstrumentationType.JAVAAGENT, k -> new HashSet<>())
122-
.addAll(results.versions());
123-
} else if (file.contains("/library/")) {
124-
results = parseGradleFile(fileContents, InstrumentationType.LIBRARY);
125-
versions
126-
.computeIfAbsent(InstrumentationType.LIBRARY, k -> new HashSet<>())
127-
.addAll(results.versions());
128-
}
129-
if (results != null && results.minJavaVersionSupported() != null) {
130-
module.setMinJavaVersion(results.minJavaVersionSupported());
131-
}
108+
private static boolean hasValidMetrics(Map.Entry<String, EmittedMetrics> entry) {
109+
return entry.getValue() != null && entry.getValue().getMetrics() != null;
132110
}
133-
module.setTargetVersions(versions);
111+
112+
private MetricsProcessor() {}
134113
}
135114
}

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

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,14 @@ public static class Metric {
5353
private String description;
5454
private String type;
5555
private String unit;
56-
private List<Attribute> attributes;
56+
private List<TelemetryAttribute> attributes;
5757

5858
public Metric(
59-
String name, String description, String type, String unit, List<Attribute> attributes) {
59+
String name,
60+
String description,
61+
String type,
62+
String unit,
63+
List<TelemetryAttribute> attributes) {
6064
this.name = name;
6165
this.description = description;
6266
this.type = type;
@@ -104,47 +108,12 @@ public void setUnit(String unit) {
104108
this.unit = unit;
105109
}
106110

107-
public List<Attribute> getAttributes() {
111+
public List<TelemetryAttribute> getAttributes() {
108112
return attributes;
109113
}
110114

111-
public void setAttributes(List<Attribute> attributes) {
115+
public void setAttributes(List<TelemetryAttribute> attributes) {
112116
this.attributes = attributes;
113117
}
114118
}
115-
116-
/**
117-
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
118-
* any time.
119-
*/
120-
public static class Attribute {
121-
private String name;
122-
private String type;
123-
124-
public Attribute() {
125-
this.name = "";
126-
this.type = "";
127-
}
128-
129-
public Attribute(String name, String type) {
130-
this.name = name;
131-
this.type = type;
132-
}
133-
134-
public String getName() {
135-
return name;
136-
}
137-
138-
public void setName(String name) {
139-
this.name = name;
140-
}
141-
142-
public String getType() {
143-
return type;
144-
}
145-
146-
public void setType(String type) {
147-
this.type = type;
148-
}
149-
}
150119
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.docs.internal;
7+
8+
import static java.util.Collections.emptyList;
9+
10+
import com.fasterxml.jackson.annotation.JsonProperty;
11+
import java.util.ArrayList;
12+
import java.util.List;
13+
14+
/**
15+
* Representation of spans emitted by an instrumentation. Includes context about whether emitted by
16+
* default or via a configuration option. This class is internal and is hence not for public use.
17+
* Its APIs are unstable and can change at any time.
18+
*/
19+
public class EmittedSpans {
20+
// Condition in which the telemetry is emitted (ex: default, or configuration option names).
21+
private String when;
22+
23+
@JsonProperty("spans_by_scope")
24+
private List<SpansByScope> spansByScope;
25+
26+
public EmittedSpans() {
27+
this.when = "";
28+
this.spansByScope = emptyList();
29+
}
30+
31+
public EmittedSpans(String when, List<SpansByScope> spansByScope) {
32+
this.when = when;
33+
this.spansByScope = spansByScope;
34+
}
35+
36+
public String getWhen() {
37+
return when;
38+
}
39+
40+
public void setWhen(String when) {
41+
this.when = when;
42+
}
43+
44+
@JsonProperty("spans_by_scope")
45+
public List<SpansByScope> getSpansByScope() {
46+
return spansByScope;
47+
}
48+
49+
@JsonProperty("spans_by_scope")
50+
public void setSpansByScope(List<SpansByScope> spans) {
51+
this.spansByScope = spans;
52+
}
53+
54+
/**
55+
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
56+
* any time.
57+
*/
58+
public static class SpansByScope {
59+
private String scope;
60+
private List<Span> spans;
61+
62+
public SpansByScope(String scopeName, List<Span> spans) {
63+
this.scope = scopeName;
64+
this.spans = spans;
65+
}
66+
67+
public SpansByScope() {
68+
this.scope = "";
69+
this.spans = emptyList();
70+
}
71+
72+
public String getScope() {
73+
return scope;
74+
}
75+
76+
public void setScope(String scope) {
77+
this.scope = scope;
78+
}
79+
80+
public List<Span> getSpans() {
81+
return spans;
82+
}
83+
84+
public void setSpans(List<Span> spans) {
85+
this.spans = spans;
86+
}
87+
}
88+
89+
/**
90+
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
91+
* any time.
92+
*/
93+
public static class Span {
94+
@JsonProperty("span_kind")
95+
private String spanKind;
96+
97+
private List<TelemetryAttribute> attributes;
98+
99+
public Span(String spanKind, List<TelemetryAttribute> attributes) {
100+
this.spanKind = spanKind;
101+
this.attributes = attributes;
102+
}
103+
104+
public Span() {
105+
this.spanKind = "";
106+
this.attributes = new ArrayList<>();
107+
}
108+
109+
@JsonProperty("span_kind")
110+
public String getSpanKind() {
111+
return spanKind;
112+
}
113+
114+
@JsonProperty("span_kind")
115+
public void setSpanKind(String spanKind) {
116+
this.spanKind = spanKind;
117+
}
118+
119+
public List<TelemetryAttribute> getAttributes() {
120+
return attributes;
121+
}
122+
123+
public void setAttributes(List<TelemetryAttribute> attributes) {
124+
this.attributes = attributes;
125+
}
126+
}
127+
}

0 commit comments

Comments
 (0)