Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,419 changes: 762 additions & 657 deletions docs/instrumentation-list.yaml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions instrumentation-docs/collect.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ readonly INSTRUMENTATIONS=(
"apache-dbcp-2.0:javaagent:test"
"apache-dbcp-2.0:javaagent:testStableSemconv"
"apache-httpclient:apache-httpclient-5.0:javaagent:test"
"apache-dubbo-2.7:javaagent:testDubbo"
"c3p0-0.9:javaagent:test"
"c3p0-0.9:javaagent:testStableSemconv"
"clickhouse-client-0.5:javaagent:test"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,31 @@

package io.opentelemetry.instrumentation.docs;

import static io.opentelemetry.instrumentation.docs.parsers.GradleParser.parseGradleFile;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.exc.ValueInstantiationException;
import io.opentelemetry.instrumentation.docs.internal.DependencyInfo;
import io.opentelemetry.instrumentation.docs.internal.EmittedMetrics;
import io.opentelemetry.instrumentation.docs.internal.InstrumentationMetaData;
import io.opentelemetry.instrumentation.docs.internal.InstrumentationModule;
import io.opentelemetry.instrumentation.docs.internal.InstrumentationType;
import io.opentelemetry.instrumentation.docs.parsers.MetricParser;
import io.opentelemetry.instrumentation.docs.parsers.EmittedMetricsParser;
import io.opentelemetry.instrumentation.docs.parsers.GradleParser;
import io.opentelemetry.instrumentation.docs.parsers.ModuleParser;
import io.opentelemetry.instrumentation.docs.parsers.SpanParser;
import io.opentelemetry.instrumentation.docs.utils.FileManager;
import io.opentelemetry.instrumentation.docs.utils.InstrumentationPath;
import io.opentelemetry.instrumentation.docs.utils.YamlHelper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import javax.annotation.Nullable;

/**
* Analyzes instrumentation modules by extracting version information, metrics, spans, and metadata
* from various source files.
*/
class InstrumentationAnalyzer {

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

/**
* Converts a list of {@link InstrumentationPath} into a list of {@link InstrumentationModule},
* Analyzes all instrumentation modules found in the root directory.
*
* @param paths the list of {@link InstrumentationPath} objects to be converted
* @return a list of {@link InstrumentationModule} objects with aggregated types
* @return a list of analyzed {@link InstrumentationModule}
* @throws IOException if file operations fail
*/
public static List<InstrumentationModule> convertToInstrumentationModules(
String rootPath, List<InstrumentationPath> paths) {
Map<String, InstrumentationModule> moduleMap = new HashMap<>();

for (InstrumentationPath path : paths) {
String key = path.group() + ":" + path.namespace() + ":" + path.instrumentationName();
if (!moduleMap.containsKey(key)) {
moduleMap.put(
key,
new InstrumentationModule.Builder()
.srcPath(sanitizePathName(rootPath, path.srcPath()))
.instrumentationName(path.instrumentationName())
.namespace(path.namespace())
.group(path.group())
.build());
}
public List<InstrumentationModule> analyze() throws IOException {
List<InstrumentationPath> paths = fileManager.getInstrumentationPaths();
List<InstrumentationModule> modules =
ModuleParser.convertToModules(fileManager.rootDir(), paths);

for (InstrumentationModule module : modules) {
enrichModule(module);
}

return new ArrayList<>(moduleMap.values());
return modules;
}

private static String sanitizePathName(String rootPath, String path) {
return path.replace(rootPath, "").replace("/javaagent", "").replace("/library", "");
private void enrichModule(InstrumentationModule module) throws IOException {
InstrumentationMetaData metaData = getMetadata(module);
if (metaData != null) {
module.setMetadata(metaData);
}

module.setTargetVersions(getVersionInformation(module));
module.setMetrics(MetricsProcessor.getMetrics(module, fileManager));
module.setSpans(SpanParser.getSpans(module, fileManager));
}

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

for (InstrumentationModule module : modules) {
List<String> gradleFiles = fileManager.findBuildGradleFiles(module.getSrcPath());
analyzeVersions(gradleFiles, module);

String metadataFile = fileManager.getMetaDataFile(module.getSrcPath());
if (metadataFile != null) {
try {
module.setMetadata(YamlHelper.metaDataParser(metadataFile));
} catch (ValueInstantiationException e) {
logger.severe("Error parsing metadata file for " + module.getInstrumentationName());
throw e;
}
}
private Map<InstrumentationType, Set<String>> getVersionInformation(
InstrumentationModule module) {
List<String> gradleFiles = fileManager.findBuildGradleFiles(module.getSrcPath());
return GradleParser.extractVersions(gradleFiles, module);
}

/** Handles processing of metrics data for instrumentation modules. */
static class MetricsProcessor {

public static Map<String, List<EmittedMetrics.Metric>> getMetrics(
InstrumentationModule module, FileManager fileManager) {
Map<String, EmittedMetrics> metrics =
MetricParser.getMetricsFromFiles(fileManager.rootDir(), module.getSrcPath());

for (Map.Entry<String, EmittedMetrics> entry : metrics.entrySet()) {
if (entry.getValue() == null || entry.getValue().getMetrics() == null) {
continue;
}
module.getMetrics().put(entry.getKey(), entry.getValue().getMetrics());
}
EmittedMetricsParser.getMetricsFromFiles(fileManager.rootDir(), module.getSrcPath());

Map<String, List<EmittedMetrics.Metric>> result = new HashMap<>();
metrics.entrySet().stream()
.filter(MetricsProcessor::hasValidMetrics)
.forEach(entry -> result.put(entry.getKey(), entry.getValue().getMetrics()));
return result;
}
return modules;
}

void analyzeVersions(List<String> files, InstrumentationModule module) {
Map<InstrumentationType, Set<String>> versions = new HashMap<>();
for (String file : files) {
String fileContents = FileManager.readFileToString(file);
if (fileContents == null) {
continue;
}

DependencyInfo results = null;

if (file.contains("/javaagent/")) {
results = parseGradleFile(fileContents, InstrumentationType.JAVAAGENT);
versions
.computeIfAbsent(InstrumentationType.JAVAAGENT, k -> new HashSet<>())
.addAll(results.versions());
} else if (file.contains("/library/")) {
results = parseGradleFile(fileContents, InstrumentationType.LIBRARY);
versions
.computeIfAbsent(InstrumentationType.LIBRARY, k -> new HashSet<>())
.addAll(results.versions());
}
if (results != null && results.minJavaVersionSupported() != null) {
module.setMinJavaVersion(results.minJavaVersionSupported());
}
private static boolean hasValidMetrics(Map.Entry<String, EmittedMetrics> entry) {
return entry.getValue() != null && entry.getValue().getMetrics() != null;
}
module.setTargetVersions(versions);

private MetricsProcessor() {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,14 @@ public static class Metric {
private String description;
private String type;
private String unit;
private List<Attribute> attributes;
private List<TelemetryAttribute> attributes;

public Metric(
String name, String description, String type, String unit, List<Attribute> attributes) {
String name,
String description,
String type,
String unit,
List<TelemetryAttribute> attributes) {
this.name = name;
this.description = description;
this.type = type;
Expand Down Expand Up @@ -104,47 +108,12 @@ public void setUnit(String unit) {
this.unit = unit;
}

public List<Attribute> getAttributes() {
public List<TelemetryAttribute> getAttributes() {
return attributes;
}

public void setAttributes(List<Attribute> attributes) {
public void setAttributes(List<TelemetryAttribute> attributes) {
this.attributes = attributes;
}
}

/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public static class Attribute {
private String name;
private String type;

public Attribute() {
this.name = "";
this.type = "";
}

public Attribute(String name, String type) {
this.name = name;
this.type = type;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.docs.internal;

import static java.util.Collections.emptyList;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.List;

/**
* Representation of spans emitted by an instrumentation. Includes context about whether emitted by
* default or via a configuration option. This class is internal and is hence not for public use.
* Its APIs are unstable and can change at any time.
*/
public class EmittedSpans {
// Condition in which the telemetry is emitted (ex: default, or configuration option names).
private String when;

@JsonProperty("spans_by_scope")
private List<SpansByScope> spansByScope;

public EmittedSpans() {
this.when = "";
this.spansByScope = emptyList();
}

public EmittedSpans(String when, List<SpansByScope> spansByScope) {
this.when = when;
this.spansByScope = spansByScope;
}

public String getWhen() {
return when;
}

public void setWhen(String when) {
this.when = when;
}

@JsonProperty("spans_by_scope")
public List<SpansByScope> getSpansByScope() {
return spansByScope;
}

@JsonProperty("spans_by_scope")
public void setSpansByScope(List<SpansByScope> spans) {
this.spansByScope = spans;
}

/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public static class SpansByScope {
private String scope;
private List<Span> spans;

public SpansByScope(String scopeName, List<Span> spans) {
this.scope = scopeName;
this.spans = spans;
}

public SpansByScope() {
this.scope = "";
this.spans = emptyList();
}

public String getScope() {
return scope;
}

public void setScope(String scope) {
this.scope = scope;
}

public List<Span> getSpans() {
return spans;
}

public void setSpans(List<Span> spans) {
this.spans = spans;
}
}

/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public static class Span {
@JsonProperty("span_kind")
private String spanKind;

private List<TelemetryAttribute> attributes;

public Span(String spanKind, List<TelemetryAttribute> attributes) {
this.spanKind = spanKind;
this.attributes = attributes;
}

public Span() {
this.spanKind = "";
this.attributes = new ArrayList<>();
}

@JsonProperty("span_kind")
public String getSpanKind() {
return spanKind;
}

@JsonProperty("span_kind")
public void setSpanKind(String spanKind) {
this.spanKind = spanKind;
}

public List<TelemetryAttribute> getAttributes() {
return attributes;
}

public void setAttributes(List<TelemetryAttribute> attributes) {
this.attributes = attributes;
}
}
}
Loading
Loading