Skip to content

Commit ec1275c

Browse files
authored
[METRICS] Add tag to AggregationConfig for aggregation type validation (#3732)
1 parent 6dcf647 commit ec1275c

File tree

5 files changed

+116
-3
lines changed

5 files changed

+116
-3
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ Increment the:
1515

1616
## [Unreleased]
1717

18+
* [METRICS] Add tag to AggregationConfig for aggregation type validation
19+
[#3732](https://github.com/open-telemetry/opentelemetry-cpp/pull/3732)
20+
1821
* [TEST] Remove workaround for metrics cardinality limit test
1922
[#3663](https://github.com/open-telemetry/opentelemetry-cpp/pull/3663)
23+
2024
* [METRICS] Allow registering one callback for multiple instruments
2125
[#3667](https://github.com/open-telemetry/opentelemetry-cpp/pull/3667)
2226

sdk/include/opentelemetry/sdk/metrics/aggregation/aggregation_config.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <vector>
77

8+
#include "opentelemetry/sdk/metrics/instruments.h"
89
#include "opentelemetry/sdk/metrics/state/attributes_hashmap.h"
910
#include "opentelemetry/version.h"
1011

@@ -13,13 +14,16 @@ namespace sdk
1314
{
1415
namespace metrics
1516
{
17+
1618
class AggregationConfig
1719
{
1820
public:
1921
AggregationConfig(size_t cardinality_limit = kAggregationCardinalityLimit)
2022
: cardinality_limit_(cardinality_limit)
2123
{}
2224

25+
virtual AggregationType GetType() const noexcept { return AggregationType::kDefault; }
26+
2327
static const AggregationConfig *GetOrDefault(const AggregationConfig *config)
2428
{
2529
if (config)
@@ -41,6 +45,8 @@ class HistogramAggregationConfig : public AggregationConfig
4145
: AggregationConfig(cardinality_limit)
4246
{}
4347

48+
AggregationType GetType() const noexcept override { return AggregationType::kHistogram; }
49+
4450
std::vector<double> boundaries_;
4551
bool record_min_max_ = true;
4652
};
@@ -53,6 +59,11 @@ class Base2ExponentialHistogramAggregationConfig : public AggregationConfig
5359
: AggregationConfig(cardinality_limit)
5460
{}
5561

62+
AggregationType GetType() const noexcept override
63+
{
64+
return AggregationType::kBase2ExponentialHistogram;
65+
}
66+
5667
size_t max_buckets_ = 160;
5768
int32_t max_scale_ = 20;
5869
bool record_min_max_ = true;

sdk/include/opentelemetry/sdk/metrics/view/view_registry.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
#pragma once
55

66
#include <algorithm>
7+
#include <cassert>
78
#include <memory>
89
#include <string>
910
#include <utility>
1011
#include <vector>
1112

1213
#include "opentelemetry/nostd/function_ref.h"
14+
#include "opentelemetry/sdk/common/global_log_handler.h"
1315
#include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
16+
#include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h"
1417
#include "opentelemetry/sdk/metrics/instruments.h"
1518
#include "opentelemetry/sdk/metrics/view/instrument_selector.h"
1619
#include "opentelemetry/sdk/metrics/view/meter_selector.h"
@@ -47,6 +50,60 @@ class ViewRegistry
4750
{
4851
// TBD - thread-safe ?
4952

53+
// Validate parameters
54+
if (!instrument_selector || !meter_selector || !view)
55+
{
56+
OTEL_INTERNAL_LOG_ERROR(
57+
"[ViewRegistry::AddView] Invalid parameters: instrument_selector, meter_selector, and "
58+
"view cannot be null. Ignoring AddView call.");
59+
return;
60+
}
61+
62+
auto aggregation_config = view->GetAggregationConfig();
63+
if (aggregation_config)
64+
{
65+
bool valid = false;
66+
auto aggregation_config_type = aggregation_config->GetType();
67+
auto aggregation_type = view->GetAggregationType();
68+
69+
if (aggregation_type == AggregationType::kDefault)
70+
{
71+
bool is_monotonic;
72+
aggregation_type = DefaultAggregation::GetDefaultAggregationType(
73+
instrument_selector->GetInstrumentType(), is_monotonic);
74+
}
75+
76+
switch (aggregation_type)
77+
{
78+
case AggregationType::kHistogram:
79+
valid = (aggregation_config_type == AggregationType::kHistogram);
80+
break;
81+
82+
case AggregationType::kBase2ExponentialHistogram:
83+
valid = (aggregation_config_type == AggregationType::kBase2ExponentialHistogram);
84+
break;
85+
86+
case AggregationType::kDrop:
87+
case AggregationType::kLastValue:
88+
case AggregationType::kSum:
89+
valid = (aggregation_config_type == AggregationType::kDefault);
90+
break;
91+
92+
default:
93+
// Unreachable: all AggregationType enum values are handled above
94+
assert(false && "Unreachable: unhandled AggregationType");
95+
valid = false;
96+
}
97+
98+
if (!valid)
99+
{
100+
OTEL_INTERNAL_LOG_ERROR(
101+
"[ViewRegistry::AddView] AggregationType and AggregationConfig type mismatch. "
102+
"Ignoring AddView call.");
103+
return;
104+
}
105+
}
106+
50107
auto registered_view = std::unique_ptr<RegisteredView>(new RegisteredView{
51108
std::move(instrument_selector), std::move(meter_selector), std::move(view)});
52109
registered_views_.push_back(std::move(registered_view));

sdk/test/metrics/meter_provider_sdk_test.cc

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ using namespace opentelemetry::sdk::metrics;
3636
TEST(MeterProvider, GetMeter)
3737
{
3838
MeterProvider mp1;
39-
// std::unique_ptr<View> view{std::unique_ptr<View>()};
40-
// MeterProvider mp1(std::move(exporters), std::move(readers), std::move(views);
4139
auto m1 = mp1.GetMeter("test");
4240
auto m2 = mp1.GetMeter("test");
4341
auto m3 = mp1.GetMeter("different", "1.0.0");
@@ -66,7 +64,7 @@ TEST(MeterProvider, GetMeter)
6664
std::unique_ptr<MetricReader> reader{new MockMetricReader(std::move(exporter))};
6765
mp1.AddMetricReader(std::move(reader));
6866

69-
std::unique_ptr<View> view{std::unique_ptr<View>()};
67+
std::unique_ptr<View> view{new View("test_view")};
7068
std::unique_ptr<InstrumentSelector> instrument_selector{
7169
new InstrumentSelector(InstrumentType::kCounter, "instru1", "unit1")};
7270
std::unique_ptr<MeterSelector> meter_selector{new MeterSelector("name1", "version1", "schema1")};

sdk/test/metrics/view_registry_test.cc

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,46 @@ TEST(ViewRegistry, FindNonExistingView)
9393
EXPECT_EQ(status, true);
9494
#endif
9595
}
96+
97+
// Tests for ViewRegistry::AddView null parameter validation
98+
// These should log errors and ignore the call instead of throwing or aborting
99+
100+
TEST(ViewRegistry, AddViewWithNullInstrumentSelector)
101+
{
102+
ViewRegistry registry;
103+
std::unique_ptr<MeterSelector> meter_selector{new MeterSelector("name", "version", "schema")};
104+
std::unique_ptr<View> view{new View("test_view")};
105+
106+
// Should not throw or abort, just log and ignore
107+
registry.AddView(nullptr, std::move(meter_selector), std::move(view));
108+
}
109+
110+
TEST(ViewRegistry, AddViewWithNullMeterSelector)
111+
{
112+
ViewRegistry registry;
113+
std::unique_ptr<InstrumentSelector> instrument_selector{
114+
new InstrumentSelector(InstrumentType::kCounter, "instrument_name", "unit")};
115+
std::unique_ptr<View> view{new View("test_view")};
116+
117+
// Should not throw or abort, just log and ignore
118+
registry.AddView(std::move(instrument_selector), nullptr, std::move(view));
119+
}
120+
121+
TEST(ViewRegistry, AddViewWithNullView)
122+
{
123+
ViewRegistry registry;
124+
std::unique_ptr<InstrumentSelector> instrument_selector{
125+
new InstrumentSelector(InstrumentType::kCounter, "instrument_name", "unit")};
126+
std::unique_ptr<MeterSelector> meter_selector{new MeterSelector("name", "version", "schema")};
127+
128+
// Should not throw or abort, just log and ignore
129+
registry.AddView(std::move(instrument_selector), std::move(meter_selector), nullptr);
130+
}
131+
132+
TEST(ViewRegistry, AddViewWithAllNullParameters)
133+
{
134+
ViewRegistry registry;
135+
136+
// Should not throw or abort, just log and ignore
137+
registry.AddView(nullptr, nullptr, nullptr);
138+
}

0 commit comments

Comments
 (0)