# Prometheus Client Libraries vs. OpenTelemetry

LLMS index: [llms.txt](/llms.txt)

---

<?code-excerpt path-base="examples/java/prometheus-compatibility"?>

> [!NOTE]
>
> This page covers Java and Go. Examples for other languages are planned.

This guide is for developers familiar with the
[Prometheus client libraries](https://prometheus.io/docs/instrumenting/clientlibs/)
who want to understand equivalent patterns in the OpenTelemetry metrics API and
SDK. It covers the most common patterns, but is not exhaustive.

## Conceptual differences

Before looking at code, it helps to understand a few structural differences
between the two systems. The
[Prometheus and OpenMetrics Compatibility](/docs/specs/otel/compatibility/prometheus_and_openmetrics/)
specification documents the complete translation rules between the two systems.
This section covers the differences most relevant to writing new instrumentation
code.

### Registry (MeterProvider)

In Prometheus, metrics register to a registry — by default a global one. You can
declare a metric anywhere in your code, and it becomes available for scraping
once registered. The exporter (HTTP server or OTLP push) is attached to the
registry as a separate, independent step.

In OpenTelemetry, `MeterProvider` and `Meter` are part of the metrics API. You
obtain a `Meter` — scoped to your library or component — from a `MeterProvider`,
and create instruments from that `Meter`. How those measurements are processed —
which exporters receive them, how they are aggregated, on what schedule — is
determined by the SDK bound to the `MeterProvider` and its configuration, which
is separate from the instrumentation code itself (see
[API and SDK](#otel-api-and-sdk)).

Like Prometheus, OpenTelemetry supports both a global `MeterProvider` (requiring
no explicit wiring from instrumentation code) and explicit `MeterProvider`
instances that can be passed to libraries which support them.

### Label names (attributes)

Prometheus requires label _names_ to be declared at metric creation time. Label
_values_ are bound at record time, via `labelValues(...)`.

OpenTelemetry has no upfront label declaration. Attribute keys and values are
both provided together at the time of the measurement via `Attributes`.

### Naming conventions

Prometheus uses `snake_case` metric names. Counter names end in `_total`. By
convention, Prometheus metric names are prefixed with the application or library
name to avoid collisions (for example, `smart_home_hvac_on_seconds_total`),
since all metrics share a flat global namespace.

OpenTelemetry conventionally uses
[dotted names](/docs/specs/semconv/general/naming/). Ownership and namespacing
are captured in the instrumentation scope (the `Meter` name, for example
`smart.home`), so metric names themselves do not need a prefix (for example,
`hvac.on`). When exporting to Prometheus, the exporter translates names: dots
become underscores, unit abbreviations expand to full words (for example, `s` →
`seconds`), and counters receive a `_total` suffix. An OpenTelemetry counter
named `hvac.on` with unit `s` is exported as `hvac_on_seconds_total`. See the
[compatibility specification](/docs/specs/otel/compatibility/prometheus_and_openmetrics/)
for the complete set of name translation rules. The translation strategy is
configurable — for example, to preserve UTF-8 characters or suppress unit and
type suffixes. See the
[Prometheus exporter](/docs/specs/otel/metrics/sdk_exporters/prometheus/)
configuration reference for details.

### Stateful and callback instruments

Both systems support two recording modes:

- **Prometheus** distinguishes _stateful_ instruments (`Counter`, `Gauge`),
  which maintain their own accumulated value, from function-based instruments,
  which invoke a callback at scrape time to return the current value. The naming
  varies by client library (`GaugeFunc`/`CounterFunc` in Go;
  `GaugeWithCallback`/`CounterWithCallback` in Java).
- **OpenTelemetry** calls these _synchronous_ (counter, histogram, etc.) and
  _asynchronous_ (observed via a registered callback). The semantics are the
  same.

Note also that Prometheus `Gauge` covers two distinct OTel instrument types:
`Gauge` for non-additive values (such as temperature) and `UpDownCounter` for
additive values that can increase or decrease (such as active connections). See
[Gauge](#gauge) for details.

### OTel: API and SDK

OpenTelemetry separates instrumentation from configuration with a two-layer
design: an **API** package and an **SDK** package. The API defines the
interfaces used to record metrics. The SDK provides the implementation — the
concrete provider, exporters, and processing pipeline.

Instrumentation code should depend only on the API. The SDK is configured once
at application startup and wired to an API reference that gets passed to the
rest of the codebase. This keeps instrumentation library code decoupled from any
specific SDK version and makes it straightforward to swap in a no-op
implementation for testing.

### OTel: Instrumentation scope

Prometheus metrics are global: every metric in a process shares the same flat
namespace, identified only by name and labels.

OpenTelemetry scopes each group of instruments to a `Meter`, identified by a
name and optional version (for example, `smart.home`). When exporting to
Prometheus, the scope name and version are added as `otel_scope_name` and
`otel_scope_version` labels on every metric point. Any additional scope
attributes are also added as labels, named `otel_scope_[attr name]`. These
labels appear automatically and may be unfamiliar to users coming from
Prometheus. They can be suppressed via the exporter's `without_scope_info`
option — see the
[Prometheus exporter](/docs/specs/otel/metrics/sdk_exporters/prometheus/)
configuration reference for details. Note that suppressing scope info is only
safe when each metric name is produced by a single scope. If two scopes emit a
metric with the same name, the scope labels are the only thing distinguishing
them; without those labels, you get duplicate time series with no way to
differentiate their origin, which produces invalid output in Prometheus.

### OTel: Aggregation temporality

Prometheus metrics are always cumulative. OpenTelemetry supports both cumulative
and delta temporality, but the Prometheus exporter enforces cumulative for all
instruments. For developers migrating from Prometheus, this is transparent — the
behavior you already rely on is preserved.

### OTel: Resource attributes

Prometheus identifies scrape targets using `job` and `instance` labels, which
are added by the Prometheus server at scrape time.

OpenTelemetry has a `Resource` — structured metadata attached to all telemetry
from a process, with attributes such as `service.name` and
`service.instance.id`. When exporting to Prometheus, the exporter maps resource
attributes to the `job` and `instance` labels, with any remaining attributes
exposed in a `target_info` metric (`target_info` is an OpenMetrics 1.0
convention — if you currently emit it manually from Prometheus, the OTel
equivalent is to set resource attributes). See the
[compatibility specification](/docs/specs/otel/compatibility/prometheus_and_openmetrics/)
for the exact mapping rules. The `target_info` metric can be suppressed via
`without_target_info`, and specific resource attributes can be promoted to
metric-level labels via `with_resource_constant_labels`. See the
[Prometheus exporter](/docs/specs/otel/metrics/sdk_exporters/prometheus/)
configuration reference for details.

## Initialization {#initialization}

The examples below cover the two main deployment patterns: exposing a Prometheus
scrape endpoint and pushing to an OTLP endpoint.

### Expose a Prometheus scrape endpoint

   <ul class="nav nav-tabs" id="tabs-0" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-00-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-00-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-00-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-00-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-0-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-00-00" role="tabpanel" aria-labelled-by="tabs-00-00-tab" tabindex="0">
        <p>Prometheus</p>
<?code-excerpt "src/main/java/otel/PrometheusScrapeInit.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Counter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.exporter.httpserver.HTTPServer</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">java.io.IOException</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusScrapeInit</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">,</span><span class="w"> </span><span class="n">InterruptedException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Create a counter and register it with the default PrometheusRegistry.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Counter</span><span class="w"> </span><span class="n">doorOpens</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Counter</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;door_opens_total&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Total number of times a door has been opened&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;door&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Start the HTTP server; Prometheus scrapes http://localhost:9464/metrics.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">HTTPServer</span><span class="w"> </span><span class="n">server</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HTTPServer</span><span class="p">.</span><span class="na">builder</span><span class="p">().</span><span class="na">port</span><span class="p">(</span><span class="n">9464</span><span class="p">).</span><span class="na">buildAndStart</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Runtime</span><span class="p">.</span><span class="na">getRuntime</span><span class="p">().</span><span class="na">addShutdownHook</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">Thread</span><span class="p">(</span><span class="n">server</span><span class="p">::</span><span class="n">close</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">doorOpens</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;front&#34;</span><span class="p">).</span><span class="na">inc</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Thread</span><span class="p">.</span><span class="na">currentThread</span><span class="p">().</span><span class="na">join</span><span class="p">();</span><span class="w"> </span><span class="c1">// sleep forever</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelScrapeInit.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.LongCounter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.exporter.prometheus.PrometheusHttpServer</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.OpenTelemetrySdk</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.SdkMeterProvider</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelScrapeInit</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c1">// Preallocate attribute keys and, when values are static, entire Attributes objects.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">DOOR</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;door&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">FRONT_DOOR</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DOOR</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;front&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">InterruptedException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Configure the SDK: register a Prometheus reader that serves /metrics.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">OpenTelemetrySdk</span><span class="w"> </span><span class="n">sdk</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">OpenTelemetrySdk</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setMeterProvider</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">SdkMeterProvider</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="p">.</span><span class="na">registerMetricReader</span><span class="p">(</span><span class="n">PrometheusHttpServer</span><span class="p">.</span><span class="na">builder</span><span class="p">().</span><span class="na">setPort</span><span class="p">(</span><span class="n">9464</span><span class="p">).</span><span class="na">build</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="p">.</span><span class="na">build</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Runtime</span><span class="p">.</span><span class="na">getRuntime</span><span class="p">().</span><span class="na">addShutdownHook</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">Thread</span><span class="p">(</span><span class="n">sdk</span><span class="p">::</span><span class="n">close</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Instrumentation code uses the OpenTelemetry API type, not the SDK type directly.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sdk</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Metrics are served at http://localhost:9464/metrics.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">LongCounter</span><span class="w"> </span><span class="n">doorOpens</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">counterBuilder</span><span class="p">(</span><span class="s">&#34;door.opens&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Total number of times a door has been opened&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">doorOpens</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">1</span><span class="p">,</span><span class="w"> </span><span class="n">FRONT_DOOR</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Thread</span><span class="p">.</span><span class="na">currentThread</span><span class="p">().</span><span class="na">join</span><span class="p">();</span><span class="w"> </span><span class="c1">// sleep forever</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-00-01" role="tabpanel" aria-labelled-by="tabs-00-01-tab" tabindex="0">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_scrape_init.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;net/http&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;github.com/prometheus/client_golang/prometheus/promhttp&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Create a counter and register it with a custom registry.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewRegistry</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">doorOpens</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewCounterVec</span><span class="p">(</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">CounterOpts</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">Name</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;door_opens_total&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">Help</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;Total number of times a door has been opened&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">},</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;door&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nx">doorOpens</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Prometheus scrapes http://localhost:9464/metrics.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">http</span><span class="p">.</span><span class="nf">Handle</span><span class="p">(</span><span class="s">&#34;/metrics&#34;</span><span class="p">,</span><span class="w"> </span><span class="nx">promhttp</span><span class="p">.</span><span class="nf">HandlerFor</span><span class="p">(</span><span class="nx">reg</span><span class="p">,</span><span class="w"> </span><span class="nx">promhttp</span><span class="p">.</span><span class="nx">HandlerOpts</span><span class="p">{}))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">go</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nf">ListenAndServe</span><span class="p">(</span><span class="s">&#34;:9464&#34;</span><span class="p">,</span><span class="w"> </span><span class="kc">nil</span><span class="p">)</span><span class="w"> </span><span class="cp">//nolint:errcheck</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">doorOpens</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;front&#34;</span><span class="p">).</span><span class="nf">Inc</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">select</span><span class="w"> </span><span class="p">{}</span><span class="w"> </span><span class="c1">// sleep forever</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_scrape_init.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;net/http&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;github.com/prometheus/client_golang/prometheus/promhttp&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/exporters/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">sdkmetric</span><span class="w"> </span><span class="s">&#34;go.opentelemetry.io/otel/sdk/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ctx</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Configure the SDK: register a Prometheus reader that serves /metrics.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">exporter</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">New</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">provider</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nf">NewMeterProvider</span><span class="p">(</span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nf">WithReader</span><span class="p">(</span><span class="nx">exporter</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">defer</span><span class="w"> </span><span class="nx">provider</span><span class="p">.</span><span class="nf">Shutdown</span><span class="p">(</span><span class="nx">ctx</span><span class="p">)</span><span class="w"> </span><span class="cp">//nolint:errcheck</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Metrics are served at http://localhost:9464/metrics.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">http</span><span class="p">.</span><span class="nf">Handle</span><span class="p">(</span><span class="s">&#34;/metrics&#34;</span><span class="p">,</span><span class="w"> </span><span class="nx">promhttp</span><span class="p">.</span><span class="nf">Handler</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">go</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nf">ListenAndServe</span><span class="p">(</span><span class="s">&#34;:9464&#34;</span><span class="p">,</span><span class="w"> </span><span class="kc">nil</span><span class="p">)</span><span class="w"> </span><span class="cp">//nolint:errcheck</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Instrumentation code uses the API, not the SDK, directly.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">meter</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">provider</span><span class="p">.</span><span class="nf">Meter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">doorOpens</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Int64Counter</span><span class="p">(</span><span class="s">&#34;door.opens&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Total number of times a door has been opened&#34;</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">doorOpens</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;door&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;front&#34;</span><span class="p">)))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">select</span><span class="w"> </span><span class="p">{}</span><span class="w"> </span><span class="c1">// sleep forever</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
</div>


### Push metrics to an OTLP endpoint

   <ul class="nav nav-tabs" id="tabs-1" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-01-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-01-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-01-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-01-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-01-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-01-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-1-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-01-00" role="tabpanel" aria-labelled-by="tabs-01-00-tab" tabindex="1">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusOtlpInit.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Counter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusOtlpInit</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">Exception</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Create a counter and register it with the default PrometheusRegistry.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Counter</span><span class="w"> </span><span class="n">doorOpens</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Counter</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;door_opens_total&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Total number of times a door has been opened&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;door&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Start the OTLP exporter. It reads from the default PrometheusRegistry and</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// pushes metrics to the configured endpoint on a fixed interval.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">OpenTelemetryExporter</span><span class="w"> </span><span class="n">exporter</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">OpenTelemetryExporter</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">protocol</span><span class="p">(</span><span class="s">&#34;http/protobuf&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">endpoint</span><span class="p">(</span><span class="s">&#34;http://localhost:4318&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">intervalSeconds</span><span class="p">(</span><span class="n">60</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">buildAndStart</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Runtime</span><span class="p">.</span><span class="na">getRuntime</span><span class="p">().</span><span class="na">addShutdownHook</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">Thread</span><span class="p">(</span><span class="n">exporter</span><span class="p">::</span><span class="n">close</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">doorOpens</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;front&#34;</span><span class="p">).</span><span class="na">inc</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Thread</span><span class="p">.</span><span class="na">currentThread</span><span class="p">().</span><span class="na">join</span><span class="p">();</span><span class="w"> </span><span class="c1">// sleep forever</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelOtlpInit.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.LongCounter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.OpenTelemetrySdk</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.SdkMeterProvider</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.export.PeriodicMetricReader</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">java.time.Duration</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelOtlpInit</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">InterruptedException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Configure the SDK: export metrics over OTLP/HTTP on a fixed interval.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">OpenTelemetrySdk</span><span class="w"> </span><span class="n">sdk</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">OpenTelemetrySdk</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setMeterProvider</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">SdkMeterProvider</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="p">.</span><span class="na">registerMetricReader</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                        </span><span class="n">PeriodicMetricReader</span><span class="p">.</span><span class="na">builder</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                                </span><span class="n">OtlpHttpMetricExporter</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                                    </span><span class="p">.</span><span class="na">setEndpoint</span><span class="p">(</span><span class="s">&#34;http://localhost:4318&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                                    </span><span class="p">.</span><span class="na">build</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                            </span><span class="p">.</span><span class="na">setInterval</span><span class="p">(</span><span class="n">Duration</span><span class="p">.</span><span class="na">ofSeconds</span><span class="p">(</span><span class="n">60</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                            </span><span class="p">.</span><span class="na">build</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="p">.</span><span class="na">build</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Runtime</span><span class="p">.</span><span class="na">getRuntime</span><span class="p">().</span><span class="na">addShutdownHook</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">Thread</span><span class="p">(</span><span class="n">sdk</span><span class="p">::</span><span class="n">close</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Instrumentation code uses the OpenTelemetry API type, not the SDK type directly.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sdk</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">LongCounter</span><span class="w"> </span><span class="n">doorOpens</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">counterBuilder</span><span class="p">(</span><span class="s">&#34;door.opens&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Total number of times a door has been opened&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">doorOpens</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">1</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Thread</span><span class="p">.</span><span class="na">currentThread</span><span class="p">().</span><span class="na">join</span><span class="p">();</span><span class="w"> </span><span class="c1">// sleep forever</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-01-01" role="tabpanel" aria-labelled-by="tabs-01-01-tab" tabindex="1">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<p>The Prometheus Go client library does not include an OTLP push exporter.</p>
<p>OpenTelemetry</p>
<?code-excerpt "otel_otlp_init.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">sdkmetric</span><span class="w"> </span><span class="s">&#34;go.opentelemetry.io/otel/sdk/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ctx</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Configure the SDK: export metrics over OTLP/HTTP on a fixed interval.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// The endpoint defaults to localhost:4318 and can be configured via</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// the OTEL_EXPORTER_OTLP_ENDPOINT environment variable.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">exporter</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">otlpmetrichttp</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="nx">ctx</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">provider</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nf">NewMeterProvider</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nf">WithReader</span><span class="p">(</span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nf">NewPeriodicReader</span><span class="p">(</span><span class="nx">exporter</span><span class="p">)),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">defer</span><span class="w"> </span><span class="nx">provider</span><span class="p">.</span><span class="nf">Shutdown</span><span class="p">(</span><span class="nx">ctx</span><span class="p">)</span><span class="w"> </span><span class="cp">//nolint:errcheck</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">meter</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">provider</span><span class="p">.</span><span class="nf">Meter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">doorOpens</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Int64Counter</span><span class="p">(</span><span class="s">&#34;door.opens&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Total number of times a door has been opened&#34;</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">doorOpens</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;door&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;front&#34;</span><span class="p">)))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">select</span><span class="w"> </span><span class="p">{}</span><span class="w"> </span><span class="c1">// sleep forever</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
</div>


## Counter {#counter}

A counter records monotonically increasing values. Prometheus `Counter` maps to
the OpenTelemetry `Counter` instrument.

- **Unit encoding**: Prometheus encodes the unit in the metric name
  (`hvac_on_seconds_total`). OpenTelemetry separates the name (`hvac.on`) from
  the unit (`s`), and the Prometheus exporter appends the unit suffix
  automatically.

### Counter

The Prometheus `Counter` includes two series-management features that have no
OpenTelemetry equivalent:

- **Series pre-initialization**: Prometheus clients can pre-initialize label
  value combinations so they appear in scrape output with value 0 before any
  recording occurs. OpenTelemetry has no equivalent; data points first appear on
  the first `add()` call.
- **Pre-bound series**: Prometheus clients let you cache the result of
  `labelValues()` to pre-bind to a specific label value combination. Subsequent
  calls go directly to the data point, skipping the internal series lookup.
  OpenTelemetry has no equivalent, though it is
  [under discussion](https://github.com/open-telemetry/opentelemetry-specification/issues/4126).

   <ul class="nav nav-tabs" id="tabs-2" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-02-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-02-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-02-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-02-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-02-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-02-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-2-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-02-00" role="tabpanel" aria-labelled-by="tabs-02-00-tab" tabindex="2">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusCounter.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Counter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusCounter</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">counterUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Counter</span><span class="w"> </span><span class="n">hvacOnTime</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Counter</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;hvac_on_seconds_total&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Total time the HVAC system has been running, in seconds&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Pre-bind to label value sets: subsequent calls go directly to the data point,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// skipping the internal series lookup.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">var</span><span class="w"> </span><span class="n">upstairs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">hvacOnTime</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">var</span><span class="w"> </span><span class="n">downstairs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">hvacOnTime</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">upstairs</span><span class="p">.</span><span class="na">inc</span><span class="p">(</span><span class="n">127</span><span class="p">.</span><span class="na">5</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">downstairs</span><span class="p">.</span><span class="na">inc</span><span class="p">(</span><span class="n">3600</span><span class="p">.</span><span class="na">0</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Pre-initialize zones so they appear in /metrics with value 0 on startup.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">hvacOnTime</span><span class="p">.</span><span class="na">initLabelValues</span><span class="p">(</span><span class="s">&#34;basement&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelCounter.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.DoubleCounter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelCounter</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c1">// Preallocate attribute keys and, when values are static, entire Attributes objects.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ZONE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">UPSTAIRS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ZONE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">DOWNSTAIRS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ZONE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">counterUsage</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// HVAC on-time is fractional — use ofDoubles() to get a DoubleCounter.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// No upfront label declaration: attributes are provided at record time.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">DoubleCounter</span><span class="w"> </span><span class="n">hvacOnTime</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">counterBuilder</span><span class="p">(</span><span class="s">&#34;hvac.on&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Total time the HVAC system has been running&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setUnit</span><span class="p">(</span><span class="s">&#34;s&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">ofDoubles</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">hvacOnTime</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">127</span><span class="p">.</span><span class="na">5</span><span class="p">,</span><span class="w"> </span><span class="n">UPSTAIRS</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">hvacOnTime</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">3600</span><span class="p">.</span><span class="na">0</span><span class="p">,</span><span class="w"> </span><span class="n">DOWNSTAIRS</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Key differences:</p>
<ul>
<li><code>inc(value)</code> → <code>add(value)</code>. Unlike Prometheus, OpenTelemetry requires an
explicit value — there is no bare <code>inc()</code> shorthand.</li>
<li>OpenTelemetry distinguishes <code>LongCounter</code> (integers, the default) from
<code>DoubleCounter</code> (via <code>.ofDoubles()</code>, for fractional values). Prometheus uses a
single <code>Counter</code> type.</li>
<li>Preallocate <code>AttributeKey</code> instances (always) and <code>Attributes</code> objects (when
values are static) to avoid per-call allocation on the hot path.</li>
</ul>

    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-02-01" role="tabpanel" aria-labelled-by="tabs-02-01-tab" tabindex="2">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_counter.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">hvacOnTime</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewCounterVec</span><span class="p">(</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">CounterOpts</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Name</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;hvac_on_seconds_total&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Help</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;Total time the HVAC system has been running, in seconds&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">},</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;zone&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">prometheusCounterUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nx">hvacOnTime</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Pre-bind to label value sets: subsequent calls avoid the series lookup.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">upstairs</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">hvacOnTime</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">downstairs</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">hvacOnTime</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">upstairs</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="mf">127.5</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">downstairs</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="mf">3600.0</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Pre-initialize a series so it appears in /metrics with value 0.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">hvacOnTime</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;basement&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_counter.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// Preallocate attribute options when values are static to avoid per-call allocation.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">zoneUpstairsOpts</span><span class="w">   </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">AddOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">zoneDownstairsOpts</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">AddOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">otelCounterUsage</span><span class="p">(</span><span class="nx">ctx</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// No upfront label declaration: attributes are provided at record time.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">hvacOnTime</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Float64Counter</span><span class="p">(</span><span class="s">&#34;hvac.on&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Total time the HVAC system has been running&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithUnit</span><span class="p">(</span><span class="s">&#34;s&#34;</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">hvacOnTime</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">127.5</span><span class="p">,</span><span class="w"> </span><span class="nx">zoneUpstairsOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">hvacOnTime</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">3600.0</span><span class="p">,</span><span class="w"> </span><span class="nx">zoneDownstairsOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Key differences:</p>
<ul>
<li><code>Add(value)</code> → <code>Add(ctx, value, metric.WithAttributes(...))</code>. All instrument
calls require a <code>context.Context</code> as the first argument.</li>
<li>In Go, <code>meter.Float64Counter</code> and <code>meter.Int64Counter</code> are separate methods.
Prometheus uses a single <code>Counter</code> type.</li>
<li>Instrument creation returns <code>(Instrument, error)</code> and the error must be
handled.</li>
</ul>

    </div>
</div>


### Callback (async) counter

Use a callback counter (an asynchronous counter in OpenTelemetry) when the total
is maintained by an external source — such as a device or runtime — and you want
to observe it at collection time rather than increment it yourself.

   <ul class="nav nav-tabs" id="tabs-3" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-03-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-03-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-03-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-03-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-03-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-03-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-3-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-03-00" role="tabpanel" aria-labelled-by="tabs-03-00-tab" tabindex="3">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusCounterCallback.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.CounterWithCallback</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusCounterCallback</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">counterCallbackUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Each zone has its own smart energy meter tracking cumulative joule totals.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Use a callback counter to report those values at scrape time without</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// maintaining separate counters in application code.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">CounterWithCallback</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;energy_consumed_joules_total&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Total energy consumed in joules&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">callback</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">callback</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">callback</span><span class="p">.</span><span class="na">call</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">callback</span><span class="p">.</span><span class="na">call</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelCounterCallback.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelCounterCallback</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ZONE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">UPSTAIRS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ZONE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">DOWNSTAIRS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ZONE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">counterCallbackUsage</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Each zone has its own smart energy meter tracking cumulative joule totals.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Use an asynchronous counter to report those values when a MetricReader</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// collects metrics, without maintaining separate counters in application code.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">counterBuilder</span><span class="p">(</span><span class="s">&#34;energy.consumed&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Total energy consumed&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">setUnit</span><span class="p">(</span><span class="s">&#34;J&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">ofDoubles</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">buildWithCallback</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">measurement</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">measurement</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="n">UPSTAIRS</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">measurement</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="n">DOWNSTAIRS</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">});</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Key differences:</p>
<ul>
<li>OpenTelemetry distinguishes integer and floating-point counters;
<code>.ofDoubles()</code> selects the floating-point variant. Prometheus
<code>CounterWithCallback</code> always uses floating-point values.</li>
</ul>

    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-03-01" role="tabpanel" aria-labelled-by="tabs-03-01-tab" tabindex="3">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_counter_callback.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">type</span><span class="w"> </span><span class="nx">energyCollector</span><span class="w"> </span><span class="kd">struct</span><span class="p">{</span><span class="w"> </span><span class="nx">desc</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Desc</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">newEnergyCollector</span><span class="p">()</span><span class="w"> </span><span class="o">*</span><span class="nx">energyCollector</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">energyCollector</span><span class="p">{</span><span class="nx">desc</span><span class="p">:</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewDesc</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="s">&#34;energy_consumed_joules_total&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="s">&#34;Total energy consumed in joules&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;zone&#34;</span><span class="p">},</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">)}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">energyCollector</span><span class="p">)</span><span class="w"> </span><span class="nf">Describe</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="kd">chan</span><span class="o">&lt;-</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Desc</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">energyCollector</span><span class="p">)</span><span class="w"> </span><span class="nf">Collect</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="kd">chan</span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Metric</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">MustNewConstMetric</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="p">,</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">CounterValue</span><span class="p">,</span><span class="w"> </span><span class="nf">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">MustNewConstMetric</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="p">,</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">CounterValue</span><span class="p">,</span><span class="w"> </span><span class="nf">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">prometheusCounterCallbackUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Each zone has its own smart energy meter tracking cumulative joule totals.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Implement prometheus.Collector to report those values at scrape time.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nf">newEnergyCollector</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_counter_callback.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">zoneUpstairs</span><span class="w">   </span><span class="p">=</span><span class="w"> </span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">zoneDownstairs</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">otelCounterCallbackUsage</span><span class="p">(</span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Each zone has its own smart energy meter tracking cumulative joule totals.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Use an observable counter to report those values when metrics are collected.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Float64ObservableCounter</span><span class="p">(</span><span class="s">&#34;energy.consumed&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Total energy consumed&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithUnit</span><span class="p">(</span><span class="s">&#34;J&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithFloat64Callback</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">_</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">o</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Float64Observer</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="nx">o</span><span class="p">.</span><span class="nf">Observe</span><span class="p">(</span><span class="nf">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">zoneUpstairs</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="nx">o</span><span class="p">.</span><span class="nf">Observe</span><span class="p">(</span><span class="nf">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">zoneDownstairs</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Key differences:</p>
<ul>
<li>The Prometheus example implements <code>prometheus.Collector</code> with <code>Describe</code> and
<code>Collect</code> methods to report labeled counter values.</li>
<li>OpenTelemetry distinguishes <code>Float64ObservableCounter</code> from
<code>Int64ObservableCounter</code>.</li>
</ul>

    </div>
</div>


## Gauge {#gauge}

A gauge records an instantaneous value that can increase or decrease. Prometheus
uses a single `Gauge` type for all such values, but OpenTelemetry distinguishes
between **additive** and **non-additive** values when choosing the right
instrument:

- **Non-additive** values cannot be meaningfully summed across instances — for
  example, temperature: adding readings from three room sensors doesn't produce
  a useful number. These map to OTel `Gauge` and `ObservableGauge`.
- **Additive** values can be meaningfully summed across instances — for example,
  connected device counts summed across service instances give a useful total.
  These map to OTel `UpDownCounter` and `ObservableUpDownCounter`.

This distinction applies to all gauge patterns: abs, inc and dec, and callback
variants. See the
[instrument selection guide](/docs/specs/otel/metrics/supplementary-guidelines/#instrument-selection)
for a fuller explanation.

### Gauge — abs

Use this pattern for values recorded as an absolute value — such as a
configuration value or a device setpoint. Prometheus `Gauge` maps to the
OpenTelemetry `Gauge` instrument.

   <ul class="nav nav-tabs" id="tabs-4" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-04-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-04-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-04-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-04-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-04-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-04-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-4-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-04-00" role="tabpanel" aria-labelled-by="tabs-04-00-tab" tabindex="4">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusGauge.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Gauge</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusGauge</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">gaugeUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Gauge</span><span class="w"> </span><span class="n">thermostatSetpoint</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Gauge</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;thermostat_setpoint_celsius&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Target temperature set on the thermostat&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">thermostatSetpoint</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">).</span><span class="na">set</span><span class="p">(</span><span class="n">22</span><span class="p">.</span><span class="na">5</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">thermostatSetpoint</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">).</span><span class="na">set</span><span class="p">(</span><span class="n">20</span><span class="p">.</span><span class="na">0</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelGauge.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.DoubleGauge</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelGauge</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c1">// Preallocate attribute keys and, when values are static, entire Attributes objects.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ZONE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">UPSTAIRS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ZONE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">DOWNSTAIRS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ZONE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">gaugeUsage</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">DoubleGauge</span><span class="w"> </span><span class="n">thermostatSetpoint</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">gaugeBuilder</span><span class="p">(</span><span class="s">&#34;thermostat.setpoint&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Target temperature set on the thermostat&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setUnit</span><span class="p">(</span><span class="s">&#34;Cel&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">thermostatSetpoint</span><span class="p">.</span><span class="na">set</span><span class="p">(</span><span class="n">22</span><span class="p">.</span><span class="na">5</span><span class="p">,</span><span class="w"> </span><span class="n">UPSTAIRS</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">thermostatSetpoint</span><span class="p">.</span><span class="na">set</span><span class="p">(</span><span class="n">20</span><span class="p">.</span><span class="na">0</span><span class="p">,</span><span class="w"> </span><span class="n">DOWNSTAIRS</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Key differences:</p>
<ul>
<li><code>set(value)</code> → <code>set(value, attributes)</code>. The method name is the same.</li>
<li>OpenTelemetry distinguishes <code>LongGauge</code> (integers, via <code>.ofLongs()</code>) from
<code>DoubleGauge</code> (the default). Prometheus uses a single <code>Gauge</code> type.</li>
<li>Preallocate <code>AttributeKey</code> instances (always) and <code>Attributes</code> objects (when
values are static) to avoid per-call allocation on the hot path.</li>
</ul>

    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-04-01" role="tabpanel" aria-labelled-by="tabs-04-01-tab" tabindex="4">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_gauge.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">thermostatSetpoint</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewGaugeVec</span><span class="p">(</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">GaugeOpts</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Name</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;thermostat_setpoint_celsius&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Help</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;Target temperature set on the thermostat&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">},</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;zone&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">prometheusGaugeUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nx">thermostatSetpoint</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">thermostatSetpoint</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">).</span><span class="nf">Set</span><span class="p">(</span><span class="mf">22.5</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">thermostatSetpoint</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">).</span><span class="nf">Set</span><span class="p">(</span><span class="mf">20.0</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_gauge.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// Preallocate attribute options when values are static to avoid per-call allocation.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">zoneUpstairsGaugeOpts</span><span class="w">   </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">RecordOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">zoneDownstairsGaugeOpts</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">RecordOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">otelGaugeUsage</span><span class="p">(</span><span class="nx">ctx</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">thermostatSetpoint</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Float64Gauge</span><span class="p">(</span><span class="s">&#34;thermostat.setpoint&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Target temperature set on the thermostat&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithUnit</span><span class="p">(</span><span class="s">&#34;Cel&#34;</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">thermostatSetpoint</span><span class="p">.</span><span class="nf">Record</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">22.5</span><span class="p">,</span><span class="w"> </span><span class="nx">zoneUpstairsGaugeOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">thermostatSetpoint</span><span class="p">.</span><span class="nf">Record</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">20.0</span><span class="p">,</span><span class="w"> </span><span class="nx">zoneDownstairsGaugeOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Key differences:</p>
<ul>
<li><code>Set(value)</code> → <code>Record(ctx, value, metric.WithAttributes(...))</code>.</li>
<li>In Go, <code>meter.Float64Gauge</code> and <code>meter.Int64Gauge</code> are separate methods.
Prometheus uses a single <code>Gauge</code> type.</li>
</ul>

    </div>
</div>


### Callback gauge — abs

Use a callback gauge (an asynchronous gauge in OpenTelemetry) when a
non-additive value is maintained externally — such as a sensor reading — and you
want to observe it at collection time rather than track it yourself.

   <ul class="nav nav-tabs" id="tabs-5" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-05-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-05-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-05-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-05-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-05-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-05-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-5-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-05-00" role="tabpanel" aria-labelled-by="tabs-05-00-tab" tabindex="5">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusGaugeCallback.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.GaugeWithCallback</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusGaugeCallback</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">gaugeCallbackUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Temperature sensors maintain their own readings in firmware.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Use a callback gauge to report those values at scrape time without</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// maintaining a separate gauge in application code.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">GaugeWithCallback</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;room_temperature_celsius&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Current temperature in the room&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;room&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">callback</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">callback</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">callback</span><span class="p">.</span><span class="na">call</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">livingRoomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="s">&#34;living_room&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">callback</span><span class="p">.</span><span class="na">call</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">bedroomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="s">&#34;bedroom&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelGaugeCallback.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelGaugeCallback</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ROOM</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;room&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">LIVING_ROOM</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ROOM</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;living_room&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">BEDROOM</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ROOM</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;bedroom&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">gaugeCallbackUsage</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Temperature sensors maintain their own readings in firmware.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Use an asynchronous gauge to report those values when a MetricReader</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// collects metrics, without maintaining separate gauges in application code.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">gaugeBuilder</span><span class="p">(</span><span class="s">&#34;room.temperature&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Current temperature in the room&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">setUnit</span><span class="p">(</span><span class="s">&#34;Cel&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">buildWithCallback</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">measurement</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">measurement</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">livingRoomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="n">LIVING_ROOM</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">measurement</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">bedroomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="n">BEDROOM</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">});</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-05-01" role="tabpanel" aria-labelled-by="tabs-05-01-tab" tabindex="5">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_gauge_callback.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">type</span><span class="w"> </span><span class="nx">temperatureCollector</span><span class="w"> </span><span class="kd">struct</span><span class="p">{</span><span class="w"> </span><span class="nx">desc</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Desc</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">newTemperatureCollector</span><span class="p">()</span><span class="w"> </span><span class="o">*</span><span class="nx">temperatureCollector</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">temperatureCollector</span><span class="p">{</span><span class="nx">desc</span><span class="p">:</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewDesc</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="s">&#34;room_temperature_celsius&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="s">&#34;Current temperature in the room&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;room&#34;</span><span class="p">},</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">)}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">temperatureCollector</span><span class="p">)</span><span class="w"> </span><span class="nf">Describe</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="kd">chan</span><span class="o">&lt;-</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Desc</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">temperatureCollector</span><span class="p">)</span><span class="w"> </span><span class="nf">Collect</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="kd">chan</span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Metric</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">MustNewConstMetric</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="p">,</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">GaugeValue</span><span class="p">,</span><span class="w"> </span><span class="nf">livingRoomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="s">&#34;living_room&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">MustNewConstMetric</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="p">,</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">GaugeValue</span><span class="p">,</span><span class="w"> </span><span class="nf">bedroomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="s">&#34;bedroom&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">prometheusGaugeCallbackUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Temperature sensors maintain their own readings in firmware.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Implement prometheus.Collector to report those values at scrape time.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nf">newTemperatureCollector</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_gauge_callback.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">roomLivingRoom</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;room&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;living_room&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">roomBedroom</span><span class="w">    </span><span class="p">=</span><span class="w"> </span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;room&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;bedroom&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">otelGaugeCallbackUsage</span><span class="p">(</span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Temperature sensors maintain their own readings in firmware.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Use an observable gauge to report those values when metrics are collected.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Float64ObservableGauge</span><span class="p">(</span><span class="s">&#34;room.temperature&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Current temperature in the room&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithUnit</span><span class="p">(</span><span class="s">&#34;Cel&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithFloat64Callback</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">_</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">o</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Float64Observer</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="nx">o</span><span class="p">.</span><span class="nf">Observe</span><span class="p">(</span><span class="nf">livingRoomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">roomLivingRoom</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="nx">o</span><span class="p">.</span><span class="nf">Observe</span><span class="p">(</span><span class="nf">bedroomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">roomBedroom</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Key differences:</p>
<ul>
<li>The Prometheus example implements <code>prometheus.Collector</code> with <code>Describe</code> and
<code>Collect</code> methods to report labeled gauge values.</li>
</ul>

    </div>
</div>


### Gauge — inc and dec

Prometheus `Gauge` supports incrementing and decrementing for values that change
gradually — such as the number of connected devices or active sessions.
OpenTelemetry `Gauge` records absolute values only; this pattern maps to the
OpenTelemetry `UpDownCounter` instrument.

   <ul class="nav nav-tabs" id="tabs-6" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-06-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-06-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-06-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-06-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-06-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-06-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-6-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-06-00" role="tabpanel" aria-labelled-by="tabs-06-00-tab" tabindex="6">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusUpDownCounter.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Gauge</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusUpDownCounter</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">upDownCounterUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Prometheus uses Gauge for values that can increase or decrease.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Gauge</span><span class="w"> </span><span class="n">devicesConnected</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Gauge</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;devices_connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Increment when a device connects, decrement when it disconnects.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="na">inc</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="na">inc</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="na">inc</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="na">dec</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelUpDownCounter.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.LongUpDownCounter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelUpDownCounter</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c1">// Preallocate attribute keys and, when values are static, entire Attributes objects.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">DEVICE_TYPE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">LOCK</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">upDownCounterUsage</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">LongUpDownCounter</span><span class="w"> </span><span class="n">devicesConnected</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">upDownCounterBuilder</span><span class="p">(</span><span class="s">&#34;devices.connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// add() accepts positive and negative values.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">1</span><span class="p">,</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">1</span><span class="p">,</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">1</span><span class="p">,</span><span class="w"> </span><span class="n">LOCK</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="o">-</span><span class="n">1</span><span class="p">,</span><span class="w"> </span><span class="n">LOCK</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Key differences:</p>
<ul>
<li><code>inc()</code> / <code>dec()</code> → <code>add(1)</code> / <code>add(-1)</code>. <code>add()</code> accepts both positive and
negative values.</li>
<li>The Prometheus type is <code>Gauge</code>; the OpenTelemetry type is <code>LongUpDownCounter</code>
(or <code>DoubleUpDownCounter</code> via <code>.ofDoubles()</code>).</li>
</ul>

    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-06-01" role="tabpanel" aria-labelled-by="tabs-06-01-tab" tabindex="6">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_up_down_counter.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// Prometheus uses Gauge for values that can increase or decrease.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">devicesConnected</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewGaugeVec</span><span class="p">(</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">GaugeOpts</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Name</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;devices_connected&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Help</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">},</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;device_type&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">prometheusUpDownCounterUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nx">devicesConnected</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Increment when a device connects, decrement when it disconnects.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="nf">Inc</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="nf">Inc</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="nf">Inc</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="nf">Dec</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_up_down_counter.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// Preallocate attribute options when values are static to avoid per-call allocation.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceThermostatAddOpts</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">AddOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceLockAddOpts</span><span class="w">       </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">AddOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">otelUpDownCounterUsage</span><span class="p">(</span><span class="nx">ctx</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Int64UpDownCounter</span><span class="p">(</span><span class="s">&#34;devices.connected&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Add() accepts positive and negative values.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nx">deviceThermostatAddOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nx">deviceThermostatAddOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nx">deviceLockAddOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nx">deviceLockAddOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Key differences:</p>
<ul>
<li><code>Inc()</code> / <code>Dec()</code> → <code>Add(ctx, 1, ...)</code> / <code>Add(ctx, -1, ...)</code>. <code>Add()</code> accepts
both positive and negative values.</li>
<li>The Prometheus type is <code>Gauge</code>; the OpenTelemetry type is <code>Int64UpDownCounter</code>
(or <code>Float64UpDownCounter</code> via <code>meter.Float64UpDownCounter</code>).</li>
</ul>

    </div>
</div>


### Callback gauge — inc and dec

Use a callback gauge (an asynchronous up-down counter in OpenTelemetry) when an
additive count that would otherwise be tracked with `inc()`/`dec()` is
maintained externally — such as by a device manager or connection pool — and you
want to observe it at collection time.

   <ul class="nav nav-tabs" id="tabs-7" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-07-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-07-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-07-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-07-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-07-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-07-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-7-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-07-00" role="tabpanel" aria-labelled-by="tabs-07-00-tab" tabindex="7">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusUpDownCounterCallback.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.GaugeWithCallback</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusUpDownCounterCallback</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">upDownCounterCallbackUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// The device manager maintains the count of connected devices.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Use a callback gauge to report that value at scrape time.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">GaugeWithCallback</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;devices_connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">callback</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">callback</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">callback</span><span class="p">.</span><span class="na">call</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">),</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">callback</span><span class="p">.</span><span class="na">call</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">),</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelUpDownCounterCallback.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelUpDownCounterCallback</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">DEVICE_TYPE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">LOCK</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">upDownCounterCallbackUsage</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// The device manager maintains the count of connected devices.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Use an asynchronous up-down counter to report that value when a MetricReader</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// collects metrics.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">upDownCounterBuilder</span><span class="p">(</span><span class="s">&#34;devices.connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">buildWithCallback</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">measurement</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">measurement</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">),</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">measurement</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">),</span><span class="w"> </span><span class="n">LOCK</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">});</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-07-01" role="tabpanel" aria-labelled-by="tabs-07-01-tab" tabindex="7">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_up_down_counter_callback.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">type</span><span class="w"> </span><span class="nx">deviceCountCollector</span><span class="w"> </span><span class="kd">struct</span><span class="p">{</span><span class="w"> </span><span class="nx">desc</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Desc</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">newDeviceCountCollector</span><span class="p">()</span><span class="w"> </span><span class="o">*</span><span class="nx">deviceCountCollector</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">deviceCountCollector</span><span class="p">{</span><span class="nx">desc</span><span class="p">:</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewDesc</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="s">&#34;devices_connected&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;device_type&#34;</span><span class="p">},</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">)}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">deviceCountCollector</span><span class="p">)</span><span class="w"> </span><span class="nf">Describe</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="kd">chan</span><span class="o">&lt;-</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Desc</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">deviceCountCollector</span><span class="p">)</span><span class="w"> </span><span class="nf">Collect</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="kd">chan</span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Metric</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">MustNewConstMetric</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="p">,</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">GaugeValue</span><span class="p">,</span><span class="w"> </span><span class="nb">float64</span><span class="p">(</span><span class="nf">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">)),</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">MustNewConstMetric</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="p">,</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">GaugeValue</span><span class="p">,</span><span class="w"> </span><span class="nb">float64</span><span class="p">(</span><span class="nf">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">)),</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">prometheusUpDownCounterCallbackUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// The device manager maintains the count of connected devices.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Implement prometheus.Collector to report those values at scrape time.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nf">newDeviceCountCollector</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_up_down_counter_callback.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceThermostat</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceLock</span><span class="w">       </span><span class="p">=</span><span class="w"> </span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">otelUpDownCounterCallbackUsage</span><span class="p">(</span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// The device manager maintains the count of connected devices.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Use an observable up-down counter to report that value when metrics are collected.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Int64ObservableUpDownCounter</span><span class="p">(</span><span class="s">&#34;devices.connected&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithInt64Callback</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">_</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">o</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Int64Observer</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="nx">o</span><span class="p">.</span><span class="nf">Observe</span><span class="p">(</span><span class="nb">int64</span><span class="p">(</span><span class="nf">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">)),</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">deviceThermostat</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="nx">o</span><span class="p">.</span><span class="nf">Observe</span><span class="p">(</span><span class="nb">int64</span><span class="p">(</span><span class="nf">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">)),</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">deviceLock</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Key differences:</p>
<ul>
<li>The Prometheus example implements <code>prometheus.Collector</code> with <code>Describe</code> and
<code>Collect</code> methods to report labeled gauge values.</li>
<li><code>Int64ObservableUpDownCounter</code> uses <code>metric.WithInt64Callback</code>.</li>
</ul>

    </div>
</div>


## Histogram {#histogram}

A histogram records the distribution of a set of measurements, tracking the
count of observations, their sum, and the number that fall within configurable
bucket boundaries.

Both Prometheus and OpenTelemetry support classic (explicit-bucket) histograms
and native (base2 exponential) histograms. Prometheus also has a `Summary` type,
which has no direct OTel equivalent — see [Summary](#summary) below.

Prometheus `Histogram` maps to the OpenTelemetry `Histogram` instrument.

### Classic (explicit) histogram

Both systems support classic histograms, where fixed bucket boundaries partition
observations into discrete ranges.

- **Bucket configuration**: Prometheus declares bucket boundaries on the
  instrument itself at creation time. In OpenTelemetry, bucket boundaries are
  set on the instrument as a hint that can be overridden or replaced by views
  configured at the SDK level. This separation keeps instrumentation code
  independent of collection configuration. If no boundaries are specified and no
  view is configured, the SDK uses a default set designed for millisecond-scale
  latency
  (`[0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000]`),
  which is likely wrong for second-scale measurements. Always provide boundaries
  or configure a view when migrating existing histograms.

   <ul class="nav nav-tabs" id="tabs-8" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-08-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-08-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-08-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-08-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-08-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-08-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-8-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-08-00" role="tabpanel" aria-labelled-by="tabs-08-00-tab" tabindex="8">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusHistogram.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Histogram</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusHistogram</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">histogramUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Histogram</span><span class="w"> </span><span class="n">deviceCommandDuration</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Histogram</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;device_command_duration_seconds&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">classicUpperBounds</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">1</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">25</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">5</span><span class="p">,</span><span class="w"> </span><span class="n">1</span><span class="p">.</span><span class="na">0</span><span class="p">,</span><span class="w"> </span><span class="n">2</span><span class="p">.</span><span class="na">5</span><span class="p">,</span><span class="w"> </span><span class="n">5</span><span class="p">.</span><span class="na">0</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="na">observe</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">35</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="na">observe</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">85</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelHistogram.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.DoubleHistogram</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">java.util.List</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelHistogram</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c1">// Preallocate attribute keys and, when values are static, entire Attributes objects.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">DEVICE_TYPE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">LOCK</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">histogramUsage</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// setExplicitBucketBoundariesAdvice() sets default boundaries as a hint to the SDK.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Views configured at the SDK level take precedence over this advice.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">DoubleHistogram</span><span class="w"> </span><span class="n">deviceCommandDuration</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">histogramBuilder</span><span class="p">(</span><span class="s">&#34;device.command.duration&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setUnit</span><span class="p">(</span><span class="s">&#34;s&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setExplicitBucketBoundariesAdvice</span><span class="p">(</span><span class="n">List</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">1</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">25</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">5</span><span class="p">,</span><span class="w"> </span><span class="n">1</span><span class="p">.</span><span class="na">0</span><span class="p">,</span><span class="w"> </span><span class="n">2</span><span class="p">.</span><span class="na">5</span><span class="p">,</span><span class="w"> </span><span class="n">5</span><span class="p">.</span><span class="na">0</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">35</span><span class="p">,</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">85</span><span class="p">,</span><span class="w"> </span><span class="n">LOCK</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Key differences:</p>
<ul>
<li><code>observe(value)</code> → <code>record(value, attributes)</code>.</li>
<li>OpenTelemetry distinguishes <code>LongHistogram</code> (integers, via <code>.ofLongs()</code>) from
<code>DoubleHistogram</code> (the default). Prometheus uses a single <code>Histogram</code> type.</li>
<li>Preallocate <code>AttributeKey</code> instances (always) and <code>Attributes</code> objects (when
values are static) to avoid per-call allocation on the hot path.</li>
<li>SDK views can override the boundaries set by
<code>setExplicitBucketBoundariesAdvice()</code>, and can also configure other aspects of
histogram collection such as attribute filtering, min/max recording, and
instrument renaming.</li>
</ul>

    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-08-01" role="tabpanel" aria-labelled-by="tabs-08-01-tab" tabindex="8">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_histogram.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">deviceCommandDuration</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewHistogramVec</span><span class="p">(</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">HistogramOpts</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Name</span><span class="p">:</span><span class="w">    </span><span class="s">&#34;device_command_duration_seconds&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Help</span><span class="p">:</span><span class="w">    </span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Buckets</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="kt">float64</span><span class="p">{</span><span class="mf">0.1</span><span class="p">,</span><span class="w"> </span><span class="mf">0.25</span><span class="p">,</span><span class="w"> </span><span class="mf">0.5</span><span class="p">,</span><span class="w"> </span><span class="mf">1.0</span><span class="p">,</span><span class="w"> </span><span class="mf">2.5</span><span class="p">,</span><span class="w"> </span><span class="mf">5.0</span><span class="p">},</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">},</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;device_type&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">prometheusHistogramUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nx">deviceCommandDuration</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="nf">Observe</span><span class="p">(</span><span class="mf">0.35</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="nf">Observe</span><span class="p">(</span><span class="mf">0.85</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_histogram.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// Preallocate attribute options when values are static to avoid per-call allocation.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceThermostatOpts</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">RecordOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceLockOpts</span><span class="w">       </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">RecordOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">otelHistogramUsage</span><span class="p">(</span><span class="nx">ctx</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// WithExplicitBucketBoundaries sets default boundaries as a hint to the SDK.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Views configured at the SDK level take precedence over this hint.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Float64Histogram</span><span class="p">(</span><span class="s">&#34;device.command.duration&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithUnit</span><span class="p">(</span><span class="s">&#34;s&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithExplicitBucketBoundaries</span><span class="p">(</span><span class="mf">0.1</span><span class="p">,</span><span class="w"> </span><span class="mf">0.25</span><span class="p">,</span><span class="w"> </span><span class="mf">0.5</span><span class="p">,</span><span class="w"> </span><span class="mf">1.0</span><span class="p">,</span><span class="w"> </span><span class="mf">2.5</span><span class="p">,</span><span class="w"> </span><span class="mf">5.0</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">.</span><span class="nf">Record</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">0.35</span><span class="p">,</span><span class="w"> </span><span class="nx">deviceThermostatOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">.</span><span class="nf">Record</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">0.85</span><span class="p">,</span><span class="w"> </span><span class="nx">deviceLockOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Key differences:</p>
<ul>
<li><code>Observe(value)</code> → <code>Record(ctx, value, metric.WithAttributes(...))</code>.</li>
<li>In Go, <code>metric.WithExplicitBucketBoundaries(...)</code> is variadic (not a slice).
Prometheus uses a <code>Buckets</code> field in <code>HistogramOpts</code>.</li>
<li>SDK views can override the boundaries set by <code>WithExplicitBucketBoundaries()</code>,
and can also configure other aspects of histogram collection such as attribute
filtering, min/max recording, and instrument renaming.</li>
</ul>

    </div>
</div>


### Native (base2 exponential) histogram

Both systems support native (base2 exponential) histograms, which automatically
adjust bucket boundaries to cover the observed range without requiring manual
configuration.

- **Format selection**: Prometheus instruments can emit classic format only,
  native format only, or both simultaneously — enabling gradual migration
  without instrumentation changes. In OpenTelemetry, format selection is
  configured outside instrumentation code — on the exporter or via a view — so
  instrumentation code requires no changes either way.
- **Instrumentation code**: The OpenTelemetry instrumentation code is identical
  for classic and native histograms. The same `record()` calls produce either
  format depending on how the SDK is configured.

   <ul class="nav nav-tabs" id="tabs-9" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-09-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-09-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-09-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-09-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-09-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-09-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-9-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-09-00" role="tabpanel" aria-labelled-by="tabs-09-00-tab" tabindex="9">
        <p>Prometheus</p>
<p>In Prometheus, the histogram format is controlled at instrument creation time.
The example below uses <code>.nativeOnly()</code> to restrict to native format; omitting it
would emit both classic and native formats simultaneously:</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusHistogramNative.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Histogram</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusHistogramNative</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">nativeHistogramUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Histogram</span><span class="w"> </span><span class="n">deviceCommandDuration</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Histogram</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;device_command_duration_seconds&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">nativeOnly</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="na">observe</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">35</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="na">observe</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">85</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-09-01" role="tabpanel" aria-labelled-by="tabs-09-01-tab" tabindex="9">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<p>In Prometheus, setting <code>NativeHistogramBucketFactor</code> enables native histograms
alongside the classic bucket configuration — both formats are reported
simultaneously:</p>
<?code-excerpt "prometheus_histogram_native.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">nativeDeviceCommandDuration</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewHistogramVec</span><span class="p">(</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">HistogramOpts</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Name</span><span class="p">:</span><span class="w">                        </span><span class="s">&#34;device_command_duration_seconds&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Help</span><span class="p">:</span><span class="w">                        </span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">NativeHistogramBucketFactor</span><span class="p">:</span><span class="w"> </span><span class="mf">1.1</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">},</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;device_type&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">nativeHistogramUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nx">nativeDeviceCommandDuration</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">nativeDeviceCommandDuration</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="nf">Observe</span><span class="p">(</span><span class="mf">0.35</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">nativeDeviceCommandDuration</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="nf">Observe</span><span class="p">(</span><span class="mf">0.85</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Key differences:</p>
<ul>
<li><code>NativeHistogramBucketFactor</code> must be set to a value greater than 1.0 to
enable native histograms in Go — it is not optional. Setting it to 0 (the zero
value) disables native histograms entirely. The value controls the maximum
ratio between consecutive bucket boundaries; smaller values give finer
resolution at the cost of more buckets. To approximate the same bucket density
as the commonly used value of <code>1.1</code>, set <code>MaxScale: 3</code> on
<code>AggregationBase2ExponentialHistogram</code>.</li>
</ul>

    </div>
</div>


In OpenTelemetry, the instrumentation code is identical to the classic histogram
case. The base2 exponential format is configured separately, outside the
instrumentation layer.

The preferred approach is to configure it on the metric exporter. This applies
to all histograms exported through that exporter without touching
instrumentation code:

   <ul class="nav nav-tabs" id="tabs-10" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-10-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-10-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-10-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-10-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-10-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-10-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-10-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-10-00" role="tabpanel" aria-labelled-by="tabs-10-00-tab" tabindex="10">
        <?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/OtelHistogramExponentialExporter.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.Aggregation</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.InstrumentType</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelHistogramExponentialExporter</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">static</span><span class="w"> </span><span class="n">OtlpHttpMetricExporter</span><span class="w"> </span><span class="nf">createExporter</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Configure the exporter to use exponential histograms for all histogram instruments.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// This is the preferred approach — it applies globally without modifying instrumentation code.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">OtlpHttpMetricExporter</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">setEndpoint</span><span class="p">(</span><span class="s">&#34;http://localhost:4318&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">setDefaultAggregationSelector</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">DefaultAggregationSelector</span><span class="p">.</span><span class="na">getDefault</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">.</span><span class="na">with</span><span class="p">(</span><span class="n">InstrumentType</span><span class="p">.</span><span class="na">HISTOGRAM</span><span class="p">,</span><span class="w"> </span><span class="n">Aggregation</span><span class="p">.</span><span class="na">base2ExponentialBucketHistogram</span><span class="p">()))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-10-01" role="tabpanel" aria-labelled-by="tabs-10-01-tab" tabindex="10">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<?code-excerpt "otel_histogram_exponential_exporter.go" region="createExponentialExporter"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">sdkmetric</span><span class="w"> </span><span class="s">&#34;go.opentelemetry.io/otel/sdk/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">createExponentialExporter</span><span class="p">(</span><span class="nx">ctx</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="nx">otlpmetrichttp</span><span class="p">.</span><span class="nx">Exporter</span><span class="p">,</span><span class="w"> </span><span class="kt">error</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Configure the exporter to use exponential histograms for all histogram instruments.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// This is the preferred approach — it applies globally without modifying instrumentation code.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="nx">otlpmetrichttp</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">otlpmetrichttp</span><span class="p">.</span><span class="nf">WithAggregationSelector</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">ik</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">InstrumentKind</span><span class="p">)</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">Aggregation</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">if</span><span class="w"> </span><span class="nx">ik</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">InstrumentKindHistogram</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">				</span><span class="k">return</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">AggregationBase2ExponentialHistogram</span><span class="p">{}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nf">DefaultAggregationSelector</span><span class="p">(</span><span class="nx">ik</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
</div>


For more granular control — for example, to use base2 exponential histograms for
specific instruments while keeping explicit buckets for others — configure a
view instead:

   <ul class="nav nav-tabs" id="tabs-11" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-11-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-11-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-11-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-11-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-11-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-11-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-11-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-11-00" role="tabpanel" aria-labelled-by="tabs-11-00-tab" tabindex="11">
        <?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/OtelHistogramExponentialView.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.Aggregation</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.InstrumentSelector</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.SdkMeterProvider</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.View</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelHistogramExponentialView</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">static</span><span class="w"> </span><span class="n">SdkMeterProvider</span><span class="w"> </span><span class="nf">createMeterProvider</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Use a view for per-instrument control — select a specific instrument by name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// to use exponential histograms while keeping explicit buckets for others.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">SdkMeterProvider</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">registerView</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">InstrumentSelector</span><span class="p">.</span><span class="na">builder</span><span class="p">().</span><span class="na">setName</span><span class="p">(</span><span class="s">&#34;device.command.duration&#34;</span><span class="p">).</span><span class="na">build</span><span class="p">(),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">View</span><span class="p">.</span><span class="na">builder</span><span class="p">().</span><span class="na">setAggregation</span><span class="p">(</span><span class="n">Aggregation</span><span class="p">.</span><span class="na">base2ExponentialBucketHistogram</span><span class="p">()).</span><span class="na">build</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-11-01" role="tabpanel" aria-labelled-by="tabs-11-01-tab" tabindex="11">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<?code-excerpt "otel_histogram_exponential.go" region="createExponentialView"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">createExponentialView</span><span class="p">()</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">View</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Use a view for per-instrument control — select a specific instrument by name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// to use exponential histograms while keeping explicit buckets for others.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nf">NewView</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">Instrument</span><span class="p">{</span><span class="nx">Name</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;device.command.duration&#34;</span><span class="p">},</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">Stream</span><span class="p">{</span><span class="nx">Aggregation</span><span class="p">:</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">AggregationBase2ExponentialHistogram</span><span class="p">{}!},</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
</div>


### Summary {#summary}

Prometheus `Summary` computes quantiles client-side at scrape time and exposes
them as labeled time series (for example, `{quantile="0.95"}`). OpenTelemetry
has no direct equivalent.

For quantile estimation, a **base2 exponential histogram** is the recommended
replacement: it automatically adjusts bucket boundaries to cover the observed
range, and `histogram_quantile()` in PromQL can compute quantiles with bounded
errors at query time. Unlike `Summary`, the results can be aggregated across
instances. See
[Native (base2 exponential) histogram](#native-base2-exponential-histogram).

If you only need count and sum — not quantiles — a histogram with no explicit
bucket boundaries captures those statistics with minimal overhead. The examples
below show this simpler approach.

   <ul class="nav nav-tabs" id="tabs-12" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-12-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-12-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-12-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-12-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-12-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-12-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-12-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-12-00" role="tabpanel" aria-labelled-by="tabs-12-00-tab" tabindex="12">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusSummary.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Summary</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusSummary</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">summaryUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Summary</span><span class="w"> </span><span class="n">deviceCommandDuration</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Summary</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;device_command_duration_seconds&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">quantile</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">5</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">05</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">quantile</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">95</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">01</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">quantile</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">99</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">001</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="na">observe</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">35</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="na">observe</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">85</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelHistogramAsSummary.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.DoubleHistogram</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">java.util.List</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelHistogramAsSummary</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">DEVICE_TYPE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">LOCK</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">summaryReplacement</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// No explicit bucket boundaries: captures count and sum, a good stand-in for most</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Summary use cases. For quantile estimation, add boundaries that bracket your thresholds.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">DoubleHistogram</span><span class="w"> </span><span class="n">deviceCommandDuration</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">histogramBuilder</span><span class="p">(</span><span class="s">&#34;device.command.duration&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setUnit</span><span class="p">(</span><span class="s">&#34;s&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setExplicitBucketBoundariesAdvice</span><span class="p">(</span><span class="n">List</span><span class="p">.</span><span class="na">of</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">35</span><span class="p">,</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">85</span><span class="p">,</span><span class="w"> </span><span class="n">LOCK</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-12-01" role="tabpanel" aria-labelled-by="tabs-12-01-tab" tabindex="12">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_summary.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">summaryDeviceCommandDuration</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewSummaryVec</span><span class="p">(</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">SummaryOpts</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Name</span><span class="p">:</span><span class="w">       </span><span class="s">&#34;device_command_duration_seconds&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Help</span><span class="p">:</span><span class="w">       </span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Objectives</span><span class="p">:</span><span class="w"> </span><span class="kd">map</span><span class="p">[</span><span class="kt">float64</span><span class="p">]</span><span class="kt">float64</span><span class="p">{</span><span class="mf">0.5</span><span class="p">:</span><span class="w"> </span><span class="mf">0.05</span><span class="p">,</span><span class="w"> </span><span class="mf">0.95</span><span class="p">:</span><span class="w"> </span><span class="mf">0.01</span><span class="p">,</span><span class="w"> </span><span class="mf">0.99</span><span class="p">:</span><span class="w"> </span><span class="mf">0.001</span><span class="p">},</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">},</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;device_type&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">summaryUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nx">summaryDeviceCommandDuration</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">summaryDeviceCommandDuration</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="nf">Observe</span><span class="p">(</span><span class="mf">0.35</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">summaryDeviceCommandDuration</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="nf">Observe</span><span class="p">(</span><span class="mf">0.85</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_histogram_as_summary.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// Preallocate attribute options when values are static to avoid per-call allocation.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">summaryThermostatOpts</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">RecordOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">summaryLockOpts</span><span class="w">       </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">RecordOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">summaryReplacement</span><span class="p">(</span><span class="nx">ctx</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// No explicit bucket boundaries: captures count and sum only.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// For quantile estimation, prefer a base2 exponential histogram instead.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Float64Histogram</span><span class="p">(</span><span class="s">&#34;device.command.duration&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithUnit</span><span class="p">(</span><span class="s">&#34;s&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithExplicitBucketBoundaries</span><span class="p">())</span><span class="w"> </span><span class="c1">// no boundaries</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">.</span><span class="nf">Record</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">0.35</span><span class="p">,</span><span class="w"> </span><span class="nx">summaryThermostatOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">.</span><span class="nf">Record</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">0.85</span><span class="p">,</span><span class="w"> </span><span class="nx">summaryLockOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
</div>
