1 // Copyright The OpenTelemetry Authors
2 // SPDX-License-Identifier: Apache-2.0
4 #ifdef ENABLE_METRICS_PREVIEW
5 # include <gtest/gtest.h>
8 # include "opentelemetry/sdk/_metrics/meter.h"
10 using namespace opentelemetry::sdk::metrics
;
11 namespace metrics_api
= opentelemetry::metrics
;
12 namespace common
= opentelemetry::common
;
13 namespace nostd
= opentelemetry::nostd
;
15 OPENTELEMETRY_BEGIN_NAMESPACE
17 TEST(Meter
, CreateSyncInstruments
)
19 // Test that there are no errors creating synchronous instruments.
22 m
.NewShortCounter("Test-short-counter", "For testing", "Unitless", true);
23 m
.NewIntCounter("Test-int-counter", "For testing", "Unitless", true);
24 m
.NewFloatCounter("Test-float-counter", "For testing", "Unitless", true);
25 m
.NewDoubleCounter("Test-double-counter", "For testing", "Unitless", true);
27 m
.NewShortUpDownCounter("Test-short-ud-counter", "For testing", "Unitless", true);
28 m
.NewIntUpDownCounter("Test-int-ud-counter", "For testing", "Unitless", true);
29 m
.NewFloatUpDownCounter("Test-float-ud-counter", "For testing", "Unitless", true);
30 m
.NewDoubleUpDownCounter("Test-double-ud-counter", "For testing", "Unitless", true);
32 m
.NewShortValueRecorder("Test-short-recorder", "For testing", "Unitless", true);
33 m
.NewIntValueRecorder("Test-int-recorder", "For testing", "Unitless", true);
34 m
.NewFloatValueRecorder("Test-float-recorder", "For testing", "Unitless", true);
35 m
.NewDoubleValueRecorder("Test-double-recorder", "For testing", "Unitless", true);
38 // Dummy functions for asynchronous instrument constructors
39 void ShortCallback(metrics_api::ObserverResult
<short>) {}
40 void IntCallback(metrics_api::ObserverResult
<int>) {}
41 void FloatCallback(metrics_api::ObserverResult
<float>) {}
42 void DoubleCallback(metrics_api::ObserverResult
<double>) {}
44 TEST(Meter
, CreateAsyncInstruments
)
46 // Test that there are no errors when creating asynchronous instruments.
49 m
.NewShortSumObserver("Test-short-sum-obs", "For testing", "Unitless", true, &ShortCallback
);
50 m
.NewIntSumObserver("Test-int-sum-obs", "For testing", "Unitless", true, &IntCallback
);
51 m
.NewFloatSumObserver("Test-float-sum-obs", "For testing", "Unitless", true, &FloatCallback
);
52 m
.NewDoubleSumObserver("Test-double-sum-obs", "For testing", "Unitless", true, &DoubleCallback
);
54 m
.NewShortUpDownSumObserver("Test-short-ud-sum-obs", "For testing", "Unitless", true,
56 m
.NewIntUpDownSumObserver("Test-int-ud-sum-obs", "For testing", "Unitless", true, &IntCallback
);
57 m
.NewFloatUpDownSumObserver("Test-float-ud-sum-obs", "For testing", "Unitless", true,
59 m
.NewDoubleUpDownSumObserver("Test-double-ud-sum-obs", "For testing", "Unitless", true,
62 m
.NewShortValueObserver("Test-short-val-obs", "For testing", "Unitless", true, &ShortCallback
);
63 m
.NewIntValueObserver("Test-int-val-obs", "For testing", "Unitless", true, &IntCallback
);
64 m
.NewFloatValueObserver("Test-float-val-obs", "For testing", "Unitless", true, &FloatCallback
);
65 m
.NewDoubleValueObserver("Test-double-val-obs", "For testing", "Unitless", true, &DoubleCallback
);
68 TEST(Meter
, CollectSyncInstruments
)
70 // Verify that the records returned on a call to Collect() are correct for synchronous
74 ASSERT_EQ(m
.Collect().size(), 0);
76 auto counter
= m
.NewShortCounter("Test-counter", "For testing", "Unitless", true);
78 std::map
<std::string
, std::string
> labels
= {{"Key", "Value"}};
79 auto labelkv
= common::KeyValueIterableView
<decltype(labels
)>{labels
};
81 counter
->add(1, labelkv
);
83 std::vector
<Record
> res
= m
.Collect();
84 auto agg_var
= res
[0].GetAggregator();
85 auto agg
= nostd::get
<0>(agg_var
);
87 ASSERT_EQ(agg
->get_checkpoint()[0], 1);
89 // Now call add() and Collect() again to ensure that the value in the underlying
90 // aggregator was reset to the default.
92 counter
->add(10, labelkv
);
95 agg_var
= res
[0].GetAggregator();
96 agg
= nostd::get
<0>(agg_var
);
98 ASSERT_EQ(agg
->get_checkpoint()[0], 10);
101 TEST(Meter
, CollectDeletedSync
)
103 // Verify that calling Collect() after creating a synchronous instrument and destroying
104 // the return pointer does not result in a segfault.
108 ASSERT_EQ(m
.Collect().size(), 0);
110 std::map
<std::string
, std::string
> labels
= {{"Key", "Value"}};
111 auto labelkv
= common::KeyValueIterableView
<decltype(labels
)>{labels
};
113 auto counter
= m
.NewShortCounter("Test-counter", "For testing", "Unitless", true);
114 counter
->add(1, labelkv
);
115 } // counter shared_ptr deleted here
117 std::vector
<Record
> res
= m
.Collect();
118 auto agg_var
= res
[0].GetAggregator();
119 auto agg
= nostd::get
<0>(agg_var
);
121 ASSERT_EQ(agg
->get_checkpoint()[0], 1);
124 // Dummy function for asynchronous instrument constructors.
125 void Callback(metrics_api::ObserverResult
<short> result
)
127 std::map
<std::string
, std::string
> labels
= {{"key", "value"}};
128 auto labelkv
= common::KeyValueIterableView
<decltype(labels
)>{labels
};
129 result
.observe(1, labelkv
);
132 TEST(Meter
, CollectAsyncInstruments
)
134 // Verify that the records returned on a call to Collect() are correct for asynchronous
138 ASSERT_EQ(m
.Collect().size(), 0);
141 m
.NewShortSumObserver("Test-counter", "For testing", "Unitless", true, &ShortCallback
);
143 std::map
<std::string
, std::string
> labels
= {{"Key", "Value"}};
144 auto labelkv
= common::KeyValueIterableView
<decltype(labels
)>{labels
};
146 sumobs
->observe(1, labelkv
);
148 std::vector
<Record
> res
= m
.Collect();
149 auto agg_var
= res
[0].GetAggregator();
150 auto agg
= nostd::get
<0>(agg_var
);
152 ASSERT_EQ(agg
->get_checkpoint()[0], 1);
154 // Now call observe() and Collect() again to ensure that the value in the underlying
155 // aggregator was reset to the default.
157 sumobs
->observe(10, labelkv
);
160 agg_var
= res
[0].GetAggregator();
161 agg
= nostd::get
<0>(agg_var
);
163 ASSERT_EQ(agg
->get_checkpoint()[0], 10);
166 TEST(Meter
, CollectDeletedAsync
)
168 // Verify that calling Collect() after creating an asynchronous instrument and destroying
169 // the return pointer does not result in a segfault.
173 ASSERT_EQ(m
.Collect().size(), 0);
175 std::map
<std::string
, std::string
> labels
= {{"Key", "Value"}};
176 auto labelkv
= common::KeyValueIterableView
<decltype(labels
)>{labels
};
178 auto sumobs
= m
.NewShortSumObserver("Test-counter", "For testing", "Unitless", true, &Callback
);
179 sumobs
->observe(1, labelkv
);
180 } // sumobs shared_ptr deleted here
182 std::vector
<Record
> res
= m
.Collect();
183 auto agg_var
= res
[0].GetAggregator();
184 auto agg
= nostd::get
<0>(agg_var
);
186 ASSERT_EQ(agg
->get_checkpoint()[0], 1);
189 TEST(Meter
, RecordBatch
)
191 // This tests that RecordBatch appropriately updates the aggregators of the instruments
192 // passed to the function. Short, int, float, and double data types are tested.
195 auto scounter
= m
.NewShortCounter("Test-scounter", "For testing", "Unitless", true);
196 auto icounter
= m
.NewIntCounter("Test-icounter", "For testing", "Unitless", true);
197 auto fcounter
= m
.NewFloatCounter("Test-fcounter", "For testing", "Unitless", true);
198 auto dcounter
= m
.NewDoubleCounter("Test-dcounter", "For testing", "Unitless", true);
200 std::map
<std::string
, std::string
> labels
= {{"Key", "Value"}};
201 auto labelkv
= common::KeyValueIterableView
<decltype(labels
)>{labels
};
203 metrics_api::SynchronousInstrument
<short> *sinstr_arr
[] = {scounter
.get()};
204 short svalues_arr
[] = {1};
206 nostd::span
<metrics_api::SynchronousInstrument
<short> *> sinstrs
{sinstr_arr
};
207 nostd::span
<const short, 1> svalues
{svalues_arr
};
209 m
.RecordShortBatch(labelkv
, sinstrs
, svalues
);
210 std::vector
<Record
> res
= m
.Collect();
211 auto short_agg_var
= res
[0].GetAggregator();
212 auto short_agg
= nostd::get
<0>(short_agg_var
);
213 ASSERT_EQ(short_agg
->get_checkpoint()[0], 1);
215 metrics_api::SynchronousInstrument
<int> *iinstr_arr
[] = {icounter
.get()};
216 int ivalues_arr
[] = {1};
218 nostd::span
<metrics_api::SynchronousInstrument
<int> *> iinstrs
{iinstr_arr
};
219 nostd::span
<const int, 1> ivalues
{ivalues_arr
};
221 m
.RecordIntBatch(labelkv
, iinstrs
, ivalues
);
223 auto int_agg_var
= res
[0].GetAggregator();
224 auto int_agg
= nostd::get
<1>(int_agg_var
);
225 ASSERT_EQ(int_agg
->get_checkpoint()[0], 1);
227 metrics_api::SynchronousInstrument
<float> *finstr_arr
[] = {fcounter
.get()};
228 float fvalues_arr
[] = {1.0};
230 nostd::span
<metrics_api::SynchronousInstrument
<float> *> finstrs
{finstr_arr
};
231 nostd::span
<const float, 1> fvalues
{fvalues_arr
};
233 m
.RecordFloatBatch(labelkv
, finstrs
, fvalues
);
235 auto float_agg_var
= res
[0].GetAggregator();
236 auto float_agg
= nostd::get
<2>(float_agg_var
);
237 ASSERT_EQ(float_agg
->get_checkpoint()[0], 1.0);
239 metrics_api::SynchronousInstrument
<double> *dinstr_arr
[] = {dcounter
.get()};
240 double dvalues_arr
[] = {1.0};
242 nostd::span
<metrics_api::SynchronousInstrument
<double> *> dinstrs
{dinstr_arr
};
243 nostd::span
<const double, 1> dvalues
{dvalues_arr
};
245 m
.RecordDoubleBatch(labelkv
, dinstrs
, dvalues
);
247 auto double_agg_var
= res
[0].GetAggregator();
248 auto double_agg
= nostd::get
<3>(double_agg_var
);
249 ASSERT_EQ(double_agg
->get_checkpoint()[0], 1.0);
252 TEST(Meter
, DisableCollectSync
)
255 std::map
<std::string
, std::string
> labels
= {{"Key", "Value"}};
256 auto labelkv
= common::KeyValueIterableView
<decltype(labels
)>{labels
};
257 auto c
= m
.NewShortCounter("c", "", "", false);
259 ASSERT_EQ(m
.Collect().size(), 0);
262 TEST(Meter
, DisableCollectAsync
)
265 std::map
<std::string
, std::string
> labels
= {{"Key", "Value"}};
266 auto labelkv
= common::KeyValueIterableView
<decltype(labels
)>{labels
};
267 auto c
= m
.NewShortValueObserver("c", "", "", false, &ShortCallback
);
268 c
->observe(1, labelkv
);
269 ASSERT_EQ(m
.Collect().size(), 0);
272 TEST(MeterStringUtil
, IsValid
)
276 ASSERT_ANY_THROW(m
.NewShortCounter("", "Empty name is invalid", " ", true));
277 ASSERT_ANY_THROW(m
.NewShortCounter("1a", "Can't begin with a number", " ", true));
278 ASSERT_ANY_THROW(m
.NewShortCounter(".a", "Can't begin with punctuation", " ", true));
279 ASSERT_ANY_THROW(m
.NewShortCounter(" a", "Can't begin with space", " ", true));
280 ASSERT_ANY_THROW(m
.NewShortCounter(
281 "te^ s=%t", "Only alphanumeric ., -, and _ characters are allowed", " ", true));
285 TEST(MeterStringUtil
, AlreadyExists
)
290 m
.NewShortCounter("a", "First instance of instrument named 'a'", "", true);
291 ASSERT_ANY_THROW(m
.NewShortCounter("a", "Second (illegal) instrument named 'a'", "", true));
292 ASSERT_ANY_THROW(m
.NewShortSumObserver("a", "Still illegal even though it is not a short counter",
293 "", true, &ShortCallback
));
296 OPENTELEMETRY_END_NAMESPACE