Skip to content
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
a2c48c6
Add tag to AggregationConfig for type checking
ThomsonTan Oct 29, 2025
d2330d1
Add test
ThomsonTan Oct 31, 2025
177d85a
Fix format
ThomsonTan Oct 31, 2025
db221d8
Address feedback
ThomsonTan Oct 31, 2025
7ec33ec
Merge branch 'main' into add_tag_to_aggregationconfig
ThomsonTan Oct 31, 2025
4d9331c
Merge branch 'main' into add_tag_to_aggregationconfig
ThomsonTan Nov 3, 2025
5dfc194
Support build without exception
ThomsonTan Nov 3, 2025
2c4266b
Remove logging
ThomsonTan Nov 3, 2025
6f04f06
Handle unittest in noexception build
ThomsonTan Nov 3, 2025
363eb46
Fix EXPECT_NO_THROW for no-exception build
ThomsonTan Nov 4, 2025
b500f61
Fix iwyu
ThomsonTan Nov 4, 2025
af73f3a
Move check to AddView
ThomsonTan Nov 5, 2025
f28235c
Merge branch 'main' into add_tag_to_aggregationconfig
ThomsonTan Nov 5, 2025
6179d6f
Handle kDefault in AddView
ThomsonTan Nov 5, 2025
d3b4c42
Fix meter provider test
ThomsonTan Nov 5, 2025
8e2a1b0
Merge branch 'main' into add_tag_to_aggregationconfig
ThomsonTan Nov 5, 2025
9dd5eae
Fix iwyu
ThomsonTan Nov 5, 2025
36ef49a
Remove noexcept on AddView
ThomsonTan Nov 5, 2025
5e96531
Add changelog
ThomsonTan Nov 6, 2025
f30cea6
Update changelog
ThomsonTan Nov 6, 2025
f150c4a
Merge branch 'main' into add_tag_to_aggregationconfig
ThomsonTan Nov 6, 2025
4b27470
Merge branch 'main' into add_tag_to_aggregationconfig
ThomsonTan Nov 6, 2025
4400651
Merge branch 'main' into add_tag_to_aggregationconfig
ThomsonTan Nov 7, 2025
a530053
Merge branch 'main' into add_tag_to_aggregationconfig
ThomsonTan Nov 10, 2025
01889b2
Log View validation error and ignore it
ThomsonTan Nov 10, 2025
3867d1d
Add back noexcept on AddView
ThomsonTan Nov 10, 2025
c1c5d0a
Add noexcept back to AddView implementation
ThomsonTan Nov 10, 2025
83f6394
Merge branch 'main' into add_tag_to_aggregationconfig
ThomsonTan Nov 14, 2025
b61e528
Address feedback
ThomsonTan Nov 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ Increment the:

## [Unreleased]

