Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
38 changes: 38 additions & 0 deletions docs/instrumentation-list.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,21 @@ libraries:
- org.apache.camel:camel-core:[2.19,3)
cassandra:
- name: cassandra-4.0
description: |
Instruments the Cassandra database client, providing database client spans and metrics for Cassandra queries.
source_path: instrumentation/cassandra/cassandra-4.0
scope:
name: io.opentelemetry.cassandra-4.0
target_versions:
javaagent:
- com.datastax.oss:java-driver-core:[4.0,4.4)
configurations:
- name: otel.instrumentation.common.db-statement-sanitizer.enabled
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@trask should we have a framework specific flags for this in all frameworks? I think it was added for a few.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I almost wish we didn't have the "common" variant, to make it harder for users to do the wrong thing (send sensitive data unexpectedly from some other db instrumentation)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would it be worth me opening an issue to replace the common config flags, or at the very least start with this one? I plan on working through module to module to document the various configs, so I can track the common ones I find and replace the usages with framework specific ones as I go, if that's a direction we want to move in.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, I only dislike this one common flag due to it broadly disabling sensitive data sanitization, the other common flags I like

I'm not sure I dislike it enough though to cause upgrade pain by removing it

description: Enables or disables statement sanitization for database queries.
default: 'true'
- name: cassandra-4.4
description: |
Instruments the Cassandra database client, providing database client spans and metrics for Cassandra queries.
source_path: instrumentation/cassandra/cassandra-4.4
scope:
name: io.opentelemetry.cassandra-4.4
Expand All @@ -254,13 +262,23 @@ libraries:
- com.datastax.oss:java-driver-core:[4.4,]
library:
- com.datastax.oss:java-driver-core:4.4.0
configurations:
- name: otel.instrumentation.common.db-statement-sanitizer.enabled
description: Enables or disables statement sanitization for database queries.
default: 'true'
- name: cassandra-3.0
description: |
Instruments the Cassandra database client, providing database client spans and metrics for Cassandra queries.
source_path: instrumentation/cassandra/cassandra-3.0
scope:
name: io.opentelemetry.cassandra-3.0
target_versions:
javaagent:
- com.datastax.cassandra:cassandra-driver-core:[3.0,4.0)
configurations:
- name: otel.instrumentation.common.db-statement-sanitizer.enabled
description: Enables or disables statement sanitization for database queries.
default: 'true'
clickhouse:
- name: clickhouse-client-0.5
description: Instruments the V1 ClickHouseClient, providing database client spans
Expand All @@ -271,6 +289,10 @@ libraries:
target_versions:
javaagent:
- com.clickhouse.client:clickhouse-client:[0.5.0,)
configurations:
- name: otel.instrumentation.common.db-statement-sanitizer.enabled
description: Enables or disables statement sanitization for database queries.
default: 'true'
couchbase:
- name: couchbase-3.1.6
source_path: instrumentation/couchbase/couchbase-3.1.6
Expand Down Expand Up @@ -382,6 +404,8 @@ libraries:
- org.elasticsearch:elasticsearch:[5.3.0,6.0.0)
executors:
- name: executors
description: |
The executor instrumentation ensures that context is automatically carried across threads by wrapping common Java executors (e.g., Executor, ExecutorService, 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
scope:
name: io.opentelemetry.executors
Expand Down Expand Up @@ -708,13 +732,27 @@ libraries:
- org.jboss.logmanager:jboss-logmanager:[1.1.0.GA,)
jdbc:
- name: jdbc
description: |
Traces JDBC operations such as statements, batches, commits, and rollbacks by injecting byte‑code into JDBC drivers and common connection‑pool proxies. Each call produces a span named after the SQL verb, enriched with standard DB client attributes (system, database, operation, sanitized statement, peer address) and error details if an exception occurs.
disabled_by_default: true
source_path: instrumentation/jdbc
scope:
name: io.opentelemetry.jdbc
target_versions:
javaagent:
- Java 8+
configurations:
- name: otel.instrumentation.jdbc.statement-sanitizer.enabled
description: Enables or disables statement sanitization for database queries.
Takes precedent to otel.instrumentation.common.db-statement-sanitizer.enabled.
default: 'true'
- name: otel.instrumentation.common.db-statement-sanitizer.enabled
description: Enables or disables statement sanitization for database queries.
default: 'true'
- name: otel.instrumentation.common.peer-service-mapping
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related to this PR but I guess the peer service handling is a bit inconsistent. I think we are using it only for some of the instrumentations.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you think it's worth an effort to standardize the approach?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should strive for consistent behavior across instrumentations, but it is one of the many nice to have things.

description: Used to specify a mapping from host names or IP addresses to peer
services.
default: ''
jedis:
- name: jedis-1.4
source_path: instrumentation/jedis/jedis-1.4
Expand Down
1 change: 1 addition & 0 deletions instrumentation-docs/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ otelJava {

dependencies {
implementation("org.yaml:snakeyaml:2.4")
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.2")
implementation("io.opentelemetry:opentelemetry-sdk-common")

testImplementation(enforcedPlatform("org.junit:junit-bom:5.12.2"))
Expand Down
7 changes: 7 additions & 0 deletions instrumentation-docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ public class SpringWebInstrumentationModule extends InstrumentationModule
* List of supported versions by the module, broken down by `library` or `javaagent` support
* scope
* Name: The scope name of the instrumentation, `io.opentelemetry.{instrumentation name}`
* configurations settings
* List of settings that are available for the instrumentation module
* Each setting has a name, description, and default value

## Methodology

Expand All @@ -81,6 +84,10 @@ As of now, the following fields are supported, all of which are optional:
description: "Instruments..." # Description of the instrumentation module
disabled_by_default: true # Defaults to `false`
classification: internal # instrumentation classification: library | internal | custom
configurations:
- name: otel.instrumentation.common.db-statement-sanitizer.enabled
description: Enables or disables statement sanitization for database queries.
default: true
```

### Gradle File Derived Information
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

package io.opentelemetry.instrumentation.docs;

import static java.util.Locale.Category.FORMAT;

import com.fasterxml.jackson.core.JsonProcessingException;
import io.opentelemetry.instrumentation.docs.internal.InstrumentationModule;
import io.opentelemetry.instrumentation.docs.utils.FileManager;
import io.opentelemetry.instrumentation.docs.utils.YamlHelper;
Expand All @@ -14,13 +17,16 @@
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Locale;
import java.util.TreeMap;
import java.util.logging.Logger;
import java.util.stream.Collectors;

public class DocGeneratorApplication {

private static final Logger logger = Logger.getLogger(DocGeneratorApplication.class.getName());

public static void main(String[] args) {
public static void main(String[] args) throws JsonProcessingException {
FileManager fileManager = new FileManager("instrumentation/");
List<InstrumentationModule> modules = new InstrumentationAnalyzer(fileManager).analyze();

Expand All @@ -35,6 +41,67 @@ public static void main(String[] args) {
} catch (IOException e) {
logger.severe("Error writing instrumentation list: " + e.getMessage());
}

printStats(modules);
}

private static void printStats(List<InstrumentationModule> modules) {
List<InstrumentationModule> metadata =
modules.stream().filter(m -> m.getMetadata() != null).toList();

long withDescriptions =
metadata.stream()
.filter(
m ->
m.getMetadata().getDescription() != null
&& !m.getMetadata().getDescription().isEmpty())
.count();

long withConfigurations =
metadata.stream().filter(m -> !m.getMetadata().getConfigurations().isEmpty()).count();

String stats =
String.format(
Locale.getDefault(FORMAT),
"""
-----------------------------------
Analysis Summary:
Total Modules: %d
By classification:
%s
metadata.yaml contents:
%s
%s
""",
modules.size(),
getClassificationStats(modules),
getPercentage("descriptions", withDescriptions, modules.size()),
getPercentage("configurations", withConfigurations, modules.size()));

logger.info(stats);
}

private static String getClassificationStats(List<InstrumentationModule> modules) {
return modules.stream()
.collect(
Collectors.groupingBy(
m -> m.getMetadata().getClassification(), TreeMap::new, Collectors.toList()))
.entrySet()
.stream()
.map(
entry ->
String.format(
Locale.getDefault(FORMAT), "\t%s: %d", entry.getKey(), entry.getValue().size()))
.collect(Collectors.joining("\n"));
}

private static String getPercentage(String label, long numerator, long denominator) {
return label
+ ": "
+ numerator
+ " ("
+ String.format(Locale.getDefault(FORMAT), "%.2f", (double) numerator / denominator * 100)
+ "%)";
}

private DocGeneratorApplication() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

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

import com.fasterxml.jackson.core.JsonProcessingException;
import io.opentelemetry.instrumentation.docs.internal.DependencyInfo;
import io.opentelemetry.instrumentation.docs.internal.InstrumentationModule;
import io.opentelemetry.instrumentation.docs.internal.InstrumentationType;
Expand Down Expand Up @@ -62,7 +63,7 @@ public static List<InstrumentationModule> convertToInstrumentationModules(
*
* @return a list of {@link InstrumentationModule}
*/
List<InstrumentationModule> analyze() {
List<InstrumentationModule> analyze() throws JsonProcessingException {
List<InstrumentationPath> paths = fileManager.getInstrumentationPaths();
List<InstrumentationModule> modules = convertToInstrumentationModules(paths);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.docs.internal;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public record ConfigurationOption(
String name, String description, @JsonProperty("default") String defaultValue) {}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

package io.opentelemetry.instrumentation.docs.internal;

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;
Expand All @@ -15,16 +18,26 @@
*/
public class InstrumentationMetaData {
@Nullable private String description;
@Nullable private Boolean disabledByDefault;

@JsonProperty("disabled_by_default")
@Nullable
private Boolean disabledByDefault;

private String classification;

private List<ConfigurationOption> configurations = Collections.emptyList();

public InstrumentationMetaData() {}

public InstrumentationMetaData(
String description, String classification, Boolean disabledByDefault) {
String description,
String classification,
Boolean disabledByDefault,
List<ConfigurationOption> configurations) {
this.classification = classification;
this.disabledByDefault = disabledByDefault;
this.description = description;
this.configurations = Objects.requireNonNullElse(configurations, Collections.emptyList());
}

@Nullable
Expand Down Expand Up @@ -54,4 +67,12 @@ public void setClassification(@Nullable String classification) {
public void setDisabledByDefault(@Nullable Boolean disabledByDefault) {
this.disabledByDefault = disabledByDefault;
}

public List<ConfigurationOption> getConfigurations() {
return configurations;
}

public void setConfigurations(@Nullable List<ConfigurationOption> configurations) {
this.configurations = Objects.requireNonNullElse(configurations, Collections.emptyList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@

package io.opentelemetry.instrumentation.docs.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import io.opentelemetry.instrumentation.docs.internal.ConfigurationOption;
import io.opentelemetry.instrumentation.docs.internal.InstrumentationClassification;
import io.opentelemetry.instrumentation.docs.internal.InstrumentationMetaData;
import io.opentelemetry.instrumentation.docs.internal.InstrumentationModule;
Expand All @@ -17,23 +21,13 @@
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;

public class YamlHelper {

private static final Logger logger = Logger.getLogger(YamlHelper.class.getName());

private static final Yaml metaDataYaml = new Yaml();

static {
TypeDescription customDescriptor = new TypeDescription(InstrumentationMetaData.class);
customDescriptor.substituteProperty(
"disabled_by_default", Boolean.class, "getDisabledByDefault", "setDisabledByDefault");
customDescriptor.substituteProperty(
"classification", String.class, "getClassification", "setClassification");
metaDataYaml.addTypeDescription(customDescriptor);
}
private static final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());

public static void generateInstrumentationYaml(
List<InstrumentationModule> list, BufferedWriter writer) {
Expand Down Expand Up @@ -149,6 +143,18 @@ private static Map<String, Object> baseProperties(InstrumentationModule module)
moduleMap.put("target_versions", targetVersions);
}

if (module.getMetadata() != null && !module.getMetadata().getConfigurations().isEmpty()) {
List<Map<String, String>> configurations = new ArrayList<>();
for (ConfigurationOption configuration : module.getMetadata().getConfigurations()) {
Map<String, String> conf = new LinkedHashMap<>();
conf.put("name", configuration.name());
conf.put("description", configuration.description());
conf.put("default", configuration.defaultValue());
configurations.add(conf);
}
moduleMap.put("configurations", configurations);
}

return moduleMap;
}

Expand All @@ -158,8 +164,9 @@ private static Map<String, Object> getScopeMap(InstrumentationModule module) {
return scopeMap;
}

public static InstrumentationMetaData metaDataParser(String input) {
return metaDataYaml.loadAs(input, InstrumentationMetaData.class);
public static InstrumentationMetaData metaDataParser(String input)
throws JsonProcessingException {
return mapper.readValue(input, InstrumentationMetaData.class);
}

private YamlHelper() {}
Expand Down
Loading
Loading