Skip to content

Commit 26324a9

Browse files
authored
Add Support for UpDownCounter, ObservableUpDownCounter, ObservableGauge<int64_t>, Histogram<double> (#241)
1 parent dba13fe commit 26324a9

File tree

8 files changed

+218
-51
lines changed

8 files changed

+218
-51
lines changed

exporters/geneva/example/example_metrics.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ const std::string kNamespaceName = "test_ns";
2626

2727
void initMetrics(const std::string &name, const std::string &account_name) {
2828

29-
#ifndef _WIN32
30-
conn_string = "Endpoint=unix://" + kUnixDomainPath + ";" + conn_string;
31-
#else
3229
std::string conn_string =
3330
"Account=" + account_name + ";Namespace=" + kNamespaceName;
31+
#ifndef _WIN32
32+
conn_string = "Endpoint=unix://" + kUnixDomainPath + ";" + conn_string;
3433
#endif
34+
3535
geneva_exporter::ExporterOptions options{conn_string};
3636
std::unique_ptr<metric_sdk::PushMetricExporter> exporter{
3737
new geneva_exporter::Exporter(options)};

exporters/geneva/include/opentelemetry/exporters/geneva/metrics/data_transport.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,19 @@ namespace exporter {
1212
namespace geneva {
1313
namespace metrics {
1414

15-
// These enums are defined in
15+
// These enums are defined in
1616
// file: test/decoder/ifx_metrics_bin.ksy (enum metric_event_type)
1717
enum class MetricsEventType : uint16_t {
18-
ULongMetric = 50,
18+
Uint64Metric = 50,
19+
DoubleScaledToLongMetric = 51,
20+
BatchMetric = 52,
21+
ExternallyAggregatedUlongMetric = 53,
22+
ExternallyAggregatedDoubleMetric = 54,
1923
DoubleMetric = 55,
20-
ExternallyAggregatedULongDistributionMetric = 56
24+
ExternallyAggregatedUlongDistributionMetric = 56,
25+
ExternallyAggregatedDoubleDistributionMetric = 57,
26+
ExternallyAggregatedDoubleScaledToLongDistributionMetric = 58,
27+
Undefined = 100
2128
};
2229

2330
class DataTransport {
@@ -26,9 +33,9 @@ class DataTransport {
2633
virtual bool Send(MetricsEventType event_type, const char *data,
2734
uint16_t length) noexcept = 0;
2835
virtual bool Disconnect() noexcept = 0;
29-
virtual ~DataTransport() = 0;
36+
virtual ~DataTransport() = default;
3037
};
3138
} // namespace metrics
3239
} // namespace geneva
3340
} // namespace exporter
34-
OPENTELEMETRY_END_NAMESPACE
41+
OPENTELEMETRY_END_NAMESPACE

exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ constexpr uint64_t kSecondsToUnixTime =
3333
// 1601-01-01T00:00:00Z and UNIX/Linux epoch
3434
// (1970-01-01T00:00:00Z)
3535

36+
using ValueType = nostd::variant<int64_t, double>;
37+
3638
/**
3739
* The Geneva metrics exporter exports metrics data to Geneva
3840
*/

exporters/geneva/include/opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class UnixDomainSocketDataTransport : public DataTransport {
2121
bool Send(MetricsEventType event_type, const char *data,
2222
uint16_t length) noexcept override;
2323
bool Disconnect() noexcept override;
24+
~UnixDomainSocketDataTransport() = default;
2425

2526
private:
2627
// Socket connection is re-established for every batch of events

exporters/geneva/src/exporter.cc

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -81,47 +81,73 @@ opentelemetry::sdk::common::ExportResult Exporter::Export(
8181
point_data_with_attributes.point_data)) {
8282
auto value = nostd::get<sdk::metrics::SumPointData>(
8383
point_data_with_attributes.point_data);
84-
MetricsEventType event_type = MetricsEventType::ULongMetric;
84+
ValueType new_value = value.value_;
85+
86+
MetricsEventType event_type;
87+
8588
if (nostd::holds_alternative<double>(value.value_)) {
8689
event_type = MetricsEventType::DoubleMetric;
90+
} else {
91+
if (!value.is_monotonic_) {
92+
// NOTE - Potential for minor precision loss implicitly going from
93+
// int64_t to double -
94+
// - A 64-bit integer can hold more significant decimal digits
95+
// than a standard
96+
// IEEE (64-bit) double precision floating-point
97+
// representation
98+
new_value = static_cast<double>(nostd::get<int64_t>(new_value));
99+
event_type = MetricsEventType::DoubleMetric;
100+
101+
} else {
102+
event_type = MetricsEventType::Uint64Metric;
103+
}
87104
}
88-
89105
body_length = SerializeNonHistogramMetrics(
90-
sdk::metrics::AggregationType::kSum, event_type, value.value_,
106+
sdk::metrics::AggregationType::kSum, event_type, new_value,
91107
metric_data.end_ts, metric_data.instrument_descriptor.name_,
92108
point_data_with_attributes.attributes);
93109
data_transport_->Send(event_type, buffer_non_histogram_,
94110
body_length + kBinaryHeaderSize);
95111

96112
} else if (nostd::holds_alternative<sdk::metrics::LastValuePointData>(
97113
point_data_with_attributes.point_data)) {
98-
auto value = nostd::get<sdk::metrics::SumPointData>(
114+
auto value = nostd::get<sdk::metrics::LastValuePointData>(
99115
point_data_with_attributes.point_data);
100-
MetricsEventType event_type = MetricsEventType::ULongMetric;
101-
if (nostd::holds_alternative<double>(value.value_)) {
102-
event_type = MetricsEventType::DoubleMetric;
116+
ValueType new_value = value.value_;
117+
if (nostd::holds_alternative<int64_t>(value.value_)) {
118+
// NOTE - Potential for minor precision loss implicitly going from
119+
// int64_t to double -
120+
// - A 64-bit integer can hold more significant decimal digits
121+
// than a standard
122+
// IEEE (64-bit) double precision floating-point representation
123+
new_value = static_cast<double>(nostd::get<int64_t>(new_value));
103124
}
125+
MetricsEventType event_type = MetricsEventType::DoubleMetric;
104126
body_length = SerializeNonHistogramMetrics(
105-
sdk::metrics::AggregationType::kLastValue, event_type,
106-
value.value_, metric_data.end_ts,
107-
metric_data.instrument_descriptor.name_,
127+
sdk::metrics::AggregationType::kLastValue, event_type, new_value,
128+
metric_data.end_ts, metric_data.instrument_descriptor.name_,
108129
point_data_with_attributes.attributes);
109130
data_transport_->Send(event_type, buffer_non_histogram_,
110131
body_length + kBinaryHeaderSize);
111132
} else if (nostd::holds_alternative<sdk::metrics::HistogramPointData>(
112133
point_data_with_attributes.point_data)) {
113134
auto value = nostd::get<sdk::metrics::HistogramPointData>(
114135
point_data_with_attributes.point_data);
115-
MetricsEventType event_type =
116-
MetricsEventType::ExternallyAggregatedULongDistributionMetric;
136+
ValueType new_sum = value.sum_;
137+
ValueType new_min = value.min_;
138+
ValueType new_max = value.max_;
139+
117140
if (nostd::holds_alternative<double>(value.sum_)) {
118-
LOG_ERROR("Geneva Exporter::Export- Double value is not supported "
119-
"for Histogram");
120-
continue;
141+
// TODO: Double is not supported by Geneva, convert it to int64_t
142+
new_sum = static_cast<int64_t>(nostd::get<double>(new_sum));
143+
new_min = static_cast<int64_t>(nostd::get<double>(new_min));
144+
new_max = static_cast<int64_t>(nostd::get<double>(new_max));
121145
}
146+
MetricsEventType event_type =
147+
MetricsEventType::ExternallyAggregatedUlongDistributionMetric;
122148
body_length = SerializeHistogramMetrics(
123149
sdk::metrics::AggregationType::kHistogram, event_type,
124-
value.count_, value.sum_, value.min_, value.max_,
150+
value.count_, new_sum, new_min, new_max,
125151
nostd::get<sdk::metrics::HistogramPointData>(
126152
point_data_with_attributes.point_data)
127153
.boundaries_,
@@ -232,13 +258,15 @@ size_t Exporter::SerializeNonHistogramMetrics(
232258
.count());
233259

234260
SerializeInt<uint64_t>(buffer_non_histogram_, bufferIndex, windows_ticks);
235-
if (event_type == MetricsEventType::ULongMetric) {
261+
if (event_type == MetricsEventType::Uint64Metric) {
236262
SerializeInt<uint64_t>(buffer_non_histogram_, bufferIndex,
237263
static_cast<uint64_t>(nostd::get<int64_t>(value)));
238-
} else {
264+
} else if (event_type == MetricsEventType::DoubleMetric) {
239265
SerializeInt<uint64_t>(
240266
buffer_non_histogram_, bufferIndex,
241267
*(reinterpret_cast<const uint64_t *>(&(nostd::get<double>(value)))));
268+
} else {
269+
// Won't reach here.
242270
}
243271
return body_length;
244272
}
@@ -290,7 +318,7 @@ size_t Exporter::SerializeHistogramMetrics(
290318
size_t index = 0;
291319
uint16_t bucket_count = 0;
292320
if (event_type ==
293-
MetricsEventType::ExternallyAggregatedULongDistributionMetric) {
321+
MetricsEventType::ExternallyAggregatedUlongDistributionMetric) {
294322
for (auto boundary : boundaries) {
295323
if (counts[index] > 0) {
296324
SerializeInt<uint64_t>(buffer_histogram_, bufferIndex,
@@ -340,7 +368,7 @@ size_t Exporter::SerializeHistogramMetrics(
340368
// sum, min, max
341369

342370
if (event_type ==
343-
MetricsEventType::ExternallyAggregatedULongDistributionMetric) {
371+
MetricsEventType::ExternallyAggregatedUlongDistributionMetric) {
344372
// sum
345373
SerializeInt<uint64_t>(buffer_histogram_, bufferIndex,
346374
static_cast<uint64_t>(nostd::get<int64_t>(sum)));
@@ -351,18 +379,7 @@ size_t Exporter::SerializeHistogramMetrics(
351379
SerializeInt<uint64_t>(buffer_histogram_, bufferIndex,
352380
static_cast<uint64_t>(nostd::get<int64_t>(max)));
353381
} else {
354-
// sum
355-
SerializeInt<uint64_t>(
356-
buffer_histogram_, bufferIndex,
357-
*(reinterpret_cast<const uint64_t *>(&(nostd::get<double>(sum)))));
358-
// min
359-
SerializeInt<uint64_t>(
360-
buffer_histogram_, bufferIndex,
361-
*(reinterpret_cast<const uint64_t *>(&(nostd::get<double>(min)))));
362-
// max
363-
SerializeInt<uint64_t>(
364-
buffer_histogram_, bufferIndex,
365-
*(reinterpret_cast<const uint64_t *>(&(nostd::get<double>(max)))));
382+
// won't reach here.
366383
}
367384
return body_length;
368385
}

exporters/geneva/test/common/generate_metrics.h

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ const uint16_t kCounterDoubleEventId = 55;
2929

3030
static inline opentelemetry::sdk::metrics::ResourceMetrics
3131
GenerateSumDataDoubleMetrics() {
32-
3332
opentelemetry::sdk::metrics::SumPointData sum_point_data1{};
3433
sum_point_data1.value_ = kCounterDoubleValue1;
34+
sum_point_data1.is_monotonic_ = true;
3535
opentelemetry::sdk::metrics::SumPointData sum_point_data2{};
3636
sum_point_data2.value_ = kCounterDoubleValue2;
37+
sum_point_data2.is_monotonic_ = true;
3738
opentelemetry::sdk::metrics::ResourceMetrics data;
3839
auto resource = opentelemetry::sdk::resource::Resource::Create(
3940
opentelemetry::sdk::resource::ResourceAttributes{});
@@ -81,9 +82,9 @@ const uint16_t kCounterLongEventId = 50;
8182

8283
static inline opentelemetry::sdk::metrics::ResourceMetrics
8384
GenerateSumDataLongMetrics() {
84-
8585
opentelemetry::sdk::metrics::SumPointData sum_point_data{};
8686
sum_point_data.value_ = kCounterLongValue;
87+
sum_point_data.is_monotonic_ = true;
8788
opentelemetry::sdk::metrics::ResourceMetrics data;
8889
auto resource = opentelemetry::sdk::resource::Resource::Create(
8990
opentelemetry::sdk::resource::ResourceAttributes{});
@@ -111,6 +112,100 @@ GenerateSumDataLongMetrics() {
111112
return data;
112113
}
113114

115+
// Counter Instrument of long type
116+
const std::string kUpDownCounterLongInstrumentName =
117+
"test_instrument_up_down_couter_long_name";
118+
const std::string kUpDownCounterLongInstrumentDesc =
119+
"test_instrument_up_down_counter_long_desc";
120+
const std::string kUpDownCounterLongInstrumentUnit =
121+
"test_instrument_up_down_conter_long_unit";
122+
const long kUpDownCounterLongValue = -10;
123+
const std::string kUpDownCounterLongAttributeKey1 = "up_down_counter_long_key1";
124+
const std::string kUpDownCounterLongAttributeValue1 =
125+
"up_down_counter_long_value1";
126+
const uint16_t kUpDownCounterLongCountDimensions = 1;
127+
128+
static inline opentelemetry::sdk::metrics::ResourceMetrics
129+
GenerateSumDataLongMetricsNonMonotonic() {
130+
opentelemetry::sdk::metrics::SumPointData sum_point_data{};
131+
sum_point_data.value_ = kUpDownCounterLongValue;
132+
sum_point_data.is_monotonic_ = false;
133+
opentelemetry::sdk::metrics::ResourceMetrics data;
134+
auto resource = opentelemetry::sdk::resource::Resource::Create(
135+
opentelemetry::sdk::resource::ResourceAttributes{});
136+
data.resource_ = &resource;
137+
auto scope =
138+
opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create(
139+
kInstrumentScopeName, kInstrumentScopeVer);
140+
opentelemetry::sdk::metrics::MetricData metric_data{
141+
opentelemetry::sdk::metrics::InstrumentDescriptor{
142+
kUpDownCounterLongInstrumentName, kUpDownCounterLongInstrumentDesc,
143+
kUpDownCounterLongInstrumentUnit,
144+
opentelemetry::sdk::metrics::InstrumentType::kUpDownCounter,
145+
opentelemetry::sdk::metrics::InstrumentValueType::kLong},
146+
opentelemetry::sdk::metrics::AggregationTemporality::kDelta,
147+
opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()},
148+
opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()},
149+
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>{
150+
{opentelemetry::sdk::metrics::PointAttributes{
151+
{kUpDownCounterLongAttributeKey1,
152+
kUpDownCounterLongAttributeValue1}},
153+
sum_point_data}}};
154+
data.scope_metric_data_ =
155+
std::vector<opentelemetry::sdk::metrics::ScopeMetrics>{
156+
{scope.get(),
157+
std::vector<opentelemetry::sdk::metrics::MetricData>{metric_data}}};
158+
return data;
159+
}
160+
161+
// Counter Instrument of double type
162+
const std::string kUpDownCounterDoubleInstrumentName =
163+
"test_instrument_up_down_couter_double_name";
164+
const std::string kUpDownCounterDoubleInstrumentDesc =
165+
"test_instrument_up_down_counter_double_desc";
166+
const std::string kUpDownCounterDoubleInstrumentUnit =
167+
"test_instrument_up_down_conter_double_unit";
168+
const double kUpDownCounterDoubleValue = -10.2;
169+
const std::string kUpDownCounterDoubleAttributeKey1 =
170+
"up_down_counter_double_key1";
171+
const std::string kUpDownCounterDoubleAttributeValue1 =
172+
"up_down_counter_double_value1";
173+
const uint16_t kUpDownCounterDoubleCountDimensions = 1;
174+
175+
static inline opentelemetry::sdk::metrics::ResourceMetrics
176+
GenerateSumDataDoubleMetricsNonMonotonic() {
177+
opentelemetry::sdk::metrics::SumPointData sum_point_data1{};
178+
sum_point_data1.value_ = kUpDownCounterDoubleValue;
179+
sum_point_data1.is_monotonic_ = false;
180+
opentelemetry::sdk::metrics::ResourceMetrics data;
181+
auto resource = opentelemetry::sdk::resource::Resource::Create(
182+
opentelemetry::sdk::resource::ResourceAttributes{});
183+
data.resource_ = &resource;
184+
auto scope =
185+
opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create(
186+
kInstrumentScopeName, kInstrumentScopeVer);
187+
opentelemetry::sdk::metrics::MetricData metric_data{
188+
opentelemetry::sdk::metrics::InstrumentDescriptor{
189+
kUpDownCounterDoubleInstrumentName,
190+
kUpDownCounterDoubleInstrumentDesc,
191+
kUpDownCounterDoubleInstrumentUnit,
192+
opentelemetry::sdk::metrics::InstrumentType::kUpDownCounter,
193+
opentelemetry::sdk::metrics::InstrumentValueType::kDouble},
194+
opentelemetry::sdk::metrics::AggregationTemporality::kDelta,
195+
opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()},
196+
opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()},
197+
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>{
198+
{opentelemetry::sdk::metrics::PointAttributes{
199+
{kUpDownCounterDoubleAttributeKey1,
200+
kUpDownCounterDoubleAttributeValue1}},
201+
sum_point_data1}}};
202+
data.scope_metric_data_ =
203+
std::vector<opentelemetry::sdk::metrics::ScopeMetrics>{
204+
{scope.get(),
205+
std::vector<opentelemetry::sdk::metrics::MetricData>{metric_data}}};
206+
return data;
207+
}
208+
114209
// Histogram Instrument of type long
115210
const std::string kHistogramLongInstrumentName =
116211
"test_instrument_histogram_long_name";

exporters/geneva/test/decoder/ifx_metrics_bin.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
#include "ifx_metrics_bin.h"
44

5+
#include <iostream>
56
ifx_metrics_bin_t::ifx_metrics_bin_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) {
7+
std::cout << "\nLALIT:ifx_metrics_bin::CONST..";
8+
69
m__parent = p__parent;
710
m__root = this;
811
m_body = 0;
@@ -17,7 +20,9 @@ ifx_metrics_bin_t::ifx_metrics_bin_t(kaitai::kstream* p__io, kaitai::kstruct* p_
1720
}
1821

1922
void ifx_metrics_bin_t::_read() {
23+
std::cout << "\nLALIT:ifx_metrics_bin::READ..";
2024
m_event_id = m__io->read_u2le();
25+
std::cout << "\nLALIT:ifx_metrics_bin Event ID:" << m_event_id << "\n";
2126
m_len_body = m__io->read_u2le();
2227
m__raw_body = m__io->read_bytes(len_body());
2328
m__io__raw_body = new kaitai::kstream(m__raw_body);

0 commit comments

Comments
 (0)