* [METRICS] Add tag to AggregationConfig for aggregation type validation
[#3732](https://github.com/open-telemetry/opentelemetry-cpp/pull/3732)

* [TEST] Remove workaround for metrics cardinality limit test
[#3663](https://github.com/open-telemetry/opentelemetry-cpp/pull/3663)

* [METRICS] Allow registering one callback for multiple instruments
[#3667](https://github.com/open-telemetry/opentelemetry-cpp/pull/3667)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <vector>

#include "opentelemetry/sdk/metrics/instruments.h"
#include "opentelemetry/sdk/metrics/state/attributes_hashmap.h"
#include "opentelemetry/version.h"

Expand All @@ -13,13 +14,16 @@ namespace sdk
{
namespace metrics
{

class AggregationConfig
{
public:
AggregationConfig(size_t cardinality_limit = kAggregationCardinalityLimit)
: cardinality_limit_(cardinality_limit)
{}

virtual AggregationType GetType() const noexcept { return AggregationType::kDefault; }

static const AggregationConfig *GetOrDefault(const AggregationConfig *config)
{
if (config)
Expand All @@ -41,6 +45,8 @@ class HistogramAggregationConfig : public AggregationConfig
: AggregationConfig(cardinality_limit)
{}

AggregationType GetType() const noexcept override { return AggregationType::kHistogram; }

std::vector<double> boundaries_;
bool record_min_max_ = true;
};
Expand All @@ -53,6 +59,11 @@ class Base2ExponentialHistogramAggregationConfig : public AggregationConfig
: AggregationConfig(cardinality_limit)
{}

AggregationType GetType() const noexcept override
{
return AggregationType::kBase2ExponentialHistogram;
}

size_t max_buckets_ = 160;
int32_t max_scale_ = 20;
bool record_min_max_ = true;
Expand Down
2 changes: 1 addition & 1 deletion sdk/include/opentelemetry/sdk/metrics/meter_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class MeterContext : public std::enable_shared_from_this<MeterContext>
*/
void AddView(std::unique_ptr<InstrumentSelector> instrument_selector,
std::unique_ptr<MeterSelector> meter_selector,
std::unique_ptr<View> view) noexcept;
std::unique_ptr<View> view);

#ifdef ENABLE_METRICS_EXEMPLAR_PREVIEW

Expand Down
1 change: 1 addition & 0 deletions sdk/include/opentelemetry/sdk/metrics/view/view.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#pragma once

#include <memory>
#include <stdexcept>
#include <string>

#include "opentelemetry/sdk/metrics/aggregation/aggregation_config.h"
Expand Down
57 changes: 57 additions & 0 deletions sdk/include/opentelemetry/sdk/metrics/view/view_registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@

#include <algorithm>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>

#include "opentelemetry/nostd/function_ref.h"
#include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
#include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h"
#include "opentelemetry/sdk/metrics/instruments.h"
#include "opentelemetry/sdk/metrics/view/instrument_selector.h"
#include "opentelemetry/sdk/metrics/view/meter_selector.h"
Expand Down Expand Up @@ -47,6 +49,61 @@ class ViewRegistry
{
// TBD - thread-safe ?

// Validate parameters
if (!instrument_selector || !meter_selector || !view)
{
#if defined(__cpp_exceptions)
throw std::invalid_argument("instrument_selector, meter_selector, and view cannot be null");
#else
std::abort();
#endif
}
Comment on lines 55 to 60
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For every other failures in general, like illegal instrument names, the code just logs an error and ignores the instrument / view.

We should not throw exceptions or worse kill the process here, only ignore invalid configuration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced throw/abort with internal error log and ignores it.


auto aggregation_config = view->GetAggregationConfig();
if (aggregation_config)
{
bool valid = false;
auto aggregation_config_type = aggregation_config->GetType();
auto aggregation_type = view->GetAggregationType();

if (aggregation_type == AggregationType::kDefault)
{
bool is_monotonic;
aggregation_type = DefaultAggregation::GetDefaultAggregationType(
instrument_selector->GetInstrumentType(), is_monotonic);
}

switch (aggregation_type)
{
case AggregationType::kHistogram:
valid = (aggregation_config_type == AggregationType::kHistogram);
break;

case AggregationType::kBase2ExponentialHistogram:
valid = (aggregation_config_type == AggregationType::kBase2ExponentialHistogram);
break;

case AggregationType::kDrop:
case AggregationType::kLastValue:
case AggregationType::kSum:
valid = (aggregation_config_type == AggregationType::kDefault);
break;

default:
// Unreachable: all AggregationType enum values are handled above
std::abort();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit - this can be a utility method say IsDefaultAggregation(agg_type, inst_type, is_monotinic) in default_aggregation.h, but can be done afterwards if required at other places.

}

if (!valid)
{
#if defined(__cpp_exceptions)
throw std::invalid_argument("AggregationType and AggregationConfig type mismatch");
#else
std::abort();
#endif
}
}

auto registered_view = std::unique_ptr<RegisteredView>(new RegisteredView{
std::move(instrument_selector), std::move(meter_selector), std::move(view)});
registered_views_.push_back(std::move(registered_view));
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/metrics/meter_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ void MeterContext::AddMetricReader(std::shared_ptr<MetricReader> reader,

void MeterContext::AddView(std::unique_ptr<InstrumentSelector> instrument_selector,
std::unique_ptr<MeterSelector> meter_selector,
std::unique_ptr<View> view) noexcept
std::unique_ptr<View> view)
{
views_->AddView(std::move(instrument_selector), std::move(meter_selector), std::move(view));
}
Expand Down
4 changes: 1 addition & 3 deletions sdk/test/metrics/meter_provider_sdk_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ using namespace opentelemetry::sdk::metrics;
TEST(MeterProvider, GetMeter)
{
MeterProvider mp1;
// std::unique_ptr<View> view{std::unique_ptr<View>()};
// MeterProvider mp1(std::move(exporters), std::move(readers), std::move(views);
auto m1 = mp1.GetMeter("test");
auto m2 = mp1.GetMeter("test");
auto m3 = mp1.GetMeter("different", "1.0.0");
Expand Down Expand Up @@ -66,7 +64,7 @@ TEST(MeterProvider, GetMeter)
std::unique_ptr<MetricReader> reader{new MockMetricReader(std::move(exporter))};
mp1.AddMetricReader(std::move(reader));

std::unique_ptr<View> view{std::unique_ptr<View>()};
std::unique_ptr<View> view{new View("test_view")};
std::unique_ptr<InstrumentSelector> instrument_selector{
new InstrumentSelector(InstrumentType::kCounter, "instru1", "unit1")};
std::unique_ptr<MeterSelector> meter_selector{new MeterSelector("name1", "version1", "schema1")};
Expand Down
63 changes: 63 additions & 0 deletions sdk/test/metrics/view_registry_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

#include <gtest/gtest.h>
#include <stdexcept>
#include <string>
#include <utility>

Expand Down Expand Up @@ -93,3 +94,65 @@ TEST(ViewRegistry, FindNonExistingView)
EXPECT_EQ(status, true);
#endif
}

// Tests for ViewRegistry::AddView null parameter validation

TEST(ViewRegistry, AddViewWithNullInstrumentSelector)
{
ViewRegistry registry;
std::unique_ptr<MeterSelector> meter_selector{new MeterSelector("name", "version", "schema")};
std::unique_ptr<View> view{new View("test_view")};

#if defined(__cpp_exceptions)
EXPECT_THROW(
{ registry.AddView(nullptr, std::move(meter_selector), std::move(view)); },
std::invalid_argument);
#else
EXPECT_DEATH({ registry.AddView(nullptr, std::move(meter_selector), std::move(view)); }, "");
#endif
}

TEST(ViewRegistry, AddViewWithNullMeterSelector)
{
ViewRegistry registry;
std::unique_ptr<InstrumentSelector> instrument_selector{
new InstrumentSelector(InstrumentType::kCounter, "instrument_name", "unit")};
std::unique_ptr<View> view{new View("test_view")};

#if defined(__cpp_exceptions)
EXPECT_THROW(
{ registry.AddView(std::move(instrument_selector), nullptr, std::move(view)); },
std::invalid_argument);
#else
EXPECT_DEATH({ registry.AddView(std::move(instrument_selector), nullptr, std::move(view)); }, "");
#endif
}

TEST(ViewRegistry, AddViewWithNullView)
{
ViewRegistry registry;
std::unique_ptr<InstrumentSelector> instrument_selector{
new InstrumentSelector(InstrumentType::kCounter, "instrument_name", "unit")};
std::unique_ptr<MeterSelector> meter_selector{new MeterSelector("name", "version", "schema")};

#if defined(__cpp_exceptions)
EXPECT_THROW(
{ registry.AddView(std::move(instrument_selector), std::move(meter_selector), nullptr); },
std::invalid_argument);
#else
EXPECT_DEATH(
{ registry.AddView(std::move(instrument_selector), std::move(meter_selector), nullptr); },
"");
#endif
}

TEST(ViewRegistry, AddViewWithAllNullParameters)
{
ViewRegistry registry;

#if defined(__cpp_exceptions)
EXPECT_THROW({ registry.AddView(nullptr, nullptr, nullptr); }, std::invalid_argument);
#else
EXPECT_DEATH({ registry.AddView(nullptr, nullptr, nullptr); }, "");
#endif
}
Loading