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
92 changes: 92 additions & 0 deletions docs/contributing/documenting-instrumentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,22 @@ configurations:
description: Enables statement sanitization for database queries.
type: boolean
default: true
override_telemetry: false
additional_telemetry:
- when: "default"
metrics:
- name: "metric.name"
description: "Metric description"
type: "COUNTER"
unit: "1"
attributes:
- name: "attribute.name"
type: "STRING"
spans:
- span_kind: "CLIENT"
attributes:
- name: "span.attribute"
type: "STRING"
```

### Description (required)
Expand Down Expand Up @@ -205,6 +221,82 @@ If an instrumentation is disabled by default, set `disabled_by_default: true`. T
the instrumentation will not be active unless explicitly enabled by the user. If this field is omitted,
it defaults to `false`, meaning the instrumentation is enabled by default.

### Manual Telemetry Documentation (optional)

You can manually document telemetry metadata (metrics and spans) directly in the `metadata.yaml` file
using the `additional_telemetry` field. This is useful for:

- Documenting telemetry that may not be captured during automated test runs
- Adding telemetry documentation when `.telemetry` files are not available
- Providing additional context or details about emitted telemetry

#### additional_telemetry

The `additional_telemetry` field allows you to specify telemetry metadata organized by configuration
conditions (`when` field):

```yaml
additional_telemetry:
- when: "default" # Telemetry emitted by default
metrics:
- name: "http.server.request.duration"
description: "Duration of HTTP server requests"
type: "HISTOGRAM"
unit: "ms"
attributes:
- name: "http.method"
type: "STRING"
- name: "http.status_code"
type: "LONG"
spans:
- span_kind: "SERVER"
attributes:
- name: "http.method"
type: "STRING"
- name: "http.url"
type: "STRING"
- when: "otel.instrumentation.example.experimental-metrics.enabled" # Telemetry enabled by configuration
metrics:
- name: "example.experimental.metric"
description: "Experimental metric enabled by configuration"
type: "COUNTER"
unit: "1"
```

Each telemetry entry includes:

- `when`: The configuration condition under which this telemetry is emitted. Use `"default"` for telemetry
emitted by default, or specify the configuration option name for conditional telemetry.
- `metrics`: List of metrics with their name, description, type, unit, and attributes
- `spans`: List of span configurations with their span_kind and attributes

For metrics, supported `type` values include: `COUNTER`, `GAUGE`, `HISTOGRAM`, `EXPONENTIAL_HISTOGRAM`.

For spans, supported `span_kind` values include: `CLIENT`, `SERVER`, `PRODUCER`, `CONSUMER`, `INTERNAL`.

For attributes, supported `type` values include: `STRING`, `LONG`, `DOUBLE`, `BOOLEAN`.

#### override_telemetry

Set `override_telemetry: true` to completely replace any auto-generated telemetry data from `.telemetry`
files. When this is enabled, only the manually documented telemetry in `additional_telemetry` will be
used, and any `.telemetry` files will be ignored.

```yaml
override_telemetry: true
additional_telemetry:
- when: "default"
metrics:
- name: "manually.documented.metric"
description: "This completely replaces auto-generated telemetry"
type: "GAUGE"
unit: "bytes"
```

If `override_telemetry` is `false` or omitted (default behavior), manual telemetry will be merged with
auto-generated telemetry, with manual entries taking precedence in case of conflicts (same metric name
or span kind within the same `when` condition).

## Instrumentation List (docs/instrumentation-list.md)

The contents of the `metadata.yaml` files are combined with other information about the instrumentation
Expand Down
4 changes: 2 additions & 2 deletions instrumentation-docs/instrumentations.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ readonly INSTRUMENTATIONS=(
"apache-httpasyncclient-4.1:javaagent:test"
"apache-httpclient:apache-httpclient-2.0:javaagent:test"
"apache-httpclient:apache-httpclient-4.0:javaagent:test"
"apache-httpclient:apache-httpclient-4.3:library:test"
# "apache-httpclient:apache-httpclient-4.3:library:test" # See https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/14771
"apache-httpclient:apache-httpclient-5.0:javaagent:test"
"apache-httpclient:apache-httpclient-5.2:library:test"
# "apache-httpclient:apache-httpclient-5.2:library:test" # See https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/14771
"armeria:armeria-1.3:javaagent:test"
"armeria:armeria-grpc-1.14:javaagent:test"
"async-http-client:async-http-client-1.9:javaagent:test"
Expand Down
60 changes: 60 additions & 0 deletions instrumentation-docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,22 @@ configurations:
description: Enables statement sanitization for database queries.
type: boolean # boolean | string | list | map
default: true
override_telemetry: false # Set to true to ignore auto-generated .telemetry files
additional_telemetry: # Manually document telemetry metadata
- when: "default"
metrics:
- name: "metric.name"
description: "Metric description"
type: "COUNTER"
unit: "1"
attributes:
- name: "attribute.name"
type: "STRING"
spans:
- span_kind: "CLIENT"
attributes:
- name: "span.attribute"
type: "STRING"
```

