Histogram metrics distribute values into predefined buckets. The OpenTelemetry SDK provides default bucket boundaries (in seconds):
[0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10]
These defaults work well for measuring latencies in seconds, but if your metric uses different units or value ranges (for example, response sizes in bytes or durations in milliseconds), you should define custom bucket boundaries that match your data.
How to Configure Custom Buckets
Custom buckets are configured in your application code when you initialize the OpenTelemetry MeterProvider. You define a View that overrides the default bucket boundaries for histogram instruments.
Python Example
The following example uses the OpenTelemetry Python SDK to configure custom histogram buckets:
from opentelemetry.metrics import set_meter_provider
from opentelemetry.sdk.metrics import MeterProvider, Histogram
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
from opentelemetry.sdk.metrics.view import ExplicitBucketHistogramAggregation, View
# Define custom bucket boundaries (in milliseconds in this example).
# Choose boundaries that match the unit you use when recording the metric.
boundaries = [0.0, 100.0, 250.0, 500.0, 750.0, 1000.0, 2500.0, 5000.0,
7500.0, 10000.0, 15000.0, 20000.0, 30000.0, 45000.0, 60000.0]
# Option 1: Apply custom buckets to ALL histogram metrics
custom_buckets_for_all_histograms = View(
instrument_type=Histogram,
aggregation=ExplicitBucketHistogramAggregation(boundaries=boundaries),
)
# Option 2: Apply custom buckets to a specific histogram metric by name
custom_buckets_for_specific_metric = View(
instrument_name="my-histogram",
aggregation=ExplicitBucketHistogramAggregation(boundaries=boundaries),
)
reader = PeriodicExportingMetricReader(OTLPMetricExporter())
set_meter_provider(
MeterProvider(
metric_readers=[reader],
views=[custom_buckets_for_all_histograms],
)
)
Choosing the Right Boundaries
- Match the unit: If your code records values in milliseconds, define boundaries in milliseconds.
- Cover the expected range: Include boundaries that capture both typical and tail-end values for your metric.
- Avoid too many buckets: Each bucket adds a time series. Keep boundaries to 10–20 for a good balance between granularity and cost.