Skip to content

Add preview support for bound instruments #4042

Open
lalitb wants to merge 2 commits intoopen-telemetry:mainfrom
lalitb:lalitb/bound-sync-instruments-preview
Open

Add preview support for bound instruments #4042
lalitb wants to merge 2 commits intoopen-telemetry:mainfrom
lalitb:lalitb/bound-sync-instruments-preview

Conversation

@lalitb
Copy link
Copy Markdown
Member

@lalitb lalitb commented May 2, 2026

Summary

Related specs PR - open-telemetry/opentelemetry-specification#5050

Adds experimental bound synchronous metric instruments for metrics ABI v2. Bound instruments let callers bind a fixed attribute set once, then record repeated measurements through a bound handle:

auto counter = meter->CreateDoubleCounter("http.server.requests");

std::map<std::string, std::string> checkout_200_attrs = {
    {"route", "/checkout"},
    {"status", "200"},
};

std::map<std::string, std::string> checkout_500_attrs = {
    {"route", "/checkout"},
    {"status", "500"},
};

auto checkout_200 = counter->Bind(
    opentelemetry::common::KeyValueIterableView<std::map<std::string, std::string>>(
        checkout_200_attrs));

auto checkout_500 = counter->Bind(
    opentelemetry::common::KeyValueIterableView<std::map<std::string, std::string>>(
        checkout_500_attrs));

checkout_200->Add(1);
checkout_500->Add(1);

Both bound handles record to the same metric instrument, http.server.requests, with different pre-bound attribute sets. This avoids repeated per-call attribute processing and hashmap lookup for hot paths that reuse the same attribute set.

Scope

This PR intentionally keeps the preview surface narrow:

  • Counter: BoundCounter + Counter::Bind(...)
  • Histogram: BoundHistogram + Histogram::Bind(...)
  • SDK support for bound sync metric storage
  • multi-storage fanout support
  • noop support
  • bound-vs-unbound benchmark coverage
  • Bazel and CMake feature-gate support

Not included in this preview:

  • UpDownCounter bind support
  • Gauge bind support
  • Context-bearing bound recording overloads
  • exemplar parity for bound recordings

Those are left as follow-ups while the spec is still being finalized.

Feature Gate

The feature is disabled by default.

CMake:

  -DWITH_ABI_VERSION_2=ON
  -DWITH_METRICS_BOUND_INSTRUMENTS_PREVIEW=ON

Bazel:

  --//api:abi_version_no=2
  --//api:with_metrics_bound_instruments_preview=true

CMake rejects enabling WITH_METRICS_BOUND_INSTRUMENTS_PREVIEW without ABI v2.

Bound code is guarded by: OPENTELEMETRY_HAVE_METRICS_BOUND_INSTRUMENTS_PREVIEW

Implementation Notes

  • Bound handles use the same metric name, description, unit, views, and export pipeline as the original instrument.
  • Attributes are processed once at bind time, then reused for later recordings.
  • Bound and unbound recordings with the same attributes are merged into the same exported datapoint.
  • Bound and unbound recordings share the same cardinality limit and overflow behavior.
  • Delta and cumulative temporality are handled by the existing metrics collection path.
  • Bound handles are safe to call after SDK storage is gone, but those late recordings are not exported.

Benchmark

Benchmark Mean Median StdDev
BM_UnboundFixedAttrsCounter 262 ns 262 ns 1.19 ns
BM_BoundFixedAttrsCounter 14.3 ns 14.9 ns 0.74 ns

Bound recording is about 18.3x faster by mean for repeated recordings with the same fixed attribute set.
Env: Ubuntu 24.04 · GCC 13.3 · AMD EPYC 9V45 (32C/64T) · 251 GiB RAM.

For significant contributions please make sure you have completed the following items:

  • CHANGELOG.md updated for non-trivial changes
  • Unit tests have been added
  • Changes in public API reviewed

@lalitb lalitb changed the title Lalitb/bound sync instruments preview Add preview support for bound sync metric instruments May 2, 2026
@lalitb lalitb changed the title Add preview support for bound sync metric instruments [WIP] Add preview support for bound sync metric instruments May 2, 2026
@lalitb lalitb changed the title [WIP] Add preview support for bound sync metric instruments [WIP] Add preview support for bound instruments May 2, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 2, 2026

Codecov Report

❌ Patch coverage is 67.47573% with 67 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.87%. Comparing base (99300d1) to head (6f91811).