### Gradle File Derived Information
Expand Down Expand Up @@ -214,6 +230,50 @@ data will be excluded from git and just generated on demand.
Each file has a `when` value along with the list of metrics that indicates whether the telemetry is
emitted by default or via a configuration option.

#### Manual Telemetry Documentation

In addition to auto-generated telemetry data from test runs, you can manually document telemetry
metadata directly in the `metadata.yaml` file. This is useful for:

- Documenting telemetry that may not be captured during test runs
- Overriding auto-generated telemetry data when it's incomplete or incorrect
- Adding additional telemetry documentation that complements the auto-generated data

You can add manual telemetry documentation using the `additional_telemetry` field:

```yaml
additional_telemetry:
- when: "default" # or any configuration condition
metrics:
- name: "my.custom.metric"
description: "Description of the metric"
type: "COUNTER"
unit: "1"
attributes:
- name: "attribute.name"
type: "STRING"
spans:
- span_kind: "CLIENT"
attributes:
- name: "span.attribute"
type: "STRING"
```

To completely replace auto-generated telemetry data (ignoring `.telemetry` files), set `override_telemetry: true`:

```yaml
override_telemetry: true
additional_telemetry:
- when: "default"
metrics:
- name: "documented.metric"
description: "This replaces all auto-generated metrics"
type: "GAUGE"
unit: "ms"
```

When both manual and auto-generated telemetry exist for the same `when` condition, they are merged with manual entries taking precedence in case of conflicts (same metric name or span kind).

## Doc Synchronization

The documentation site has a section that lists all the instrumentations in the context of
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
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.EmittedMetrics;
import io.opentelemetry.instrumentation.docs.internal.EmittedSpans;
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.TelemetryMerger;
import io.opentelemetry.instrumentation.docs.parsers.GradleParser;
import io.opentelemetry.instrumentation.docs.parsers.MetricParser;
import io.opentelemetry.instrumentation.docs.parsers.ModuleParser;
Expand Down Expand Up @@ -64,8 +67,9 @@ private void enrichModule(InstrumentationModule module) throws IOException {
}

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

// Handle telemetry merging (manual + emitted)
setMergedTelemetry(module, metaData);
}

@Nullable
Expand All @@ -88,4 +92,32 @@ private Map<InstrumentationType, Set<String>> getVersionInformation(
List<String> gradleFiles = fileManager.findBuildGradleFiles(module.getSrcPath());
return GradleParser.extractVersions(gradleFiles, module);
}

/**
* Sets merged telemetry data on the module, combining manual telemetry from metadata.yaml with
* emitted telemetry from .telemetry files.
*/
private void setMergedTelemetry(
InstrumentationModule module, @Nullable InstrumentationMetadata metadata) throws IOException {
Map<String, List<EmittedMetrics.Metric>> emittedMetrics =
MetricParser.getMetrics(module, fileManager);
Map<String, List<EmittedSpans.Span>> emittedSpans = SpanParser.getSpans(module, fileManager);

if (metadata != null && !metadata.getAdditionalTelemetry().isEmpty()) {
TelemetryMerger.MergedTelemetryData merged =
TelemetryMerger.merge(
metadata.getAdditionalTelemetry(),
metadata.getOverrideTelemetry(),
emittedMetrics,
emittedSpans,
module.getInstrumentationName());

module.setMetrics(merged.metrics());
module.setSpans(merged.spans());
} else {
// No manual telemetry, use emitted only
module.setMetrics(emittedMetrics);
module.setSpans(emittedSpans);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static java.util.Collections.emptyList;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -157,5 +158,55 @@ public List<TelemetryAttribute> getAttributes() {
public void setAttributes(List<TelemetryAttribute> attributes) {
this.attributes = attributes;
}

/**
* Builder for creating EmittedMetrics.Metric instances. This class is internal and is hence not
* for public use. Its APIs are unstable and can change at any time.
*/
public static class Builder {
private String name = "";
private String description = "";
private String type = "";
private String unit = "";
private List<TelemetryAttribute> attributes = new ArrayList<>();

@CanIgnoreReturnValue
public Builder name(String name) {
this.name = name;
return this;
}

@CanIgnoreReturnValue
public Builder description(String description) {
this.description = description;
return this;
}

@CanIgnoreReturnValue
public Builder type(String type) {
this.type = type;
return this;
}

@CanIgnoreReturnValue
public Builder unit(String unit) {
this.unit = unit;
return this;
}

@CanIgnoreReturnValue
public Builder attributes(List<TelemetryAttribute> attributes) {
this.attributes = attributes != null ? attributes : new ArrayList<>();
return this;
}

public Metric build() {
return new Metric(name, description, type, unit, attributes);
}
}

public static Builder builder() {
return new Builder();
}
}
}
Loading