OpenTelemetry metrics: instruments, Views, and export semantics
Choose metric instruments, control attributes and histogram aggregation with Views, and verify temporality and OTLP or Prometheus export.
OpenTelemetry metrics turn measurements into aggregated data points that a backend can use for rates, distributions, capacity views, and alerts. The instrument describes the measurement's meaning; the SDK aggregates it; a reader collects the result for export or scraping.
The most useful first decision is whether the application reports a change, an accumulated total, a current value, or a distribution of observations. Choosing an instrument by its name alone can produce plausible numbers with the wrong meaning.
Choose an instrument that matches the measurement
These four common choices cover many application needs:
| Instrument | What the application reports | Examples |
|---|---|---|
| Counter | Nonnegative increments | Requests completed, errors observed, bytes transferred |
| UpDownCounter | Positive or negative changes to an additive quantity | Connections opened/closed, tasks started/completed |
| Histogram | Individual observations to summarize as a distribution | Request durations, response sizes |
| Observable Gauge | A current non-additive value obtained in a callback | Temperature, utilization ratio |
The API also defines observable counters and observable up-down counters, and a synchronous Gauge where supported by the implementation. An observable counter can report a cumulative monotonic total from an existing subsystem. An observable up-down counter can report an additive current quantity such as memory usage. Check the language API and version rather than assuming it exposes only the four instruments in the table.
For queue depth, either record enqueue/dequeue changes with an up-down counter or observe the current additive count with an observable up-down counter, according to how the application obtains the value. A gauge is suitable when summing values across the relevant attributes would not make sense.
A counter's accumulated value can reset when its producer restarts. That is normal and must be represented and interpreted with the correct start time and temporality. A gauge does not create restart behavior; using it for a cumulative counter instead loses useful monotonic-sum semantics. See the metrics API specification.
Separate instruments from exported data-point types
An instrument records measurements. SDK aggregation produces data such as sums, gauges, explicit-bucket histograms, or exponential histograms. The exported record contains metadata and attributes needed to interpret that result.
A histogram typically preserves a count, sum, and bucket distribution rather than every individual observation. Explicit boundaries divide values into configured ranges. Exponential histograms use a different bucket representation that can cover a wide range with controlled resolution. Support for producing, exporting, converting, and querying each representation varies across SDKs and backends.
Metric aggregation usually happens in the SDK before export, reducing the number of individual observations sent over the network. More distinct attribute combinations still mean more streams and memory. Compact points do not make unbounded cardinality cheap.
Use Views to control the exported streams
A View selects instruments and can customize the stream name, retained attribute keys, and compatible aggregation. Filtering attributes at this stage prevents unwanted dimensions from creating separate exported series.
For example, preserve a bounded route template and drop a unique request ID. This does not remove the identifier from logs, traces, or other metric streams; apply the rule to every relevant path. Avoid passing sensitive identifiers to instrumentation in the first place where they are unnecessary.
Some SDKs support alternative aggregations, including a sum for histogram measurements. That retains a total while discarding the count/distribution needed for many latency questions; it is not a generic replacement for a histogram. Choose an aggregation based on the query you need and confirm implementation compatibility.
The following standalone Python example uses an in-memory reader to inspect a histogram. It does not send data to a backend:
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import InMemoryMetricReader
from opentelemetry.sdk.metrics.view import View, ExplicitBucketHistogramAggregation
from opentelemetry.sdk.resources import Resource
reader = InMemoryMetricReader()
provider = MeterProvider(
resource=Resource.create({"service.name": "order-service"}),
metric_readers=[reader],
views=[View(
instrument_name="example.request.duration",
attribute_keys={"http.route"},
aggregation=ExplicitBucketHistogramAggregation(
boundaries=[0.1, 0.5, 1.0, 2.0]
),
)],
)
meter = provider.get_meter("example.metrics")
duration = meter.create_histogram("example.request.duration", unit="s")
try:
for seconds in [0.05, 0.2, 1.2]:
duration.record(seconds, {
"http.route": "/orders/{id}",
"request_id": "example-request",
})
data = reader.get_metrics_data()
print(data.to_json())
finally:
provider.shutdown()
Install a compatible opentelemetry-sdk package in a virtual environment and lock its version. The expected stream contains three observations, a sum of about 1.45 seconds, and only http.route as a data-point attribute. The request ID is included only to demonstrate the View filter; omit it at the recording site in real code if no stream needs it.
The metric name is an example namespace rather than a claim that this implements the full standard HTTP instrumentation contract. A standardized metric such as http.server.request.duration has its own required unit and attribute rules. See semantic conventions.
Understand temporality before calculating rates
A cumulative sum covers the interval from a start time to the current collection time. A delta sum covers a particular collection interval. Both need the appropriate producer identity and timestamps for a backend to handle resets, gaps, and aggregation correctly.
A start timestamp alone does not guarantee a platform will calculate the right rate. Verify the exporter's temporality, receiver conversion, backend support, and query function. Treat a restarted service instance separately where required. Do not add a delta and a cumulative value as if they described the same interval.
Similarly, a histogram quantile is an estimate based on the retained buckets and the backend's query semantics. Do not average independently calculated percentiles from different instances and call the result the overall percentile.
Choose a push or pull path
OTLP push uses a periodic exporting reader to send aggregated points to a Collector or compatible DataKit input. This can fit dynamic service instances without requiring a metrics endpoint to be scraped individually. Export failures, buffering, and shutdown remain operational concerns.
Prometheus pull exposes metrics through a supported reader/exporter endpoint and lets a scraper request them. This fits existing Prometheus infrastructure, but endpoint discovery, network access, scrape health, and model conversion need to work.
For Guance, configure either the DataKit OpenTelemetry input with the correct metric protocol and route, or the Prometheus collector with the actual exposed endpoint. An OTLP trace endpoint does not automatically establish the metric route.
Start with a counter that receives known increments. Check its name, attributes, unit, value, temporality, and behavior after a restart. Then test a histogram and any observable instruments used by the application. Verify that conversions preserve the information the intended dashboards and alerts need.
Common questions
Can OpenTelemetry and Prometheus metrics be converted?
There are supported integration and conversion paths, but the models are not identical. Naming, units, resource attributes, temporality, and histogram representation can change or require configuration. Confirm the chosen receiver/exporter and DataKit version rather than assuming a lossless round trip. The OTel versus Prometheus metrics guide is currently in Chinese.
How should histogram boundaries be chosen?
Use the measurement's unit and the thresholds the team needs to evaluate. A duration measured in seconds needs boundaries expressed in seconds. Generic SDK defaults are not guaranteed to fit web latency, and minute-long inference operations may need a different range or an exponential representation. Test the backend's support and query behavior before changing a deployed histogram schema.
What collection interval should we use?
The SDK specification gives a periodic exporting reader a default interval of 60 seconds, but implementation and auto-configuration defaults should be checked. A 15–30 second interval may expose shorter fluctuations at the cost of more frequent collection and export. Export interval is not the same as tracing sample rate or histogram measurement frequency. Cost does not necessarily scale linearly because aggregation, series counts, batching, and billing units differ.
Do SDK and backend aggregation conflict?
They serve different stages. The SDK reduces measurements to points; the backend can aggregate those points across time and compatible dimensions. The operation is valid only when units, temporality, instrument semantics, and histogram schemas are compatible. Backend aggregation cannot reconstruct detail the SDK has discarded.
See the metrics SDK specification and the SDK guide. Related articles on high cardinality, sensitive-data handling, and OpenTelemetry versus Prometheus are currently in Chinese.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan