diff --git a/docs/instrumentation-list.yaml b/docs/instrumentation-list.yaml index 09b1a3a835fe..0c5cfbf87702 100644 --- a/docs/instrumentation-list.yaml +++ b/docs/instrumentation-list.yaml @@ -62,6 +62,8 @@ libraries: description: This instrumentation provides context propagation for Akka actors, it does not emit any telemetry on its own. source_path: instrumentation/akka/akka-actor-2.3 + classification: + - propagator scope: name: io.opentelemetry.akka-actor-2.3 target_versions: @@ -73,6 +75,8 @@ libraries: description: This instrumentation provides context propagation for the Akka Fork-Join Pool, it does not emit any telemetry on its own. source_path: instrumentation/akka/akka-actor-fork-join-2.5 + classification: + - propagator scope: name: io.opentelemetry.akka-actor-fork-join-2.5 target_versions: @@ -668,6 +672,8 @@ libraries: description: | This instrumentation does not emit telemetry on its own. Instead, it augments existing SERVER spans and HTTP server metrics with the HTTP route and Shenyu specific attributes. source_path: instrumentation/apache-shenyu-2.4 + classification: + - enricher scope: name: io.opentelemetry.apache-shenyu-2.4 target_versions: @@ -913,6 +919,8 @@ libraries: description: | This instrumentation does not emit telemetry on its own. Instead, it hooks into the Avaje Jex Context to extract the HTTP route and attach it to existing SERVER spans and HTTP server metrics. source_path: instrumentation/avaje-jex-3.0 + classification: + - enricher minimum_java_version: 21 scope: name: io.opentelemetry.avaje-jex-3.0 @@ -1580,6 +1588,8 @@ libraries: description: This instrumentation enables context propagation for the Azure Core library, it does not emit any telemetry on its own. source_path: instrumentation/azure-core/azure-core-1.14 + classification: + - propagator scope: name: io.opentelemetry.azure-core-1.14 target_versions: @@ -1589,6 +1599,8 @@ libraries: description: This instrumentation enables context propagation for the Azure Core library, it does not emit any telemetry on its own. source_path: instrumentation/azure-core/azure-core-1.19 + classification: + - propagator scope: name: io.opentelemetry.azure-core-1.19 target_versions: @@ -1598,6 +1610,8 @@ libraries: description: This instrumentation enables context propagation for the Azure Core library, it does not emit any telemetry on its own. source_path: instrumentation/azure-core/azure-core-1.36 + classification: + - propagator scope: name: io.opentelemetry.azure-core-1.36 target_versions: @@ -2225,6 +2239,8 @@ libraries: description: | Couchbase instrumentation is owned by the Couchbase project for versions 3+. This instrumentation automatically configures the instrumentation provided by the Couchbase library. source_path: instrumentation/couchbase/couchbase-3.1 + classification: + - configuration scope: name: io.opentelemetry.couchbase-3.1 target_versions: @@ -2234,6 +2250,8 @@ libraries: description: | Couchbase instrumentation is owned by the Couchbase project for versions 3+. This instrumentation automatically configures the instrumentation provided by the Couchbase library. source_path: instrumentation/couchbase/couchbase-3.1.6 + classification: + - configuration scope: name: io.opentelemetry.couchbase-3.1.6 target_versions: @@ -2243,6 +2261,8 @@ libraries: description: | Couchbase instrumentation is owned by the Couchbase project for versions 3+. This instrumentation automatically configures the instrumentation provided by the Couchbase library. source_path: instrumentation/couchbase/couchbase-3.2 + classification: + - configuration scope: name: io.opentelemetry.couchbase-3.2 target_versions: @@ -2825,6 +2845,8 @@ libraries: description: | The executor instrumentation ensures that context is automatically propagated when using common Java executors (e.g., ThreadPoolExecutor, ScheduledThreadPoolExecutor, ForkJoinPool). When a task is submitted, the current context is captured and bound to the task. Then, when the task eventually runs, even if it’s on a different thread, the instrumentation reactivates that context, enabling consistent correlation across concurrent and asynchronous workflows. source_path: instrumentation/executors + classification: + - propagator scope: name: io.opentelemetry.executors target_versions: @@ -5228,6 +5250,8 @@ libraries: description: | This instrumentation does not emit telemetry on its own. Instead, it extracts the HTTP route and attaches it to SERVER spans and HTTP server metrics. source_path: instrumentation/spark-2.3 + classification: + - enricher scope: name: io.opentelemetry.spark-2.3 target_versions: @@ -5656,6 +5680,8 @@ libraries: This instrumentation does not emit any telemetry on its own. Instead, it captures enduser attributes, and is only enabled when at least one of the `enduser` configurations is enabled. NOTE: The `enduser` attributes have been deprecated and will be removed in 3.0+ of the java agent. source_path: instrumentation/spring/spring-security-config-6.0 + classification: + - enricher minimum_java_version: 17 scope: name: io.opentelemetry.spring-security-config-6.0 diff --git a/instrumentation-docs/readme.md b/instrumentation-docs/readme.md index 0bb6ba9dfe52..3dc6955c8af2 100644 --- a/instrumentation-docs/readme.md +++ b/instrumentation-docs/readme.md @@ -108,9 +108,12 @@ public class SpringWebInstrumentationModule extends InstrumentationModule ## Instrumentation metadata * classification - * `library` - Instrumentation that targets a library - * `internal` - Instrumentation that is used internally by the OpenTelemetry Java Agent - * `custom` - Utilities that are used to create custom instrumentation + * `library` - Instrumentation that targets a library. + * `internal` - Instrumentation that is used internally by the OpenTelemetry Java Agent. + * `custom` - Utilities that are used by end users to create custom instrumentation. + * `enricher` - Instrumentation that enriches the telemetry produced by other instrumentations but does not generate or emit telemetry on its own. + * `propagator` - Instrumentation that acts as a bridge for context propagation but does not generate or emit telemetry on its own. + * `configuration` - Instrumentation that configures or sets up native library instrumentation. * name * Identifier for instrumentation module, used to enable/disable * Configured in `InstrumentationModule` code for each module @@ -147,7 +150,9 @@ As of now, the following fields are supported, all of which are optional: ```yaml description: "Instruments..." # Description of the instrumentation module disabled_by_default: true # Defaults to `false` -classification: internal # instrumentation classification: library | internal | custom +classification: + - library + - enricher configurations: - name: otel.instrumentation.common.db-statement-sanitizer.enabled description: Enables statement sanitization for database queries. diff --git a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/DocGeneratorApplication.java b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/DocGeneratorApplication.java index db51b6ce0e99..da488bbdc564 100644 --- a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/DocGeneratorApplication.java +++ b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/DocGeneratorApplication.java @@ -86,16 +86,14 @@ private static void printStats(List modules) { } private static String getClassificationStats(List modules) { + // Flatten all classifications and count each individually return modules.stream() - .collect( - Collectors.groupingBy( - m -> m.getMetadata().getClassification(), TreeMap::new, Collectors.toList())) + .flatMap(m -> m.getMetadata().getClassifications().stream()) + .map(c -> c.name().toLowerCase(Locale.ROOT)) + .collect(Collectors.groupingBy(c -> c, TreeMap::new, Collectors.counting())) .entrySet() .stream() - .map( - entry -> - String.format( - Locale.getDefault(FORMAT), "\t%s: %d", entry.getKey(), entry.getValue().size())) + .map(entry -> String.format(Locale.ROOT, "\t%s: %d", entry.getKey(), entry.getValue())) .collect(Collectors.joining("\n")); } diff --git a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/InstrumentationAnalyzer.java b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/InstrumentationAnalyzer.java index ad393200fd6b..b73b9e5ed8de 100644 --- a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/InstrumentationAnalyzer.java +++ b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/InstrumentationAnalyzer.java @@ -8,7 +8,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.exc.ValueInstantiationException; -import io.opentelemetry.instrumentation.docs.internal.InstrumentationMetaData; +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.GradleParser; @@ -58,9 +58,9 @@ public List analyze() throws IOException { } private void enrichModule(InstrumentationModule module) throws IOException { - InstrumentationMetaData metaData = getMetadata(module); - if (metaData != null) { - module.setMetadata(metaData); + InstrumentationMetadata metadata = getMetadata(module); + if (metadata != null) { + module.setMetadata(metadata); } module.setTargetVersions(getVersionInformation(module)); @@ -69,14 +69,14 @@ private void enrichModule(InstrumentationModule module) throws IOException { } @Nullable - private InstrumentationMetaData getMetadata(InstrumentationModule module) + private InstrumentationMetadata getMetadata(InstrumentationModule module) throws JsonProcessingException { - String metadataFile = fileManager.getMetaDataFile(module.getSrcPath()); + String metadataFile = fileManager.getMetadataFile(module.getSrcPath()); if (metadataFile == null) { return null; } try { - return YamlHelper.metaDataParser(metadataFile); + return YamlHelper.metadataParser(metadataFile); } catch (ValueInstantiationException | MismatchedInputException e) { logger.severe("Error parsing metadata file for " + module.getInstrumentationName()); throw e; diff --git a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationClassification.java b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationClassification.java index 23d26e65ae38..f5ed2ca9de3e 100644 --- a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationClassification.java +++ b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationClassification.java @@ -15,7 +15,10 @@ public enum InstrumentationClassification { LIBRARY, CUSTOM, - INTERNAL; + INTERNAL, + ENRICHER, + CONFIGURATION, + PROPAGATOR; @Nullable public static InstrumentationClassification fromString(@Nullable String type) { @@ -26,6 +29,9 @@ public static InstrumentationClassification fromString(@Nullable String type) { case "library" -> LIBRARY; case "internal" -> INTERNAL; case "custom" -> CUSTOM; + case "enricher" -> ENRICHER; + case "configuration" -> CONFIGURATION; + case "propagator" -> PROPAGATOR; default -> null; }; } diff --git a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationMetaData.java b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationMetadata.java similarity index 50% rename from instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationMetaData.java rename to instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationMetadata.java index d43a8bd2c748..450a20888499 100644 --- a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationMetaData.java +++ b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationMetadata.java @@ -5,41 +5,44 @@ package io.opentelemetry.instrumentation.docs.internal; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; + import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Collections; import java.util.List; import java.util.Objects; -import javax.annotation.Nonnull; import javax.annotation.Nullable; /** * Represents the data in a metadata.yaml file. This class is internal and is hence not for public * use. Its APIs are unstable and can change at any time. */ -public class InstrumentationMetaData { +public class InstrumentationMetadata { @Nullable private String description; @JsonProperty("disabled_by_default") @Nullable private Boolean disabledByDefault; - private String classification; + private List classifications; - private List configurations = Collections.emptyList(); + private List configurations = emptyList(); - public InstrumentationMetaData() { - this.classification = InstrumentationClassification.LIBRARY.toString(); + public InstrumentationMetadata() { + this.classifications = singletonList(InstrumentationClassification.LIBRARY.name()); } - public InstrumentationMetaData( + public InstrumentationMetadata( @Nullable String description, - String classification, + List classifications, @Nullable Boolean disabledByDefault, @Nullable List configurations) { - this.classification = classification; + this.classifications = + Objects.requireNonNullElse( + classifications, singletonList(InstrumentationClassification.LIBRARY.name())); this.disabledByDefault = disabledByDefault; this.description = description; - this.configurations = Objects.requireNonNullElse(configurations, Collections.emptyList()); + this.configurations = Objects.requireNonNullElse(configurations, emptyList()); } @Nullable @@ -47,11 +50,21 @@ public String getDescription() { return description; } - @Nonnull - public InstrumentationClassification getClassification() { - return Objects.requireNonNullElse( - InstrumentationClassification.fromString(classification), - InstrumentationClassification.LIBRARY); + public List getClassifications() { + if (classifications == null || classifications.isEmpty()) { + return singletonList(InstrumentationClassification.LIBRARY); + } + return classifications.stream() + .map( + classification -> { + InstrumentationClassification result = + InstrumentationClassification.fromString(classification); + if (result == null) { + throw new IllegalArgumentException("Invalid classification: " + classification); + } + return result; + }) + .toList(); } public Boolean getDisabledByDefault() { @@ -62,8 +75,11 @@ public void setDescription(@Nullable String description) { this.description = description; } - public void setClassification(String classification) { - this.classification = classification; + public void setClassifications(@Nullable List classifications) { + this.classifications = + (classifications == null || classifications.isEmpty()) + ? singletonList(InstrumentationClassification.LIBRARY.name()) + : classifications; } public void setDisabledByDefault(@Nullable Boolean disabledByDefault) { @@ -75,6 +91,6 @@ public List getConfigurations() { } public void setConfigurations(@Nullable List configurations) { - this.configurations = Objects.requireNonNullElse(configurations, Collections.emptyList()); + this.configurations = Objects.requireNonNullElse(configurations, emptyList()); } } diff --git a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationMetadataDeserializer.java b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationMetadataDeserializer.java new file mode 100644 index 000000000000..5fd0c4e5e6c2 --- /dev/null +++ b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationMetadataDeserializer.java @@ -0,0 +1,114 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.docs.internal; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +import static java.util.Collections.unmodifiableList; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import javax.annotation.Nullable; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class InstrumentationMetadataDeserializer + extends JsonDeserializer { + + @Override + public InstrumentationMetadata deserialize(JsonParser p, DeserializationContext ctx) + throws IOException { + JsonNode node = p.getCodec().readTree(p); + + String description = textOrNull(node, "description"); + Boolean disabledByDefault = boolOrNull(node, "disabled_by_default"); + + List classifications = readClassifications(node.path("classification")); + List configurations = readConfigurations(node.path("configurations")); + + return new InstrumentationMetadata( + description, classifications, disabledByDefault, configurations); + } + + @Nullable + private static String textOrNull(JsonNode parent, String field) { + JsonNode n = parent.path(field); + return n.isMissingNode() || n.isNull() ? null : n.asText(); + } + + @Nullable + private static Boolean boolOrNull(JsonNode parent, String field) { + JsonNode n = parent.path(field); + return (n.isMissingNode() || n.isNull()) ? null : n.asBoolean(); + } + + private static List readClassifications(JsonNode node) { + if (node.isMissingNode() || node.isNull()) { + return singletonList(InstrumentationClassification.LIBRARY.name()); + } + if (!node.isArray()) { + throw new IllegalArgumentException("Classification must be an array"); + } + List result = new ArrayList<>(); + for (JsonNode c : node) { + if (c.isTextual()) { + result.add(c.asText()); + } + } + if (result.isEmpty()) { + result.add(InstrumentationClassification.LIBRARY.name()); + } + return unmodifiableList(result); + } + + private static List readConfigurations(JsonNode configs) { + if (!configs.isArray() || configs.size() == 0) { + return emptyList(); + } + List configurationOptions = new ArrayList<>(configs.size()); + for (JsonNode cfg : configs) { + if (cfg.isNull() || !cfg.isObject()) { + throw new IllegalArgumentException("Configuration entry must be an object"); + } + + String name = textOrNull(cfg, "name"); + if (name == null) { + throw new IllegalArgumentException("Configuration entry is missing required 'name' field"); + } + + String desc = + Objects.requireNonNull( + textOrNull(cfg, "description"), + "Configuration '" + name + "' is missing required 'description' field"); + String def = + Objects.requireNonNull( + textOrNull(cfg, "default"), + "Configuration '" + name + "' is missing required 'default' field"); + String typeStr = + Objects.requireNonNull( + textOrNull(cfg, "type"), + "Configuration '" + name + "' is missing required 'type' field"); + + ConfigurationType type; + try { + type = ConfigurationType.from(typeStr); + } catch (IllegalArgumentException ex) { + throw new IllegalArgumentException( + "Configuration '" + name + "' has invalid type: '" + typeStr + "'", ex); + } + configurationOptions.add(new ConfigurationOption(name, desc, def, type)); + } + return unmodifiableList(configurationOptions); + } +} diff --git a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationModule.java b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationModule.java index 3910e291b890..1b13cb8eb55e 100644 --- a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationModule.java +++ b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationModule.java @@ -35,7 +35,7 @@ public class InstrumentationModule { @Nullable private Integer minJavaVersion; - @Nullable private InstrumentationMetaData metadata; + @Nullable private InstrumentationMetadata metadata; /** * This class is internal and is hence not for public use. Its APIs are unstable and can change at @@ -79,9 +79,9 @@ public InstrumentationScopeInfo getScopeInfo() { return scopeInfo; } - public InstrumentationMetaData getMetadata() { + public InstrumentationMetadata getMetadata() { if (metadata == null) { - metadata = new InstrumentationMetaData(); + metadata = new InstrumentationMetadata(); } return metadata; @@ -109,7 +109,7 @@ public void setTargetVersions(Map> targetVersio this.targetVersions = targetVersions; } - public void setMetadata(InstrumentationMetaData metadata) { + public void setMetadata(InstrumentationMetadata metadata) { this.metadata = metadata; } @@ -135,7 +135,7 @@ public static class Builder { @Nullable private String namespace; @Nullable private String group; @Nullable private Integer minJavaVersion; - @Nullable private InstrumentationMetaData metadata; + @Nullable private InstrumentationMetadata metadata; @Nullable private Map> targetVersions; @Nullable private Map> metrics; @Nullable private Map> spans; @@ -171,7 +171,7 @@ public Builder group(String group) { } @CanIgnoreReturnValue - public Builder metadata(InstrumentationMetaData metadata) { + public Builder metadata(InstrumentationMetadata metadata) { this.metadata = metadata; return this; } diff --git a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/utils/FileManager.java b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/utils/FileManager.java index f142cded4274..bd70a24190a6 100644 --- a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/utils/FileManager.java +++ b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/utils/FileManager.java @@ -94,7 +94,7 @@ public List findBuildGradleFiles(String instrumentationDirectory) { } @Nullable - public String getMetaDataFile(String instrumentationDirectory) { + public String getMetadataFile(String instrumentationDirectory) { String metadataFile = rootDir + instrumentationDirectory + "/metadata.yaml"; if (Files.exists(Paths.get(metadataFile))) { return readFileToString(metadataFile); diff --git a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/utils/YamlHelper.java b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/utils/YamlHelper.java index 98ed802d6047..56f39ad9e5f3 100644 --- a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/utils/YamlHelper.java +++ b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/utils/YamlHelper.java @@ -7,13 +7,15 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.opentelemetry.instrumentation.docs.internal.ConfigurationOption; import io.opentelemetry.instrumentation.docs.internal.ConfigurationType; import io.opentelemetry.instrumentation.docs.internal.EmittedMetrics; import io.opentelemetry.instrumentation.docs.internal.EmittedSpans; import io.opentelemetry.instrumentation.docs.internal.InstrumentationClassification; -import io.opentelemetry.instrumentation.docs.internal.InstrumentationMetaData; +import io.opentelemetry.instrumentation.docs.internal.InstrumentationMetadata; +import io.opentelemetry.instrumentation.docs.internal.InstrumentationMetadataDeserializer; import io.opentelemetry.instrumentation.docs.internal.InstrumentationModule; import io.opentelemetry.instrumentation.docs.internal.TelemetryAttribute; import java.io.BufferedWriter; @@ -39,7 +41,15 @@ public class YamlHelper { private static final Logger logger = Logger.getLogger(YamlHelper.class.getName()); - private static final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); + private static final ObjectMapper mapper; + + static { + mapper = new ObjectMapper(new YAMLFactory()); + SimpleModule module = new SimpleModule(); + module.addDeserializer( + InstrumentationMetadata.class, new InstrumentationMetadataDeserializer()); + mapper.registerModule(module); + } public static void generateInstrumentationYaml( List list, BufferedWriter writer) { @@ -74,8 +84,8 @@ private static Map getLibraryInstrumentations(List module .getMetadata() - .getClassification() - .equals(InstrumentationClassification.LIBRARY)) + .getClassifications() + .contains(InstrumentationClassification.LIBRARY)) .collect( Collectors.groupingBy( InstrumentationModule::getGroup, @@ -111,7 +121,7 @@ private static Map generateBaseYaml( List list, InstrumentationClassification classification) { List filtered = list.stream() - .filter(module -> module.getMetadata().getClassification().equals(classification)) + .filter(module -> module.getMetadata().getClassifications().contains(classification)) .toList(); List> instrumentations = new ArrayList<>(); @@ -135,6 +145,20 @@ private static Map baseProperties(InstrumentationModule module) addMetadataProperties(module, moduleMap); moduleMap.put("source_path", module.getSrcPath()); + // Filter out standard classifications and add remaining ones if present + List extraClassifications = + module.getMetadata().getClassifications().stream() + .filter( + c -> + !c.equals(InstrumentationClassification.LIBRARY) + && !c.equals(InstrumentationClassification.INTERNAL) + && !c.equals(InstrumentationClassification.CUSTOM)) + .map(InstrumentationClassification::toString) + .toList(); + if (!extraClassifications.isEmpty()) { + moduleMap.put("classification", extraClassifications); + } + if (module.getMinJavaVersion() != null) { moduleMap.put("minimum_java_version", module.getMinJavaVersion()); } @@ -287,9 +311,9 @@ private static Map getSpanMap(EmittedSpans.Span span) { return innerMetricMap; } - public static InstrumentationMetaData metaDataParser(String input) + public static InstrumentationMetadata metadataParser(String input) throws JsonProcessingException { - return mapper.readValue(input, InstrumentationMetaData.class); + return mapper.readValue(input, InstrumentationMetadata.class); } public static EmittedMetrics emittedMetricsParser(String input) throws JsonProcessingException { diff --git a/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationMetadataDeserializerTest.java b/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationMetadataDeserializerTest.java new file mode 100644 index 000000000000..0e2076f90c9e --- /dev/null +++ b/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationMetadataDeserializerTest.java @@ -0,0 +1,319 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.docs.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import java.io.IOException; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class InstrumentationMetadataDeserializerTest { + + private ObjectMapper objectMapper; + + @BeforeEach + void setUp() { + objectMapper = new ObjectMapper(new YAMLFactory()); + SimpleModule module = new SimpleModule(); + module.addDeserializer( + InstrumentationMetadata.class, new InstrumentationMetadataDeserializer()); + objectMapper.registerModule(module); + } + + @Test + void testSuccessfulDeserialization() throws IOException { + String yaml = + """ + description: Test instrumentation for HTTP clients + classification: + - library + - enricher + disabled_by_default: true + configurations: + - name: otel.instrumentation.messaging.experimental.receive-telemetry.enabled + description: > + Enables experimental receive telemetry, which will cause consumers to start a new trace, with + only a span link connecting it to the producer trace. + type: boolean + default: false + - name: otel.instrumentation.messaging.experimental.capture-headers + description: Allows configuring headers to capture as span attributes. + type: list + default: '' + """; + + InstrumentationMetadata metadata = objectMapper.readValue(yaml, InstrumentationMetadata.class); + + assertThat(metadata.getDescription()).isEqualTo("Test instrumentation for HTTP clients"); + assertThat(metadata.getDisabledByDefault()).isTrue(); + assertThat(metadata.getClassifications()) + .containsExactly( + InstrumentationClassification.LIBRARY, InstrumentationClassification.ENRICHER); + + List configurations = metadata.getConfigurations(); + assertThat(configurations).hasSize(2); + + ConfigurationOption firstConfig = configurations.get(0); + assertThat(firstConfig.name()) + .isEqualTo("otel.instrumentation.messaging.experimental.receive-telemetry.enabled"); + assertThat(firstConfig.description()) + .isEqualTo( + "Enables experimental receive telemetry, which will cause consumers to start a new trace, with only a span link connecting it to the producer trace.\n"); + assertThat(firstConfig.type()).isEqualTo(ConfigurationType.BOOLEAN); + assertThat(firstConfig.defaultValue()).isEqualTo("false"); + + ConfigurationOption secondConfig = configurations.get(1); + assertThat(secondConfig.name()) + .isEqualTo("otel.instrumentation.messaging.experimental.capture-headers"); + assertThat(secondConfig.description()) + .isEqualTo("Allows configuring headers to capture as span attributes."); + assertThat(secondConfig.type()).isEqualTo(ConfigurationType.LIST); + assertThat(secondConfig.defaultValue()).isEqualTo(""); + } + + @Test + void testMinimalValidYaml() throws IOException { + String yaml = "description: Simple test"; + + InstrumentationMetadata metadata = objectMapper.readValue(yaml, InstrumentationMetadata.class); + + assertThat(metadata.getDescription()).isEqualTo("Simple test"); + assertThat(metadata.getDisabledByDefault()).isFalse(); + assertThat(metadata.getClassifications()) + .containsExactly(InstrumentationClassification.LIBRARY); + assertThat(metadata.getConfigurations()).isEmpty(); + } + + @Test + void testEmptyYaml() throws IOException { + String yaml = "{}"; + + InstrumentationMetadata metadata = objectMapper.readValue(yaml, InstrumentationMetadata.class); + + assertThat(metadata.getDescription()).isNull(); + assertThat(metadata.getDisabledByDefault()).isFalse(); + assertThat(metadata.getClassifications()) + .containsExactly(InstrumentationClassification.LIBRARY); + assertThat(metadata.getConfigurations()).isEmpty(); + } + + @Test + void testSingleClassificationAsArray() throws IOException { + String yaml = + """ + classification: + - internal + """; + + InstrumentationMetadata metadata = objectMapper.readValue(yaml, InstrumentationMetadata.class); + + assertThat(metadata.getClassifications()) + .containsExactly(InstrumentationClassification.INTERNAL); + } + + @Test + void testClassificationAsArray() throws IOException { + String yaml = + """ + classification: + - custom + - enricher + """; + + InstrumentationMetadata metadata = objectMapper.readValue(yaml, InstrumentationMetadata.class); + + assertThat(metadata.getClassifications()) + .containsExactly( + InstrumentationClassification.CUSTOM, InstrumentationClassification.ENRICHER); + } + + @Test + void testAllConfigurationTypes() throws IOException { + String yaml = + """ + configurations: + - name: boolean.config + description: Boolean configuration + type: boolean + default: true + - name: string.config + description: String configuration + type: string + default: default-value + - name: int.config + description: Integer configuration + type: int + default: 42 + - name: map.config + description: Map configuration + type: map + default: "{}" + - name: list.config + description: List configuration + type: list + default: "[]" + """; + + InstrumentationMetadata metadata = objectMapper.readValue(yaml, InstrumentationMetadata.class); + + List configurations = metadata.getConfigurations(); + assertThat(configurations).hasSize(5); + + assertThat(configurations.get(0).type()).isEqualTo(ConfigurationType.BOOLEAN); + assertThat(configurations.get(1).type()).isEqualTo(ConfigurationType.STRING); + assertThat(configurations.get(2).type()).isEqualTo(ConfigurationType.INT); + assertThat(configurations.get(3).type()).isEqualTo(ConfigurationType.MAP); + assertThat(configurations.get(4).type()).isEqualTo(ConfigurationType.LIST); + } + + @Test + void testEmptyConfigurationsArray() throws IOException { + String yaml = "configurations: []"; + + InstrumentationMetadata metadata = objectMapper.readValue(yaml, InstrumentationMetadata.class); + + assertThat(metadata.getConfigurations()).isEmpty(); + } + + @Test + void testConfigurationMissingName() { + String yaml = + """ + configurations: + - description: Missing name field + type: boolean + default: true + """; + + assertThatThrownBy(() -> objectMapper.readValue(yaml, InstrumentationMetadata.class)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Configuration entry is missing required 'name' field"); + } + + @Test + void testConfigurationMissingDescription() { + String yaml = + """ + configurations: + - name: test.config + type: boolean + default: true + """; + + assertThatThrownBy(() -> objectMapper.readValue(yaml, InstrumentationMetadata.class)) + .isInstanceOf(NullPointerException.class) + .hasMessage("Configuration 'test.config' is missing required 'description' field"); + } + + @Test + void testConfigurationMissingDefault() { + String yaml = + """ + configurations: + - name: test.config + description: Test configuration + type: boolean + """; + + assertThatThrownBy(() -> objectMapper.readValue(yaml, InstrumentationMetadata.class)) + .isInstanceOf(NullPointerException.class) + .hasMessage("Configuration 'test.config' is missing required 'default' field"); + } + + @Test + void testConfigurationMissingType() { + String yaml = + """ + configurations: + - name: test.config + description: Test configuration + default: true + """; + + assertThatThrownBy(() -> objectMapper.readValue(yaml, InstrumentationMetadata.class)) + .isInstanceOf(NullPointerException.class) + .hasMessage("Configuration 'test.config' is missing required 'type' field"); + } + + @Test + void testConfigurationInvalidType() { + String yaml = + """ + configurations: + - name: test.config + description: Test configuration + type: invalid_type + default: true + """; + + assertThatThrownBy(() -> objectMapper.readValue(yaml, InstrumentationMetadata.class)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Configuration 'test.config' has invalid type: 'invalid_type'"); + } + + @Test + void testClassificationAsStringShouldFail() { + String yaml = "classification: internal"; + + assertThatThrownBy(() -> objectMapper.readValue(yaml, InstrumentationMetadata.class)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Classification must be an array"); + } + + @Test + void testInvalidClassification() { + String yaml = + """ + classification: + - invalid_classification + """; + + assertThatThrownBy( + () -> { + InstrumentationMetadata metadata = + objectMapper.readValue(yaml, InstrumentationMetadata.class); + metadata.getClassifications(); // This triggers the validation + }) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Invalid classification: invalid_classification"); + } + + @Test + void testMixedValidAndInvalidClassifications() { + String yaml = + """ + classification: + - library + - invalid_classification + - internal + """; + + assertThatThrownBy( + () -> { + InstrumentationMetadata metadata = + objectMapper.readValue(yaml, InstrumentationMetadata.class); + metadata.getClassifications(); // This triggers the validation + }) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Invalid classification: invalid_classification"); + } + + @Test + void testEmptyClassificationArrayDefaultsToLibrary() throws IOException { + String yaml = "classification: []"; + + InstrumentationMetadata metadata = objectMapper.readValue(yaml, InstrumentationMetadata.class); + + assertThat(metadata.getClassifications()) + .containsExactly(InstrumentationClassification.LIBRARY); + } +} diff --git a/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/utils/YamlHelperTest.java b/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/utils/YamlHelperTest.java index be63541917f9..2e5d3f8ea2b9 100644 --- a/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/utils/YamlHelperTest.java +++ b/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/utils/YamlHelperTest.java @@ -6,6 +6,7 @@ package io.opentelemetry.instrumentation.docs.utils; import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import com.fasterxml.jackson.core.JsonProcessingException; @@ -14,7 +15,7 @@ import io.opentelemetry.instrumentation.docs.internal.EmittedMetrics; import io.opentelemetry.instrumentation.docs.internal.EmittedSpans; import io.opentelemetry.instrumentation.docs.internal.InstrumentationClassification; -import io.opentelemetry.instrumentation.docs.internal.InstrumentationMetaData; +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.internal.TelemetryAttribute; @@ -38,10 +39,12 @@ void testPrintInstrumentationList() throws Exception { InstrumentationType.JAVAAGENT, new HashSet<>(List.of("org.springframework:spring-web:[6.0.0,)"))); - InstrumentationMetaData springMetadata = - new InstrumentationMetaData( + InstrumentationMetadata springMetadata = + new InstrumentationMetadata( "Spring Web 6.0 instrumentation", - InstrumentationClassification.LIBRARY.toString(), + List.of( + InstrumentationClassification.LIBRARY.name(), + InstrumentationClassification.ENRICHER.name()), true, null); @@ -84,6 +87,8 @@ void testPrintInstrumentationList() throws Exception { description: Spring Web 6.0 instrumentation disabled_by_default: true source_path: instrumentation/spring/spring-web/spring-web-6.0 + classification: + - enricher minimum_java_version: 11 scope: name: io.opentelemetry.spring-web-6.0 @@ -109,10 +114,10 @@ void testGenerateInstrumentationYamlSeparatesClassifications() throws Exception Map> springTargetVersions = Map.of(InstrumentationType.JAVAAGENT, Set.of("org.springframework:spring-web:[6.0.0,)")); - InstrumentationMetaData springMetadata = - new InstrumentationMetaData( + InstrumentationMetadata springMetadata = + new InstrumentationMetadata( "Spring Web 6.0 instrumentation", - InstrumentationClassification.LIBRARY.toString(), + singletonList(InstrumentationClassification.LIBRARY.toString()), false, List.of( new ConfigurationOption( @@ -132,9 +137,9 @@ void testGenerateInstrumentationYamlSeparatesClassifications() throws Exception .minJavaVersion(11) .build()); - InstrumentationMetaData internalMetadata = - new InstrumentationMetaData( - null, InstrumentationClassification.INTERNAL.toString(), null, null); + InstrumentationMetadata internalMetadata = + new InstrumentationMetadata( + null, singletonList(InstrumentationClassification.INTERNAL.toString()), null, null); modules.add( new InstrumentationModule.Builder() @@ -146,9 +151,9 @@ void testGenerateInstrumentationYamlSeparatesClassifications() throws Exception .targetVersions(new HashMap<>()) .build()); - InstrumentationMetaData customMetadata = - new InstrumentationMetaData( - null, InstrumentationClassification.CUSTOM.toString(), null, null); + InstrumentationMetadata customMetadata = + new InstrumentationMetadata( + null, singletonList(InstrumentationClassification.CUSTOM.toString()), null, null); Map> externalAnnotationsVersions = Map.of( @@ -212,7 +217,9 @@ void testMetadataParser() throws JsonProcessingException { String input = """ description: test description - classification: internal + classification: + - internal + - custom disabled_by_default: true configurations: - name: otel.instrumentation.common.db-statement-sanitizer.enabled @@ -221,7 +228,7 @@ void testMetadataParser() throws JsonProcessingException { default: true """; - InstrumentationMetaData metadata = YamlHelper.metaDataParser(input); + InstrumentationMetadata metadata = YamlHelper.metadataParser(input); ConfigurationOption config = metadata.getConfigurations().get(0); assertThat(config.name()) @@ -230,16 +237,23 @@ void testMetadataParser() throws JsonProcessingException { .isEqualTo("Enables statement sanitization for database queries."); assertThat(config.defaultValue()).isEqualTo("true"); - assertThat(metadata.getClassification()).isEqualTo(InstrumentationClassification.INTERNAL); + assertThat(metadata.getClassifications()) + .containsExactly( + InstrumentationClassification.INTERNAL, InstrumentationClassification.CUSTOM); assertThat(metadata.getDescription()).isEqualTo("test description"); assertThat(metadata.getDisabledByDefault()).isEqualTo(true); } @Test void testMetadataParserWithOnlyLibraryEntry() throws JsonProcessingException { - String input = "classification: internal"; - InstrumentationMetaData metadata = YamlHelper.metaDataParser(input); - assertThat(metadata.getClassification()).isEqualTo(InstrumentationClassification.INTERNAL); + String input = + """ + classification: + - internal + """; + InstrumentationMetadata metadata = YamlHelper.metadataParser(input); + assertThat(metadata.getClassifications()) + .containsExactly(InstrumentationClassification.INTERNAL); assertThat(metadata.getDescription()).isNull(); assertThat(metadata.getDisabledByDefault()).isFalse(); assertThat(metadata.getConfigurations()).isEmpty(); @@ -248,8 +262,9 @@ void testMetadataParserWithOnlyLibraryEntry() throws JsonProcessingException { @Test void testMetadataParserWithOnlyDescription() throws JsonProcessingException { String input = "description: false"; - InstrumentationMetaData metadata = YamlHelper.metaDataParser(input); - assertThat(metadata.getClassification()).isEqualTo(InstrumentationClassification.LIBRARY); + InstrumentationMetadata metadata = YamlHelper.metadataParser(input); + assertThat(metadata.getClassifications()) + .containsExactly(InstrumentationClassification.LIBRARY); assertThat(metadata.getDisabledByDefault()).isFalse(); assertThat(metadata.getConfigurations()).isEmpty(); } @@ -257,8 +272,9 @@ void testMetadataParserWithOnlyDescription() throws JsonProcessingException { @Test void testMetadataParserWithOnlyDisabledByDefault() throws JsonProcessingException { String input = "disabled_by_default: true"; - InstrumentationMetaData metadata = YamlHelper.metaDataParser(input); - assertThat(metadata.getClassification()).isEqualTo(InstrumentationClassification.LIBRARY); + InstrumentationMetadata metadata = YamlHelper.metadataParser(input); + assertThat(metadata.getClassifications()) + .containsExactly(InstrumentationClassification.LIBRARY); assertThat(metadata.getDescription()).isNull(); assertThat(metadata.getDisabledByDefault()).isTrue(); assertThat(metadata.getConfigurations()).isEmpty(); @@ -274,10 +290,11 @@ void testMetadataParserWithOnlyConfigurations() throws JsonProcessingException { type: boolean default: true """; - InstrumentationMetaData metadata = YamlHelper.metaDataParser(input); + InstrumentationMetadata metadata = YamlHelper.metadataParser(input); ConfigurationOption config = metadata.getConfigurations().get(0); - assertThat(metadata.getClassification()).isEqualTo(InstrumentationClassification.LIBRARY); + assertThat(metadata.getClassifications()) + .containsExactly(InstrumentationClassification.LIBRARY); assertThat(metadata.getDescription()).isNull(); assertThat(metadata.getDisabledByDefault()).isFalse(); diff --git a/instrumentation/akka/akka-actor-2.3/metadata.yaml b/instrumentation/akka/akka-actor-2.3/metadata.yaml index c1a83e29bb5f..8908a9ac933a 100644 --- a/instrumentation/akka/akka-actor-2.3/metadata.yaml +++ b/instrumentation/akka/akka-actor-2.3/metadata.yaml @@ -1 +1,4 @@ description: This instrumentation provides context propagation for Akka actors, it does not emit any telemetry on its own. +classification: + - library + - propagator diff --git a/instrumentation/akka/akka-actor-fork-join-2.5/metadata.yaml b/instrumentation/akka/akka-actor-fork-join-2.5/metadata.yaml index b9bfd2254016..c6292eff2e8b 100644 --- a/instrumentation/akka/akka-actor-fork-join-2.5/metadata.yaml +++ b/instrumentation/akka/akka-actor-fork-join-2.5/metadata.yaml @@ -1 +1,4 @@ description: This instrumentation provides context propagation for the Akka Fork-Join Pool, it does not emit any telemetry on its own. +classification: + - library + - propagator diff --git a/instrumentation/apache-shenyu-2.4/metadata.yaml b/instrumentation/apache-shenyu-2.4/metadata.yaml index 54b38ebaf92c..ff6963acad38 100644 --- a/instrumentation/apache-shenyu-2.4/metadata.yaml +++ b/instrumentation/apache-shenyu-2.4/metadata.yaml @@ -1,6 +1,9 @@ description: > This instrumentation does not emit telemetry on its own. Instead, it augments existing SERVER spans and HTTP server metrics with the HTTP route and Shenyu specific attributes. +classification: + - library + - enricher configurations: - name: otel.instrumentation.apache-shenyu.experimental-span-attributes description: > diff --git a/instrumentation/avaje-jex-3.0/metadata.yaml b/instrumentation/avaje-jex-3.0/metadata.yaml index 7b96ea51bd23..69b8d871bd41 100644 --- a/instrumentation/avaje-jex-3.0/metadata.yaml +++ b/instrumentation/avaje-jex-3.0/metadata.yaml @@ -2,3 +2,6 @@ description: > This instrumentation does not emit telemetry on its own. Instead, it hooks into the Avaje Jex Context to extract the HTTP route and attach it to existing SERVER spans and HTTP server metrics. +classification: + - library + - enricher diff --git a/instrumentation/azure-core/azure-core-1.14/metadata.yaml b/instrumentation/azure-core/azure-core-1.14/metadata.yaml index bee04ae8b1c4..485bb19e4c09 100644 --- a/instrumentation/azure-core/azure-core-1.14/metadata.yaml +++ b/instrumentation/azure-core/azure-core-1.14/metadata.yaml @@ -1 +1,4 @@ description: This instrumentation enables context propagation for the Azure Core library, it does not emit any telemetry on its own. +classification: + - library + - propagator diff --git a/instrumentation/azure-core/azure-core-1.19/metadata.yaml b/instrumentation/azure-core/azure-core-1.19/metadata.yaml index bee04ae8b1c4..485bb19e4c09 100644 --- a/instrumentation/azure-core/azure-core-1.19/metadata.yaml +++ b/instrumentation/azure-core/azure-core-1.19/metadata.yaml @@ -1 +1,4 @@ description: This instrumentation enables context propagation for the Azure Core library, it does not emit any telemetry on its own. +classification: + - library + - propagator diff --git a/instrumentation/azure-core/azure-core-1.36/metadata.yaml b/instrumentation/azure-core/azure-core-1.36/metadata.yaml index bee04ae8b1c4..485bb19e4c09 100644 --- a/instrumentation/azure-core/azure-core-1.36/metadata.yaml +++ b/instrumentation/azure-core/azure-core-1.36/metadata.yaml @@ -1 +1,4 @@ description: This instrumentation enables context propagation for the Azure Core library, it does not emit any telemetry on its own. +classification: + - library + - propagator diff --git a/instrumentation/couchbase/couchbase-3.1.6/metadata.yaml b/instrumentation/couchbase/couchbase-3.1.6/metadata.yaml index 959f05125813..6a58672e789a 100644 --- a/instrumentation/couchbase/couchbase-3.1.6/metadata.yaml +++ b/instrumentation/couchbase/couchbase-3.1.6/metadata.yaml @@ -1,3 +1,6 @@ description: > Couchbase instrumentation is owned by the Couchbase project for versions 3+. This instrumentation automatically configures the instrumentation provided by the Couchbase library. +classification: + - library + - configuration diff --git a/instrumentation/couchbase/couchbase-3.1/metadata.yaml b/instrumentation/couchbase/couchbase-3.1/metadata.yaml index 959f05125813..6a58672e789a 100644 --- a/instrumentation/couchbase/couchbase-3.1/metadata.yaml +++ b/instrumentation/couchbase/couchbase-3.1/metadata.yaml @@ -1,3 +1,6 @@ description: > Couchbase instrumentation is owned by the Couchbase project for versions 3+. This instrumentation automatically configures the instrumentation provided by the Couchbase library. +classification: + - library + - configuration diff --git a/instrumentation/couchbase/couchbase-3.2/metadata.yaml b/instrumentation/couchbase/couchbase-3.2/metadata.yaml index 959f05125813..6a58672e789a 100644 --- a/instrumentation/couchbase/couchbase-3.2/metadata.yaml +++ b/instrumentation/couchbase/couchbase-3.2/metadata.yaml @@ -1,3 +1,6 @@ description: > Couchbase instrumentation is owned by the Couchbase project for versions 3+. This instrumentation automatically configures the instrumentation provided by the Couchbase library. +classification: + - library + - configuration diff --git a/instrumentation/executors/metadata.yaml b/instrumentation/executors/metadata.yaml index d2b8978137a6..fd9173b5a6c5 100644 --- a/instrumentation/executors/metadata.yaml +++ b/instrumentation/executors/metadata.yaml @@ -4,7 +4,9 @@ description: > is submitted, the current context is captured and bound to the task. Then, when the task eventually runs, even if it’s on a different thread, the instrumentation reactivates that context, enabling consistent correlation across concurrent and asynchronous workflows. - +classification: + - library + - propagator configurations: - name: otel.instrumentation.executors.include description: List of Executor subclasses to be instrumented. diff --git a/instrumentation/external-annotations/metadata.yaml b/instrumentation/external-annotations/metadata.yaml index 5e9578e705ee..1e902e1b33ba 100644 --- a/instrumentation/external-annotations/metadata.yaml +++ b/instrumentation/external-annotations/metadata.yaml @@ -1,4 +1,5 @@ -classification: custom +classification: + - custom description: > The external-annotations instrumentation acts as a "shim" that automatically instruments methods annotated with custom or third-party tracing annotations. This is particularly useful if you have diff --git a/instrumentation/internal/internal-application-logger/metadata.yaml b/instrumentation/internal/internal-application-logger/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/internal/internal-application-logger/metadata.yaml +++ b/instrumentation/internal/internal-application-logger/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/internal/internal-class-loader/metadata.yaml b/instrumentation/internal/internal-class-loader/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/internal/internal-class-loader/metadata.yaml +++ b/instrumentation/internal/internal-class-loader/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/internal/internal-eclipse-osgi-3.6/metadata.yaml b/instrumentation/internal/internal-eclipse-osgi-3.6/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/internal/internal-eclipse-osgi-3.6/metadata.yaml +++ b/instrumentation/internal/internal-eclipse-osgi-3.6/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/internal/internal-lambda/metadata.yaml b/instrumentation/internal/internal-lambda/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/internal/internal-lambda/metadata.yaml +++ b/instrumentation/internal/internal-lambda/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/internal/internal-reflection/metadata.yaml b/instrumentation/internal/internal-reflection/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/internal/internal-reflection/metadata.yaml +++ b/instrumentation/internal/internal-reflection/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/internal/internal-url-class-loader/metadata.yaml b/instrumentation/internal/internal-url-class-loader/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/internal/internal-url-class-loader/metadata.yaml +++ b/instrumentation/internal/internal-url-class-loader/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/java-util-logging/metadata.yaml b/instrumentation/java-util-logging/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/java-util-logging/metadata.yaml +++ b/instrumentation/java-util-logging/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/jmx-metrics/metadata.yaml b/instrumentation/jmx-metrics/metadata.yaml index 34f5b4213aca..59eea511b618 100644 --- a/instrumentation/jmx-metrics/metadata.yaml +++ b/instrumentation/jmx-metrics/metadata.yaml @@ -1,4 +1,5 @@ -classification: custom +classification: + - custom description: > Collects and reports metrics exposed through Java Management Extensions (JMX). It can be configured to extract JVM and application-level telemetry data from JMX MBeans such as memory diff --git a/instrumentation/methods/metadata.yaml b/instrumentation/methods/metadata.yaml index 0c9b2bb73353..facd6dec3fa8 100644 --- a/instrumentation/methods/metadata.yaml +++ b/instrumentation/methods/metadata.yaml @@ -1,4 +1,5 @@ -classification: custom +classification: + - custom description: > Provides a flexible way to capture telemetry at the method level in JVM applications. By weaving instrumentation into targeted methods at runtime based on the diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/metadata.yaml b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/metadata.yaml +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.10/metadata.yaml b/instrumentation/opentelemetry-api/opentelemetry-api-1.10/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.10/metadata.yaml +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.10/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.15/metadata.yaml b/instrumentation/opentelemetry-api/opentelemetry-api-1.15/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.15/metadata.yaml +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.15/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.27/metadata.yaml b/instrumentation/opentelemetry-api/opentelemetry-api-1.27/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.27/metadata.yaml +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.27/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/metadata.yaml b/instrumentation/opentelemetry-api/opentelemetry-api-1.31/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/metadata.yaml +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.31/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/metadata.yaml b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/metadata.yaml +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.37/metadata.yaml b/instrumentation/opentelemetry-api/opentelemetry-api-1.37/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.37/metadata.yaml +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.37/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.38/metadata.yaml b/instrumentation/opentelemetry-api/opentelemetry-api-1.38/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.38/metadata.yaml +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.38/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.4/metadata.yaml b/instrumentation/opentelemetry-api/opentelemetry-api-1.4/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.4/metadata.yaml +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.4/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.40/metadata.yaml b/instrumentation/opentelemetry-api/opentelemetry-api-1.40/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.40/metadata.yaml +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.40/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.42/metadata.yaml b/instrumentation/opentelemetry-api/opentelemetry-api-1.42/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.42/metadata.yaml +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.42/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.47/metadata.yaml b/instrumentation/opentelemetry-api/opentelemetry-api-1.47/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.47/metadata.yaml +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.47/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.50/metadata.yaml b/instrumentation/opentelemetry-api/opentelemetry-api-1.50/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.50/metadata.yaml +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.50/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.52/metadata.yaml b/instrumentation/opentelemetry-api/opentelemetry-api-1.52/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.52/metadata.yaml +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.52/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/opentelemetry-extension-annotations-1.0/metadata.yaml b/instrumentation/opentelemetry-extension-annotations-1.0/metadata.yaml index cd1c92c27857..1bd3a538a920 100644 --- a/instrumentation/opentelemetry-extension-annotations-1.0/metadata.yaml +++ b/instrumentation/opentelemetry-extension-annotations-1.0/metadata.yaml @@ -1,4 +1,5 @@ -classification: custom +classification: + - custom description: > Instruments methods annotated with OpenTelemetry extension annotations, such as @WithSpan and @SpanAttribute. diff --git a/instrumentation/opentelemetry-extension-kotlin-1.0/metadata.yaml b/instrumentation/opentelemetry-extension-kotlin-1.0/metadata.yaml index f2c98a07d4cd..f4a829506c8c 100644 --- a/instrumentation/opentelemetry-extension-kotlin-1.0/metadata.yaml +++ b/instrumentation/opentelemetry-extension-kotlin-1.0/metadata.yaml @@ -1,4 +1,5 @@ -classification: internal +classification: + - internal description: > Our Kotlin coroutine instrumentation relies on a shaded copy of the opentelemetry-extension-kotlin library. This can cause conflicts when the application itself also uses diff --git a/instrumentation/opentelemetry-instrumentation-annotations-1.16/metadata.yaml b/instrumentation/opentelemetry-instrumentation-annotations-1.16/metadata.yaml index c7da9704cc33..35d7078c0c09 100644 --- a/instrumentation/opentelemetry-instrumentation-annotations-1.16/metadata.yaml +++ b/instrumentation/opentelemetry-instrumentation-annotations-1.16/metadata.yaml @@ -1,4 +1,5 @@ -classification: custom +classification: + - custom description: > Instruments methods annotated with OpenTelemetry instrumentation annotations, such as @WithSpan and @SpanAttribute. diff --git a/instrumentation/opentelemetry-instrumentation-api/metadata.yaml b/instrumentation/opentelemetry-instrumentation-api/metadata.yaml index 5a03ece2f748..410703a76044 100644 --- a/instrumentation/opentelemetry-instrumentation-api/metadata.yaml +++ b/instrumentation/opentelemetry-instrumentation-api/metadata.yaml @@ -1 +1,2 @@ -classification: internal +classification: + - internal diff --git a/instrumentation/spark-2.3/metadata.yaml b/instrumentation/spark-2.3/metadata.yaml index e4523dffa326..cec23ee1a091 100644 --- a/instrumentation/spark-2.3/metadata.yaml +++ b/instrumentation/spark-2.3/metadata.yaml @@ -1,3 +1,6 @@ description: > This instrumentation does not emit telemetry on its own. Instead, it extracts the HTTP route and attaches it to SERVER spans and HTTP server metrics. +classification: + - library + - enricher diff --git a/instrumentation/spring/spring-security-config-6.0/metadata.yaml b/instrumentation/spring/spring-security-config-6.0/metadata.yaml index a009f50b527a..8bc3f5de7de9 100644 --- a/instrumentation/spring/spring-security-config-6.0/metadata.yaml +++ b/instrumentation/spring/spring-security-config-6.0/metadata.yaml @@ -3,6 +3,9 @@ description: > attributes, and is only enabled when at least one of the `enduser` configurations is enabled. NOTE: The `enduser` attributes have been deprecated and will be removed in 3.0+ of the java agent. +classification: + - library + - enricher configurations: - name: otel.instrumentation.common.enduser.id.enabled description: Enables capturing the enduser.id attribute.