1111#include " opentelemetry/nostd/type_traits.h"
1212#include " opentelemetry/version.h"
1313
14+ #ifdef OPENTELEMETRY_HAVE_METRICS_BOUND_INSTRUMENTS_PREVIEW
15+ # include " opentelemetry/nostd/unique_ptr.h"
16+ #endif
17+
1418OPENTELEMETRY_BEGIN_NAMESPACE
1519namespace metrics
1620{
@@ -26,6 +30,62 @@ class SynchronousInstrument
2630 virtual ~SynchronousInstrument () = default ;
2731};
2832
33+ #ifdef OPENTELEMETRY_HAVE_METRICS_BOUND_INSTRUMENTS_PREVIEW
34+ // Bound synchronous instrument support intentionally covers Counter and
35+ // Histogram only. UpDownCounter, Gauge, exemplar parity, and context-bearing
36+ // bound operations are follow-ups. This API is experimental and is gated
37+ // behind both ABI v2 and ENABLE_METRICS_BOUND_INSTRUMENTS_PREVIEW
38+ // (see OPENTELEMETRY_HAVE_METRICS_BOUND_INSTRUMENTS_PREVIEW in version.h).
39+ /* *
40+ * @since ABI_VERSION 2
41+ * A bound counter handle obtained via Counter<T>::Bind(...). The associated
42+ * attribute set is captured at Bind time so the hot path avoids per-call
43+ * attribute processing and hashmap lookup. The handle must not outlive the
44+ * Counter instrument from which it was obtained.
45+ */
46+ template <class T >
47+ class BoundCounter
48+ {
49+ public:
50+ BoundCounter () = default ;
51+ BoundCounter (const BoundCounter &) = delete ;
52+ BoundCounter (BoundCounter &&) noexcept = delete ;
53+ BoundCounter &operator =(const BoundCounter &) = delete ;
54+ BoundCounter &operator =(BoundCounter &&) noexcept = delete ;
55+ virtual ~BoundCounter () = default ;
56+
57+ /* *
58+ * Record a value against the bound attribute set.
59+ *
60+ * @param value The increment amount. MUST be non-negative.
61+ */
62+ virtual void Add (T value) noexcept = 0;
63+ };
64+
65+ /* *
66+ * @since ABI_VERSION 2
67+ * A bound histogram handle obtained via Histogram<T>::Bind(...).
68+ */
69+ template <class T >
70+ class BoundHistogram
71+ {
72+ public:
73+ BoundHistogram () = default ;
74+ BoundHistogram (const BoundHistogram &) = delete ;
75+ BoundHistogram (BoundHistogram &&) noexcept = delete ;
76+ BoundHistogram &operator =(const BoundHistogram &) = delete ;
77+ BoundHistogram &operator =(BoundHistogram &&) noexcept = delete ;
78+ virtual ~BoundHistogram () = default ;
79+
80+ /* *
81+ * Record a value against the bound attribute set.
82+ *
83+ * @param value The measurement value. MUST be non-negative.
84+ */
85+ virtual void Record (T value) noexcept = 0;
86+ };
87+ #endif
88+
2989/* A Counter instrument that adds values. */
3090template <class T >
3191class Counter : public SynchronousInstrument
@@ -98,6 +158,32 @@ class Counter : public SynchronousInstrument
98158 attributes.begin (), attributes.end ()},
99159 context);
100160 }
161+
162+ #ifdef OPENTELEMETRY_HAVE_METRICS_BOUND_INSTRUMENTS_PREVIEW
163+ /* *
164+ * @since ABI_VERSION 2
165+ * Returns a bound counter handle for the given attribute set. Repeated calls
166+ * to BoundCounter<T>::Add(value) avoid per-call attribute processing and
167+ * hashmap lookup. The bound handle MUST NOT outlive this Counter instrument.
168+ */
169+ virtual nostd::unique_ptr<BoundCounter<T>> Bind (
170+ const common::KeyValueIterable &attributes) noexcept = 0;
171+
172+ template <class U ,
173+ nostd::enable_if_t <common::detail::is_key_value_iterable<U>::value> * = nullptr >
174+ nostd::unique_ptr<BoundCounter<T>> Bind (const U &attributes) noexcept
175+ {
176+ return this ->Bind (common::KeyValueIterableView<U>{attributes});
177+ }
178+
179+ nostd::unique_ptr<BoundCounter<T>> Bind (
180+ std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
181+ attributes) noexcept
182+ {
183+ return this ->Bind (nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
184+ attributes.begin (), attributes.end ()});
185+ }
186+ #endif
101187};
102188
103189/* * A histogram instrument that records values. */
@@ -140,6 +226,33 @@ class Histogram : public SynchronousInstrument
140226 }
141227#endif
142228
229+ #ifdef OPENTELEMETRY_HAVE_METRICS_BOUND_INSTRUMENTS_PREVIEW
230+ /* *
231+ * @since ABI_VERSION 2
232+ * Returns a bound histogram handle for the given attribute set. Repeated
233+ * calls to BoundHistogram<T>::Record(value) avoid per-call attribute
234+ * processing and hashmap lookup. The bound handle MUST NOT outlive this
235+ * Histogram instrument.
236+ */
237+ virtual nostd::unique_ptr<BoundHistogram<T>> Bind (
238+ const common::KeyValueIterable &attributes) noexcept = 0;
239+
240+ template <class U ,
241+ nostd::enable_if_t <common::detail::is_key_value_iterable<U>::value> * = nullptr >
242+ nostd::unique_ptr<BoundHistogram<T>> Bind (const U &attributes) noexcept
243+ {
244+ return this ->Bind (common::KeyValueIterableView<U>{attributes});
245+ }
246+
247+ nostd::unique_ptr<BoundHistogram<T>> Bind (
248+ std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
249+ attributes) noexcept
250+ {
251+ return this ->Bind (nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
252+ attributes.begin (), attributes.end ()});
253+ }
254+ #endif
255+
143256 /* *
144257 * Records a value.
145258 *
0 commit comments