From e7ea33d72be8c3f9cd64445ed5a6796cf4b5561d Mon Sep 17 00:00:00 2001 From: Joshua Date: Sun, 18 Jan 2026 22:33:50 -0500 Subject: [PATCH 1/8] exporters/otlp: implement collection limits logic in OtlpRecordable Signed-off-by: Joshua --- .../exporters/otlp/otlp_recordable.h | 17 ++++++++++++ exporters/otlp/src/otlp_recordable.cc | 27 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h index 103357d11f..18c692c27c 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h @@ -35,6 +35,18 @@ namespace otlp class OtlpRecordable final : public opentelemetry::sdk::trace::Recordable { public: + explicit OtlpRecordable(uint32_t max_attributes = UINT32_MAX, + uint32_t max_events = UINT32_MAX, + uint32_t max_links = UINT32_MAX, + uint32_t max_attributes_per_event = UINT32_MAX, + uint32_t max_attributes_per_link = UINT32_MAX) + : max_attributes_(max_attributes), + max_events_(max_events), + max_links_(max_links), + max_attributes_per_event_(max_attributes_per_event), + max_attributes_per_link_(max_attributes_per_link) + {} + proto::trace::v1::Span &span() noexcept { return span_; } const proto::trace::v1::Span &span() const noexcept { return span_; } @@ -85,6 +97,11 @@ class OtlpRecordable final : public opentelemetry::sdk::trace::Recordable const opentelemetry::sdk::resource::Resource *resource_ = nullptr; const opentelemetry::sdk::instrumentationscope::InstrumentationScope *instrumentation_scope_ = nullptr; + uint32_t max_attributes_; + uint32_t max_events_; + uint32_t max_links_; + uint32_t max_attributes_per_event_; + uint32_t max_attributes_per_link_; }; } // namespace otlp } // namespace exporter diff --git a/exporters/otlp/src/otlp_recordable.cc b/exporters/otlp/src/otlp_recordable.cc index 3564448787..6bf4e89267 100644 --- a/exporters/otlp/src/otlp_recordable.cc +++ b/exporters/otlp/src/otlp_recordable.cc @@ -120,6 +120,12 @@ void OtlpRecordable::SetResource(const sdk::resource::Resource &resource) noexce void OtlpRecordable::SetAttribute(nostd::string_view key, const common::AttributeValue &value) noexcept { + if (span_.attributes_size() >= max_attributes_) + { + span_.set_dropped_attributes_count(span_.dropped_attributes_count() + 1); + return; + } + auto *attribute = span_.add_attributes(); OtlpPopulateAttributeUtils::PopulateAttribute(attribute, key, value, false); } @@ -128,11 +134,22 @@ void OtlpRecordable::AddEvent(nostd::string_view name, common::SystemTimestamp timestamp, const common::KeyValueIterable &attributes) noexcept { + if (span_.events_size() >= max_events_) + { + span_.set_dropped_events_count(span_.dropped_events_count() + 1); + return; + } + auto *event = span_.add_events(); event->set_name(name.data(), name.size()); event->set_time_unix_nano(timestamp.time_since_epoch().count()); attributes.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { + if (event->attributes_size() >= max_attributes_per_event_) + { + event->set_dropped_attributes_count(event->dropped_attributes_count() + 1); + return true; + } OtlpPopulateAttributeUtils::PopulateAttribute(event->add_attributes(), key, value, false); return true; }); @@ -141,6 +158,11 @@ void OtlpRecordable::AddEvent(nostd::string_view name, void OtlpRecordable::AddLink(const trace::SpanContext &span_context, const common::KeyValueIterable &attributes) noexcept { + if (span_.links_size() >= max_links_) + { + span_.set_dropped_links_count(span_.dropped_links_count() + 1); + return; + } auto *link = span_.add_links(); link->set_trace_id(reinterpret_cast(span_context.trace_id().Id().data()), trace::TraceId::kSize); @@ -148,6 +170,11 @@ void OtlpRecordable::AddLink(const trace::SpanContext &span_context, trace::SpanId::kSize); link->set_trace_state(span_context.trace_state()->ToHeader()); attributes.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { + if (link->attributes_size() >= max_attributes_per_link_) + { + link->set_dropped_attributes_count(link->dropped_attributes_count() + 1); + return true; + } OtlpPopulateAttributeUtils::PopulateAttribute(link->add_attributes(), key, value, false); return true; }); From 3a11c315e481539e179eff65777c3066f41dc53d Mon Sep 17 00:00:00 2001 From: Joshua Date: Sun, 18 Jan 2026 22:44:48 -0500 Subject: [PATCH 2/8] exporters/otlp: add limit options to OTLP exporter configuration Signed-off-by: Joshua --- .../exporters/otlp/otlp_grpc_exporter_options.h | 7 +++++++ .../exporters/otlp/otlp_http_exporter_options.h | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h index 4fceaa9151..6907ab57ca 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h @@ -32,6 +32,13 @@ struct OPENTELEMETRY_EXPORT OtlpGrpcExporterOptions : public OtlpGrpcClientOptio OtlpGrpcExporterOptions &operator=(const OtlpGrpcExporterOptions &) = default; OtlpGrpcExporterOptions &operator=(OtlpGrpcExporterOptions &&) = default; ~OtlpGrpcExporterOptions() override; + + /** Collection Limits. No limit by default. */ + std::uint32_t max_attributes = UINT32_MAX; + std::uint32_t max_events = UINT32_MAX; + std::uint32_t max_links = UINT32_MAX; + std::uint32_t max_attributes_per_event = UINT32_MAX; + std::uint32_t max_attributes_per_link = UINT32_MAX; }; } // namespace otlp diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter_options.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter_options.h index 93e15ed887..457a442346 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter_options.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter_options.h @@ -125,6 +125,13 @@ struct OPENTELEMETRY_EXPORT OtlpHttpExporterOptions /** The backoff will be multiplied by this value after each retry attempt. */ float retry_policy_backoff_multiplier{}; + + /** Collection Limits. No limit by default. */ + std::uint32_t max_attributes = UINT32_MAX; + std::uint32_t max_events = UINT32_MAX; + std::uint32_t max_links = UINT32_MAX; + std::uint32_t max_attributes_per_event = UINT32_MAX; + std::uint32_t max_attributes_per_link = UINT32_MAX; }; } // namespace otlp From 787f6d03cb604b876df149d21cdd3a37c036fbac Mon Sep 17 00:00:00 2001 From: Joshua Date: Sun, 18 Jan 2026 22:57:23 -0500 Subject: [PATCH 3/8] exporters/otlp: apply configured limits in OTLP exporters Signed-off-by: Joshua --- exporters/otlp/src/otlp_grpc_exporter.cc | 4 +++- exporters/otlp/src/otlp_http_exporter.cc | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/exporters/otlp/src/otlp_grpc_exporter.cc b/exporters/otlp/src/otlp_grpc_exporter.cc index cd61dfae68..fa665ed4e4 100644 --- a/exporters/otlp/src/otlp_grpc_exporter.cc +++ b/exporters/otlp/src/otlp_grpc_exporter.cc @@ -97,7 +97,9 @@ OtlpGrpcExporter::~OtlpGrpcExporter() std::unique_ptr OtlpGrpcExporter::MakeRecordable() noexcept { - return std::unique_ptr(new OtlpRecordable); + return std::unique_ptr( + new OtlpRecordable(options_.max_attributes, options_.max_events, options_.max_links, + options_.max_attributes_per_event, options_.max_attributes_per_link)); } sdk::common::ExportResult OtlpGrpcExporter::Export( diff --git a/exporters/otlp/src/otlp_http_exporter.cc b/exporters/otlp/src/otlp_http_exporter.cc index 6eaf1eed22..499d577185 100644 --- a/exporters/otlp/src/otlp_http_exporter.cc +++ b/exporters/otlp/src/otlp_http_exporter.cc @@ -140,8 +140,9 @@ OtlpHttpExporter::OtlpHttpExporter(std::unique_ptr http_client) std::unique_ptr OtlpHttpExporter::MakeRecordable() noexcept { - return std::unique_ptr( - new exporter::otlp::OtlpRecordable()); + return std::unique_ptr(new exporter::otlp::OtlpRecordable( + options_.max_attributes, options_.max_events, options_.max_links, + options_.max_attributes_per_event, options_.max_attributes_per_link)); } opentelemetry::sdk::common::ExportResult OtlpHttpExporter::Export( From 01b4aa00cdd1c5de858717cf69c19bfa773b89df Mon Sep 17 00:00:00 2001 From: Joshua Date: Sun, 18 Jan 2026 23:18:07 -0500 Subject: [PATCH 4/8] exporters/otlp: add unit tests for collection limits Signed-off-by: Joshua --- exporters/otlp/test/otlp_recordable_test.cc | 41 +++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/exporters/otlp/test/otlp_recordable_test.cc b/exporters/otlp/test/otlp_recordable_test.cc index 70016de15a..221571dca2 100644 --- a/exporters/otlp/test/otlp_recordable_test.cc +++ b/exporters/otlp/test/otlp_recordable_test.cc @@ -598,6 +598,47 @@ TYPED_TEST(IntAttributeTest, SetIntArrayAttribute) EXPECT_EQ(rec.span().attributes(0).value().array_value().values(i).int_value(), int_span[i]); } } + +TEST(OtlpRecordableTest, TestCollectionLimits) +{ + // Initialize recordable with strict limits: + // Max Attributes: 2, Max Events: 2, Max Links: 2 + // Max Attributes Per Event: 1, Max Attributes Per Link: 1 + OtlpRecordable recordable(2, 2, 2, 1, 1); + + // Test Attribute Limits + recordable.SetAttribute("attr1", 1); + recordable.SetAttribute("attr2", 2); + recordable.SetAttribute("attr3", 3); // Should be dropped + + EXPECT_EQ(recordable.span().attributes_size(), 2); + EXPECT_EQ(recordable.span().dropped_attributes_count(), 1); + + // Test Event Limits + std::map empty_map; + common::KeyValueIterableView> empty_attrs(empty_map); + + recordable.AddEvent("event1", std::chrono::system_clock::now(), empty_attrs); + recordable.AddEvent("event2", std::chrono::system_clock::now(), empty_attrs); + recordable.AddEvent("event3", std::chrono::system_clock::now(), + empty_attrs); // Should be dropped + + EXPECT_EQ(recordable.span().events_size(), 2); + EXPECT_EQ(recordable.span().dropped_events_count(), 1); + + // Test Per-Event Attribute Limits + std::map attr_map = {{"e_attr1", 1}, {"e_attr2", 2}}; + common::KeyValueIterableView> event_attrs(attr_map); + + OtlpRecordable event_recordable(10, 10, 10, 1, 1); + event_recordable.AddEvent("event_with_attrs", std::chrono::system_clock::now(), event_attrs); + + auto &event_list = event_recordable.span().events(); + ASSERT_EQ(event_list.size(), 1); + // The event itself should have 1 attribute, and 1 dropped + EXPECT_EQ(event_list[0].attributes_size(), 1); + EXPECT_EQ(event_list[0].dropped_attributes_count(), 1); +} } // namespace otlp } // namespace exporter OPENTELEMETRY_END_NAMESPACE From 52e38cea726d8ace2a59d329d052b1f7da05e632 Mon Sep 17 00:00:00 2001 From: Joshua Date: Mon, 19 Jan 2026 16:45:11 +0000 Subject: [PATCH 5/8] fix: resolve signed/unsigned comparison warnings in OtlpRecordable Signed-off-by: Joshua --- .../opentelemetry/exporters/otlp/otlp_recordable.h | 2 ++ exporters/otlp/src/otlp_recordable.cc | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h index 18c692c27c..d01710b448 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h @@ -4,6 +4,8 @@ #pragma once #include +#include // For uint32_t +#include // For UINT32_MAX #include // clang-format off diff --git a/exporters/otlp/src/otlp_recordable.cc b/exporters/otlp/src/otlp_recordable.cc index 6bf4e89267..c5745856a4 100644 --- a/exporters/otlp/src/otlp_recordable.cc +++ b/exporters/otlp/src/otlp_recordable.cc @@ -120,7 +120,7 @@ void OtlpRecordable::SetResource(const sdk::resource::Resource &resource) noexce void OtlpRecordable::SetAttribute(nostd::string_view key, const common::AttributeValue &value) noexcept { - if (span_.attributes_size() >= max_attributes_) + if (static_cast(span_.attributes_size()) >= max_attributes_) { span_.set_dropped_attributes_count(span_.dropped_attributes_count() + 1); return; @@ -134,7 +134,7 @@ void OtlpRecordable::AddEvent(nostd::string_view name, common::SystemTimestamp timestamp, const common::KeyValueIterable &attributes) noexcept { - if (span_.events_size() >= max_events_) + if (static_cast(span_.events_size()) >= max_events_) { span_.set_dropped_events_count(span_.dropped_events_count() + 1); return; @@ -145,7 +145,7 @@ void OtlpRecordable::AddEvent(nostd::string_view name, event->set_time_unix_nano(timestamp.time_since_epoch().count()); attributes.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { - if (event->attributes_size() >= max_attributes_per_event_) + if (static_cast(event->attributes_size()) >= max_attributes_per_event_) { event->set_dropped_attributes_count(event->dropped_attributes_count() + 1); return true; @@ -158,7 +158,7 @@ void OtlpRecordable::AddEvent(nostd::string_view name, void OtlpRecordable::AddLink(const trace::SpanContext &span_context, const common::KeyValueIterable &attributes) noexcept { - if (span_.links_size() >= max_links_) + if (static_cast(span_.links_size()) >= max_links_) { span_.set_dropped_links_count(span_.dropped_links_count() + 1); return; @@ -170,7 +170,7 @@ void OtlpRecordable::AddLink(const trace::SpanContext &span_context, trace::SpanId::kSize); link->set_trace_state(span_context.trace_state()->ToHeader()); attributes.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { - if (link->attributes_size() >= max_attributes_per_link_) + if (static_cast(link->attributes_size()) >= max_attributes_per_link_) { link->set_dropped_attributes_count(link->dropped_attributes_count() + 1); return true; From 1b95ee84e9b1a47a5106e0f4389718375f9b98f5 Mon Sep 17 00:00:00 2001 From: Joshua Date: Wed, 28 Jan 2026 03:25:34 +0000 Subject: [PATCH 6/8] fix: use std::numeric_limits instead of macro Signed-off-by: Joshua --- .../exporters/otlp/otlp_grpc_exporter_options.h | 12 +++++++----- .../exporters/otlp/otlp_http_exporter_options.h | 11 ++++++----- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h index 6907ab57ca..cb841a749e 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h @@ -3,6 +3,8 @@ #pragma once +#include +#include #include "opentelemetry/exporters/otlp/otlp_grpc_client_options.h" #include "opentelemetry/version.h" @@ -34,11 +36,11 @@ struct OPENTELEMETRY_EXPORT OtlpGrpcExporterOptions : public OtlpGrpcClientOptio ~OtlpGrpcExporterOptions() override; /** Collection Limits. No limit by default. */ - std::uint32_t max_attributes = UINT32_MAX; - std::uint32_t max_events = UINT32_MAX; - std::uint32_t max_links = UINT32_MAX; - std::uint32_t max_attributes_per_event = UINT32_MAX; - std::uint32_t max_attributes_per_link = UINT32_MAX; + std::uint32_t max_attributes = std::numeric_limits::max(); + std::uint32_t max_events = std::numeric_limits::max(); + std::uint32_t max_links = std::numeric_limits::max(); + std::uint32_t max_attributes_per_event = std::numeric_limits::max(); + std::uint32_t max_attributes_per_link = std::numeric_limits::max(); }; } // namespace otlp diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter_options.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter_options.h index 457a442346..08177e34e7 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter_options.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter_options.h @@ -5,6 +5,7 @@ #include #include +#include #include #include "opentelemetry/exporters/otlp/otlp_environment.h" @@ -127,11 +128,11 @@ struct OPENTELEMETRY_EXPORT OtlpHttpExporterOptions float retry_policy_backoff_multiplier{}; /** Collection Limits. No limit by default. */ - std::uint32_t max_attributes = UINT32_MAX; - std::uint32_t max_events = UINT32_MAX; - std::uint32_t max_links = UINT32_MAX; - std::uint32_t max_attributes_per_event = UINT32_MAX; - std::uint32_t max_attributes_per_link = UINT32_MAX; + std::uint32_t max_attributes = std::numeric_limits::max(); + std::uint32_t max_events = std::numeric_limits::max(); + std::uint32_t max_links = std::numeric_limits::max(); + std::uint32_t max_attributes_per_event = std::numeric_limits::max(); + std::uint32_t max_attributes_per_link = std::numeric_limits::max(); }; } // namespace otlp From 0b481af71512b776e3068af7433c9ee200ebd48a Mon Sep 17 00:00:00 2001 From: Joshua Date: Fri, 30 Jan 2026 03:27:29 +0000 Subject: [PATCH 7/8] fix: links test, types, changelog updated Signed-off-by: Joshua --- CHANGELOG.md | 3 ++ .../exporters/otlp/otlp_recordable.h | 25 ++++++------- exporters/otlp/test/otlp_recordable_test.cc | 36 +++++++++++++++++++ 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 105676c8db..fc3c11722e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,9 @@ Increment the: * [ETW] Fix ETW Log Exporter: incorrect timestamp, traceId, and spanId [#3836](https://github.com/open-telemetry/opentelemetry-cpp/pull/3836) +* [OTLP] Add collection limits configuration (max attributes, events, links) to OTLP Exporters. + [#3303](https://github.com/open-telemetry/opentelemetry-cpp/pull/3303) + * [ETW] Fix infinite loop in ETWProvider::close [#3827](https://github.com/open-telemetry/opentelemetry-cpp/pull/3827) diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h index d01710b448..421de7647a 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h @@ -4,8 +4,8 @@ #pragma once #include -#include // For uint32_t -#include // For UINT32_MAX +#include // For std::uint32_t +#include // For std::numeric_limits #include // clang-format off @@ -37,11 +37,12 @@ namespace otlp class OtlpRecordable final : public opentelemetry::sdk::trace::Recordable { public: - explicit OtlpRecordable(uint32_t max_attributes = UINT32_MAX, - uint32_t max_events = UINT32_MAX, - uint32_t max_links = UINT32_MAX, - uint32_t max_attributes_per_event = UINT32_MAX, - uint32_t max_attributes_per_link = UINT32_MAX) + explicit OtlpRecordable( + std::uint32_t max_attributes = std::numeric_limits::max(), + std::uint32_t max_events = std::numeric_limits::max(), + std::uint32_t max_links = std::numeric_limits::max(), + std::uint32_t max_attributes_per_event = std::numeric_limits::max(), + std::uint32_t max_attributes_per_link = std::numeric_limits::max()) : max_attributes_(max_attributes), max_events_(max_events), max_links_(max_links), @@ -99,11 +100,11 @@ class OtlpRecordable final : public opentelemetry::sdk::trace::Recordable const opentelemetry::sdk::resource::Resource *resource_ = nullptr; const opentelemetry::sdk::instrumentationscope::InstrumentationScope *instrumentation_scope_ = nullptr; - uint32_t max_attributes_; - uint32_t max_events_; - uint32_t max_links_; - uint32_t max_attributes_per_event_; - uint32_t max_attributes_per_link_; + std::uint32_t max_attributes_; + std::uint32_t max_events_; + std::uint32_t max_links_; + std::uint32_t max_attributes_per_event_; + std::uint32_t max_attributes_per_link_; }; } // namespace otlp } // namespace exporter diff --git a/exporters/otlp/test/otlp_recordable_test.cc b/exporters/otlp/test/otlp_recordable_test.cc index 221571dca2..9eca9fcc28 100644 --- a/exporters/otlp/test/otlp_recordable_test.cc +++ b/exporters/otlp/test/otlp_recordable_test.cc @@ -639,6 +639,42 @@ TEST(OtlpRecordableTest, TestCollectionLimits) EXPECT_EQ(event_list[0].attributes_size(), 1); EXPECT_EQ(event_list[0].dropped_attributes_count(), 1); } + +TEST(OtlpRecordableTest, TestLinkLimits) +{ + // Limits: Max Links: 2, Max Attributes Per Link: 1 + OtlpRecordable recordable(10, 10, 2, 10, 1); + + // Dummy SpanContext for the links + trace::SpanContext context = trace::SpanContext::GetInvalid(); + + // Test Link Limits + // Create an empty attribute map for the links + std::map empty_map; + common::KeyValueIterableView> empty_attrs(empty_map); + + recordable.AddLink(context, empty_attrs); + recordable.AddLink(context, empty_attrs); + recordable.AddLink(context, empty_attrs); // Should be dropped (Max 2) + + EXPECT_EQ(recordable.span().links_size(), 2); + EXPECT_EQ(recordable.span().dropped_links_count(), 1); + + // Test Per-Link Attribute Limits + // Create a map with 2 attributes. Limit is 1 + std::map attr_map = {{"l_attr1", 1}, {"l_attr2", 2}}; + common::KeyValueIterableView> link_attrs(attr_map); + + // Create a new recordable for this sub-test + OtlpRecordable link_recordable(10, 10, 10, 10, 1); + link_recordable.AddLink(context, link_attrs); + + auto &link_list = link_recordable.span().links(); + ASSERT_EQ(link_list.size(), 1); + // The link itself should have 1 attribute kept, 1 dropped + EXPECT_EQ(link_list[0].attributes_size(), 1); + EXPECT_EQ(link_list[0].dropped_attributes_count(), 1); +} } // namespace otlp } // namespace exporter OPENTELEMETRY_END_NAMESPACE From 3f283aa5595af4e6424378b0ff9fe9231c26028b Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Sat, 31 Jan 2026 12:38:16 +0100 Subject: [PATCH 8/8] Apply suggestions from code review --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc3c11722e..07876c9fb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,8 +18,8 @@ Increment the: * [ETW] Fix ETW Log Exporter: incorrect timestamp, traceId, and spanId [#3836](https://github.com/open-telemetry/opentelemetry-cpp/pull/3836) -* [OTLP] Add collection limits configuration (max attributes, events, links) to OTLP Exporters. - [#3303](https://github.com/open-telemetry/opentelemetry-cpp/pull/3303) +* [EXPORTER] Add support for otlp exporter collection limits + [#3816](https://github.com/open-telemetry/opentelemetry-cpp/pull/3816) * [ETW] Fix infinite loop in ETWProvider::close [#3827](https://github.com/open-telemetry/opentelemetry-cpp/pull/3827)