diff --git a/docs/content/config/config.md b/docs/content/config/config.md index 4161ddb15..45c6d717d 100644 --- a/docs/content/config/config.md +++ b/docs/content/config/config.md @@ -149,6 +149,24 @@ This works for all Metrics properties. (1) Boolean value, `true` or `false`. Default see Javadoc. +## OpenMetrics 2.0 Properties + + + +| Name | Javadoc | Note | +| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | +| io.prometheus.openmetrics2.enabled | [OpenMetrics2Properties.getEnabled()]() | (1) | +| io.prometheus.openmetrics2.content_negotiation | [OpenMetrics2Properties.getContentNegotiation()]() | (1) | +| io.prometheus.openmetrics2.composite_values | [OpenMetrics2Properties.getCompositeValues()]() | (1) | +| io.prometheus.openmetrics2.exemplar_compliance | [OpenMetrics2Properties.getExemplarCompliance()]() | (1) | +| io.prometheus.openmetrics2.native_histograms | [OpenMetrics2Properties.getNativeHistograms()]() | (1) | + + + +(1) Boolean value, `true` or `false`. `enabled=true` switches OpenMetrics responses to the OM2 +writer, preserving metric names as written by the application. The other OM2 properties remain +opt-in. All OpenMetrics 2.0 flags are experimental and default to `false`. + ## Exporter Filter Properties @@ -198,6 +216,7 @@ Only metrics starting with these prefixes will be exposed.
| io.prometheus.exporter.opentelemetry.service_instance_id | [OpenTelemetryExporter.Builder.serviceInstanceId()]() | | | io.prometheus.exporter.opentelemetry.service_version | [OpenTelemetryExporter.Builder.serviceVersion()]() | | | io.prometheus.exporter.opentelemetry.resource_attributes | [OpenTelemetryExporter.Builder.resourceAttributes()]() | (3) | +| io.prometheus.exporter.opentelemetry.preserve_names | [ExporterOpenTelemetryProperties.getPreserveNames()]() | (4) | @@ -205,7 +224,8 @@ Only metrics starting with these prefixes will be exposed.
(1) Protocol can be `grpc` or `http/protobuf`.
(2) Format: `key1=value1,key2=value2`
-(3) Format: `key1=value1,key2=value2` +(3) Format: `key1=value1,key2=value2`
+(4) Boolean value, `true` or `false`. Default is `false` for backward compatibility. diff --git a/docs/content/exporters/formats.md b/docs/content/exporters/formats.md index a6485c84c..6360c66cd 100644 --- a/docs/content/exporters/formats.md +++ b/docs/content/exporters/formats.md @@ -11,6 +11,11 @@ All exporters the following exposition formats: Moreover, gzip encoding is supported for each of these formats. +## OpenMetrics 2.0 Preview + +The library also includes an experimental OpenMetrics 2.0 writer. It is disabled by default and +must be enabled explicitly. See [OpenMetrics 2.0 Preview]({{< relref "./openmetrics2.md" >}}). + ## Scraping with a Prometheus server The Prometheus server sends an `Accept` header to specify which format is requested. By default, the diff --git a/docs/content/exporters/openmetrics2.md b/docs/content/exporters/openmetrics2.md new file mode 100644 index 000000000..607273881 --- /dev/null +++ b/docs/content/exporters/openmetrics2.md @@ -0,0 +1,129 @@ +--- +title: OpenMetrics 2.0 Preview +weight: 2 +--- + +The Prometheus Java client library includes experimental support for the OpenMetrics 2.0 text +format. + +{{< hint type=warning >}} +OpenMetrics 2.0 support is opt-in, experimental, and subject to change while the specification is +still in draft. +{{< /hint >}} + +{{< toc >}} + +## Enable OpenMetrics 2.0 + +To switch OpenMetrics responses from the legacy OM1 writer to the OM2 writer, set: + +```properties +io.prometheus.openmetrics2.enabled=true +``` + +Programmatic configuration: + +```java +PrometheusProperties properties = PrometheusProperties.builder() + .enableOpenMetrics2(om2 -> {}) + .build(); +``` + +Enabling `enableOpenMetrics2(...)` also enables the top-level `enabled` flag automatically, so you +only need to configure the sub-flags you want. + +With `enabled=true` alone: + +- OpenMetrics requests use the OM2 writer. +- Metric names are preserved as written by the application. +- Optional OM2 features such as `composite_values`, `exemplar_compliance`, and + `native_histograms` remain off. + +To enable OM2 only when the scraper explicitly requests `version=2.0.0`, set: + +```properties +io.prometheus.openmetrics2.enabled=true +io.prometheus.openmetrics2.content_negotiation=true +``` + +Programmatic equivalent: + +```java +PrometheusProperties properties = PrometheusProperties.builder() + .enableOpenMetrics2(om2 -> om2.contentNegotiation(true)) + .build(); +``` + +## Naming Behavior + +OpenMetrics 2.0 removes OM1 suffix rewriting. + +- Counters do not get `_total` appended automatically. +- Units do not get appended automatically. +- Info metrics still end in `_info` because that is required by the spec. + +Examples: + +| Metric builder input | OM1 output | OM2 output | +| ---------------------------------- | ----------------- | -------------- | +| `Counter("events")` | `events_total` | `events` | +| `Counter("events_total")` | `events_total` | `events_total` | +| `Counter("req").unit(BYTES)` | `req_bytes_total` | `req` | +| `Counter("req_bytes").unit(BYTES)` | `req_bytes_total` | `req_bytes` | +| `Info("target")` | `target_info` | `target_info` | + +This means OpenMetrics 2.0 does not apply OM1 suffix behavior such as appending `_total` or unit +suffixes, while the legacy OpenMetrics 1.0 and Prometheus text formats keep that existing suffix +behavior. + +## Feature Flags + +All OpenMetrics 2.0 flags default to `false`. + +| Property | Effect | +| ------------------------------------------------ | -------------------------------------------------------------------------------------- | +| `io.prometheus.openmetrics2.enabled` | Metric names are preserved as written by the application. | +| `io.prometheus.openmetrics2.content_negotiation` | Apply OM2 behavior only when the scraper requests `version=2.0.0`. | +| `io.prometheus.openmetrics2.composite_values` | Emit histograms, summaries, and gauge histograms as single composite lines with `st@`. | +| `io.prometheus.openmetrics2.exemplar_compliance` | Emit only OM2-compliant exemplars with timestamps. | +| `io.prometheus.openmetrics2.native_histograms` | Emit OM2 native histogram text fields. | + +Enable all flags at once: + +```java +PrometheusProperties properties = PrometheusProperties.builder() + .enableOpenMetrics2(om2 -> om2.enableAll()) + .build(); +``` + +Equivalent properties: + +```properties +io.prometheus.openmetrics2.enabled=true +io.prometheus.openmetrics2.content_negotiation=true +io.prometheus.openmetrics2.composite_values=true +io.prometheus.openmetrics2.exemplar_compliance=true +io.prometheus.openmetrics2.native_histograms=true +``` + +## Content Negotiation + +If `content_negotiation=false`, OpenMetrics 2.0 behavior is applied to OpenMetrics responses even +if the scraper requested OpenMetrics 1.0. + +If `content_negotiation=true`, OpenMetrics 2.0 behavior is only used when the scraper explicitly +requests `version=2.0.0`. Otherwise the legacy OpenMetrics 1.0 response is returned. + +## Native Histograms + +With `io.prometheus.openmetrics2.native_histograms=true`, the OpenMetrics 2.0 writer emits native +histogram fields such as: + +- `schema` +- `zero_threshold` +- `zero_count` +- positive and negative spans +- positive and negative buckets + +OM2 native histogram output can coexist with classic histogram buckets. When both are present, the +native histogram sample is written first. diff --git a/docs/content/getting-started/metric-types.md b/docs/content/getting-started/metric-types.md index f1c2a2321..a4fee31ad 100644 --- a/docs/content/getting-started/metric-types.md +++ b/docs/content/getting-started/metric-types.md @@ -37,9 +37,13 @@ serviceTimeSeconds.inc(Unit.millisToSeconds(200)); The resulting counter has the value `0.2`. As `SECONDS` is the standard time unit in Prometheus, the `Unit` utility class has methods to convert other time units to seconds. -As defined in [OpenMetrics](https://openmetrics.io/), counter metric names must have the `_total` -suffix. If you create a counter without the `_total` suffix the suffix will be appended -automatically. +For the default OpenMetrics 1.0 and Prometheus text formats, counters are exposed with the +`_total` suffix. You can name a counter either `service_time_seconds` or +`service_time_seconds_total`; the exposed name will be `service_time_seconds_total` in both cases. + +The experimental OpenMetrics 2.0 writer behaves differently: It preserves metric names instead of +appending `_total` or unit suffixes automatically. In OpenMetrics 2.0, `_total` is recommended for +counters, but not enforced by the Java client. ## Gauge diff --git a/docs/content/otel/names.md b/docs/content/otel/names.md index a5425e07f..589be1c2c 100644 --- a/docs/content/otel/names.md +++ b/docs/content/otel/names.md @@ -21,6 +21,26 @@ The main steps when converting OpenTelemetry metric names to Prometheus metric n - If the metric has a unit, append the unit to the metric name, like `_seconds`. - If the metric type has a suffix, append it, like `_total` for counters. +## `preserve_names` + +The Prometheus Java client library can also export its own metrics to OpenTelemetry using the +[OpenTelemetryExporter](/client_java/api/io/prometheus/metrics/exporter/opentelemetry/OpenTelemetryExporter.html). + +For that exporter, `io.prometheus.exporter.opentelemetry.preserve_names=true` preserves metric +names exactly as they were written in the Prometheus Java client. + +Examples: + +| Prometheus Java metric | Default OTel export | With `preserve_names=true` | +| ---------------------------------- | --------------------- | --------------------------- | +| `Counter("events")` | `events` | `events` | +| `Counter("events_total")` | `events` | `events_total` | +| `Counter("req").unit(BYTES)` | name `req`, unit `By` | name `req`, unit `By` | +| `Counter("req_bytes").unit(BYTES)` | name `req`, unit `By` | name `req_bytes`, unit `By` | + +Today the default is `false` for backward compatibility. It is planned to change to `true` in the +next major release. + ## Dots in Metric and Label Names OpenTelemetry defines not only a line protocol, but also _semantic conventions_, i.e. standardized