Skip to content

PoC: Add experimental support for bound sum instruments#8278

Draft
dashpole wants to merge 1 commit intoopen-telemetry:mainfrom
dashpole:new_bound_instruments_poc
Draft

PoC: Add experimental support for bound sum instruments#8278
dashpole wants to merge 1 commit intoopen-telemetry:mainfrom
dashpole:new_bound_instruments_poc

Conversation

@dashpole
Copy link
Copy Markdown
Contributor

@dashpole dashpole commented Apr 29, 2026

Supersedes #7790

This implements a PoC for open-telemetry/opentelemetry-specification#5050, with some divergences (to try and make this more ergonomic):

  • Returns a metric.Float64Counter, which has an Add function that also accepts attributes. The current proposal does not allow the Add function for a bound instrument to also accept attributes.

Differences compared to the previous prototype:

  • The interface is defined in metric/x instead of in metric to avoid public API changes.
  • This now fully supports delta metrics, and includes benchmarks for delta metrics as well.

This prototype does not implement bound instruments for all instrument types (only for counters).

Benchmarks:

Note: I removed Filtered, Naive, and WithAttributes, and the 5 attribute case to make the benchmarks legible.

Overall, Bind() and Add() have zero memory allocations as long as there is a single measurement function (i.e. you don't have multiple views defined for the same instrument).

The Precomputed case, in which the attributes are known ahead of time, the runtime is very close to the underlying performance of incrementing an atomic counter on my machine (3 ns with no contention, ~25 ns) with 24 cores. In the Dynamic case, where attributes need to be computed for each call, the additional runtime cost is from hashing the incoming attributes, and performing the map lookup.

goos: linux
goarch: amd64
pkg: go.opentelemetry.io/otel/sdk/metric
cpu: AMD EPYC 7B12
                                                                                     │ out_parallel.txt │
                                                                                     │      sec/op      │
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Precomputed/Bound-24                   28.19n ± 14%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Precomputed/WithAttributeSet-24        53.70n ±  8%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Dynamic/Bound-24                       56.46n ± 28%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Dynamic/WithAttributeSet-24            128.3n ± 20%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Precomputed/Bound-24                  28.71n ± 10%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Precomputed/WithAttributeSet-24       50.87n ±  4%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Dynamic/Bound-24                      76.17n ± 18%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Dynamic/WithAttributeSet-24           860.0n ± 10%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Precomputed/Bound-24                        18.52n ± 16%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Precomputed/WithAttributeSet-24             102.5n ±  8%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Dynamic/Bound-24                            70.47n ±  6%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Dynamic/WithAttributeSet-24                 213.3n ± 11%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Precomputed/Bound-24                       18.40n ± 11%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Precomputed/WithAttributeSet-24            97.88n ± 12%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Dynamic/Bound-24                           92.74n ±  5%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Dynamic/WithAttributeSet-24                862.8n ± 10%
geomean                                                                                    82.16n

                                                                                     │ out_parallel.txt │
                                                                                     │       B/op       │
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Precomputed/Bound-24                   0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Precomputed/WithAttributeSet-24        0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Dynamic/Bound-24                       0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Dynamic/WithAttributeSet-24            64.00 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Precomputed/Bound-24                  0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Precomputed/WithAttributeSet-24       0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Dynamic/Bound-24                      0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Dynamic/WithAttributeSet-24           708.0 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Precomputed/Bound-24                        0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Precomputed/WithAttributeSet-24             0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Dynamic/Bound-24                            0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Dynamic/WithAttributeSet-24                 64.00 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Precomputed/Bound-24                       0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Precomputed/WithAttributeSet-24            0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Dynamic/Bound-24                           0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Dynamic/WithAttributeSet-24                708.0 ± 0%
geomean                                                                                               ¹
¹ summaries must be >0 to compute geomean

                                                                                     │ out_parallel.txt │
                                                                                     │    allocs/op     │
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Precomputed/Bound-24                   0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Precomputed/WithAttributeSet-24        0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Dynamic/Bound-24                       0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Dynamic/WithAttributeSet-24            1.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Precomputed/Bound-24                  0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Precomputed/WithAttributeSet-24       0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Dynamic/Bound-24                      0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Dynamic/WithAttributeSet-24           1.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Precomputed/Bound-24                        0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Precomputed/WithAttributeSet-24             0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Dynamic/Bound-24                            0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Dynamic/WithAttributeSet-24                 1.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Precomputed/Bound-24                       0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Precomputed/WithAttributeSet-24            0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Dynamic/Bound-24                           0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Dynamic/WithAttributeSet-24                1.000 ± 0%
geomean                                                                                               ¹
¹ summaries must be >0 to compute geomean

Serial Benchmarks:

goos: linux
goarch: amd64
pkg: go.opentelemetry.io/otel/sdk/metric
cpu: AMD EPYC 7B12
                                                                                  │ out_serial.txt │
                                                                                  │     sec/op     │
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Precomputed/Bound                 3.498n ±  2%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Precomputed/WithAttributeSet      41.79n ±  8%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Dynamic/Bound                     100.4n ±  5%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Dynamic/WithAttributeSet          229.6n ± 15%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Precomputed/Bound                3.482n ±  2%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Precomputed/WithAttributeSet     41.00n ±  1%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Dynamic/Bound                    644.1n ±  9%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Dynamic/WithAttributeSet         1.573µ ± 11%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Precomputed/Bound                      3.969n ±  9%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Precomputed/WithAttributeSet           46.96n ±  7%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Dynamic/Bound                          105.9n ±  4%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Dynamic/WithAttributeSet               286.5n ± 13%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Precomputed/Bound                     3.768n ±  2%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Precomputed/WithAttributeSet          47.15n ±  8%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Dynamic/Bound                         645.6n ± 10%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Dynamic/WithAttributeSet              1.420µ ± 12%
geomean                                                                               71.32n

                                                                                  │ out_serial.txt │
                                                                                  │      B/op      │
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Precomputed/Bound                 0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Precomputed/WithAttributeSet      0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Dynamic/Bound                     0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Dynamic/WithAttributeSet          64.00 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Precomputed/Bound                0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Precomputed/WithAttributeSet     0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Dynamic/Bound                    0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Dynamic/WithAttributeSet         705.0 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Precomputed/Bound                      0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Precomputed/WithAttributeSet           0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Dynamic/Bound                          0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Dynamic/WithAttributeSet               64.00 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Precomputed/Bound                     0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Precomputed/WithAttributeSet          0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Dynamic/Bound                         0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Dynamic/WithAttributeSet              704.0 ± 0%
geomean                                                                                          ¹
¹ summaries must be >0 to compute geomean

                                                                                  │ out_serial.txt │
                                                                                  │   allocs/op    │
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Precomputed/Bound                 0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Precomputed/WithAttributeSet      0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Dynamic/Bound                     0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/1/Dynamic/WithAttributeSet          1.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Precomputed/Bound                0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Precomputed/WithAttributeSet     0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Dynamic/Bound                    0.000 ± 0%
EndToEndCounterAdd/Cumulative/NoFilter/Attributes/10/Dynamic/WithAttributeSet         1.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Precomputed/Bound                      0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Precomputed/WithAttributeSet           0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Dynamic/Bound                          0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/1/Dynamic/WithAttributeSet               1.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Precomputed/Bound                     0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Precomputed/WithAttributeSet          0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Dynamic/Bound                         0.000 ± 0%
EndToEndCounterAdd/Delta/NoFilter/Attributes/10/Dynamic/WithAttributeSet              1.000 ± 0%
geomean                                                                                          ¹
¹ summaries must be >0 to compute geomean

Most of this was written by Gemini.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 29, 2026

Codecov Report

❌ Patch coverage is 78.54985% with 71 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.8%. Comparing base (468c62d) to head (47b702c).
⚠️ Report is 9 commits behind head on main.

Files with missing lines Patch % Lines
sdk/metric/internal/aggregate/sum.go 72.5% 44 Missing and 10 partials ⚠️
sdk/metric/instrument.go 58.8% 14 Missing ⚠️
attribute/set.go 89.4% 1 Missing and 1 partial ⚠️
sdk/metric/pipeline.go 97.2% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##            main   #8278     +/-   ##
=======================================
- Coverage   82.9%   82.8%   -0.1%     
=======================================
  Files        314     314             
  Lines      24911   25209    +298     
=======================================
+ Hits       20661   20889    +228     
- Misses      3878    3937     +59     
- Partials     372     383     +11     
Files with missing lines Coverage Δ
sdk/metric/internal/aggregate/aggregate.go 100.0% <100.0%> (ø)
sdk/metric/internal/aggregate/atomic.go 91.0% <100.0%> (+0.1%) ⬆️
...metric/internal/aggregate/exponential_histogram.go 100.0% <100.0%> (ø)
sdk/metric/internal/aggregate/histogram.go 100.0% <100.0%> (ø)
sdk/metric/internal/aggregate/lastvalue.go 100.0% <100.0%> (ø)
sdk/metric/meter.go 92.3% <100.0%> (ø)
sdk/metric/pipeline.go 90.6% <97.2%> (+0.3%) ⬆️
attribute/set.go 81.1% <89.4%> (+0.9%) ⬆️
sdk/metric/instrument.go 86.3% <58.8%> (-11.3%) ⬇️
sdk/metric/internal/aggregate/sum.go 83.6% <72.5%> (-16.4%) ⬇️

... and 5 files with indirect coverage changes

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

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