Files with missing lines Patch % Lines
sdk/src/metrics/sync_instruments.cc 0.00% 56 Missing ⚠️
...telemetry/sdk/metrics/state/multi_metric_storage.h 78.95% 4 Missing ⚠️
sdk/src/metrics/state/sync_metric_storage.cc 96.39% 3 Missing ⚠️
...e/opentelemetry/sdk/metrics/state/metric_storage.h 50.00% 2 Missing ⚠️
...ntelemetry/sdk/metrics/state/sync_metric_storage.h 93.75% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4042      +/-   ##
==========================================
- Coverage   82.04%   81.87%   -0.16%     
==========================================
  Files         385      385              
  Lines       15896    16103     +207     
==========================================
+ Hits        13040    13183     +143     
- Misses       2856     2920      +64     
Files with missing lines Coverage Δ
api/include/opentelemetry/metrics/noop.h 74.03% <100.00%> (+3.02%) ⬆️
...i/include/opentelemetry/metrics/sync_instruments.h 100.00% <100.00%> (ø)
...clude/opentelemetry/sdk/metrics/sync_instruments.h 100.00% <ø> (ø)
...e/opentelemetry/sdk/metrics/state/metric_storage.h 80.00% <50.00%> (-20.00%) ⬇️
...ntelemetry/sdk/metrics/state/sync_metric_storage.h 82.50% <93.75%> (+4.73%) ⬆️
sdk/src/metrics/state/sync_metric_storage.cc 96.74% <96.39%> (-3.26%) ⬇️
...telemetry/sdk/metrics/state/multi_metric_storage.h 90.25% <78.95%> (-9.75%) ⬇️
sdk/src/metrics/sync_instruments.cc 54.72% <0.00%> (-11.69%) ⬇️

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@lalitb lalitb force-pushed the lalitb/bound-sync-instruments-preview branch 4 times, most recently from 7668547 to 1fc14cf Compare May 6, 2026 02:16
@lalitb lalitb force-pushed the lalitb/bound-sync-instruments-preview branch from 1fc14cf to 3690e7e Compare May 6, 2026 02:27
// This macro affects SDK class layout/vtables and MUST match between the SDK
// library build and consumer translation units.
#if OPENTELEMETRY_ABI_VERSION_NO >= 2 && defined(ENABLE_METRICS_BOUND_INSTRUMENTS_PREVIEW)
# define OPENTELEMETRY_HAVE_METRICS_BOUND_INSTRUMENTS_PREVIEW 1
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept this derived preview macro in version.h so API and SDK headers use one consistent guard for the ABI-v2 + preview-flag combination. This is temporary while bound instruments are experimental; once the API is stabilized, we can remove the preview flag and keep the surface under the normal ABI rules.

@lalitb lalitb marked this pull request as ready for review May 6, 2026 02:33
@lalitb lalitb requested a review from a team as a code owner May 6, 2026 02:33
@lalitb
Copy link
Copy Markdown
Member Author

lalitb commented May 6, 2026

this is ready for review now. This is preview-only and gated behind ABI v2 plus ENABLE_METRICS_BOUND_INSTRUMENTS_PREVIEW, so existing users should not see the new API unless they opt in. The scope is Counter/Histogram bound handles for now, with the preview flag left in place while the API/spec settles.

@lalitb lalitb changed the title [WIP] Add preview support for bound instruments Add preview support for bound instruments May 6, 2026
@lalitb
Copy link
Copy Markdown
Member Author

lalitb commented May 6, 2026

I also did a local throwaway stress test on a 64-core test VM to sanity-check the expected performance shape using the stress framework #3241

The result matches the design expectation: bound instruments help most when the workload records repeatedly to stable attribute sets, because the hot path avoids repeated attribute processing and hashmap lookup. The benefit is small when all threads record to the same single series, since the same bound cell becomes the contention point. With many pre-bound series, the bound path scaled much better because contention was spread across many handles.

So I would not describe the largest speedup number as a general result, but the trend is encouraging and supports the usefulness of the preview API for high-concurrency, stable-attribute workloads.

For example, with 2 attributes per series and 64 threads, the local stress test showed roughly:

  • 1 series: bound was about 2x faster
  • 1,024 series: bound was about 70x faster
  • 16,384 series: bound was much faster still, but I would treat that as a stress upper bound rather than a general claim

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant