diff --git a/sdk/include/opentelemetry/sdk/configuration/periodic_metric_reader_builder.h b/sdk/include/opentelemetry/sdk/configuration/periodic_metric_reader_builder.h new file mode 100644 index 000000000..d209fb153 --- /dev/null +++ b/sdk/include/opentelemetry/sdk/configuration/periodic_metric_reader_builder.h @@ -0,0 +1,36 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include + +#include "opentelemetry/sdk/configuration/periodic_metric_reader_configuration.h" +#include "opentelemetry/sdk/metrics/metric_reader.h" +#include "opentelemetry/sdk/metrics/push_metric_exporter.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace configuration +{ + +class PeriodicMetricReaderBuilder +{ +public: + PeriodicMetricReaderBuilder() = default; + PeriodicMetricReaderBuilder(PeriodicMetricReaderBuilder &&) = default; + PeriodicMetricReaderBuilder(const PeriodicMetricReaderBuilder &) = default; + PeriodicMetricReaderBuilder &operator=(PeriodicMetricReaderBuilder &&) = default; + PeriodicMetricReaderBuilder &operator=(const PeriodicMetricReaderBuilder &other) = default; + virtual ~PeriodicMetricReaderBuilder() = default; + + virtual std::unique_ptr Build( + const opentelemetry::sdk::configuration::PeriodicMetricReaderConfiguration *model, + std::unique_ptr &&exporter) const = 0; +}; + +} // namespace configuration +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/sdk/include/opentelemetry/sdk/configuration/registry.h b/sdk/include/opentelemetry/sdk/configuration/registry.h index 955c218b0..037afb147 100644 --- a/sdk/include/opentelemetry/sdk/configuration/registry.h +++ b/sdk/include/opentelemetry/sdk/configuration/registry.h @@ -25,6 +25,7 @@ #include "opentelemetry/sdk/configuration/otlp_http_log_record_exporter_builder.h" #include "opentelemetry/sdk/configuration/otlp_http_push_metric_exporter_builder.h" #include "opentelemetry/sdk/configuration/otlp_http_span_exporter_builder.h" +#include "opentelemetry/sdk/configuration/periodic_metric_reader_builder.h" #include "opentelemetry/sdk/configuration/prometheus_pull_metric_exporter_builder.h" #include "opentelemetry/sdk/configuration/text_map_propagator_builder.h" #include "opentelemetry/version.h" @@ -143,6 +144,16 @@ class Registry prometheus_metric_builder_ = std::move(builder); } + const PeriodicMetricReaderBuilder *GetPeriodicMetricReaderBuilder() const + { + return periodic_metric_reader_builder_.get(); + } + + void SetPeriodicMetricReaderBuilder(std::unique_ptr &&builder) + { + periodic_metric_reader_builder_ = std::move(builder); + } + const OtlpHttpLogRecordExporterBuilder *GetOtlpHttpLogRecordBuilder() const { return otlp_http_log_record_builder_.get(); @@ -246,6 +257,7 @@ class Registry std::unique_ptr otlp_file_push_metric_builder_; std::unique_ptr console_metric_builder_; std::unique_ptr prometheus_metric_builder_; + std::unique_ptr periodic_metric_reader_builder_; std::unique_ptr otlp_http_log_record_builder_; std::unique_ptr otlp_grpc_log_record_builder_; diff --git a/sdk/src/configuration/registry.cc b/sdk/src/configuration/registry.cc index 0671db848..3058e8311 100644 --- a/sdk/src/configuration/registry.cc +++ b/sdk/src/configuration/registry.cc @@ -1,6 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +#include #include #include #include @@ -14,8 +15,14 @@ #include "opentelemetry/sdk/configuration/extension_sampler_builder.h" #include "opentelemetry/sdk/configuration/extension_span_exporter_builder.h" #include "opentelemetry/sdk/configuration/extension_span_processor_builder.h" +#include "opentelemetry/sdk/configuration/periodic_metric_reader_builder.h" +#include "opentelemetry/sdk/configuration/periodic_metric_reader_configuration.h" #include "opentelemetry/sdk/configuration/registry.h" #include "opentelemetry/sdk/configuration/text_map_propagator_builder.h" +#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_factory.h" +#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_options.h" +#include "opentelemetry/sdk/metrics/metric_reader.h" +#include "opentelemetry/sdk/metrics/push_metric_exporter.h" #include "opentelemetry/trace/propagation/b3_propagator.h" #include "opentelemetry/trace/propagation/http_trace_context.h" #include "opentelemetry/trace/propagation/jaeger.h" @@ -80,6 +87,23 @@ class JaegerBuilder : public TextMapPropagatorBuilder } }; +class DefaultPeriodicMetricReaderBuilder : public PeriodicMetricReaderBuilder +{ +public: + std::unique_ptr Build( + const opentelemetry::sdk::configuration::PeriodicMetricReaderConfiguration *model, + std::unique_ptr &&exporter) const override + { + opentelemetry::sdk::metrics::PeriodicExportingMetricReaderOptions options; + + options.export_interval_millis = std::chrono::milliseconds(model->interval); + options.export_timeout_millis = std::chrono::milliseconds(model->timeout); + + return opentelemetry::sdk::metrics::PeriodicExportingMetricReaderFactory::Create( + std::move(exporter), options); + } +}; + } // namespace Registry::Registry() @@ -89,6 +113,8 @@ Registry::Registry() SetTextMapPropagatorBuilder("b3", std::make_unique()); SetTextMapPropagatorBuilder("b3multi", std::make_unique()); SetTextMapPropagatorBuilder("jaeger", std::make_unique()); + + SetPeriodicMetricReaderBuilder(std::make_unique()); } const TextMapPropagatorBuilder *Registry::GetTextMapPropagatorBuilder(const std::string &name) const diff --git a/sdk/src/configuration/sdk_builder.cc b/sdk/src/configuration/sdk_builder.cc index 3d4494e7a..b94ccd279 100644 --- a/sdk/src/configuration/sdk_builder.cc +++ b/sdk/src/configuration/sdk_builder.cc @@ -98,6 +98,7 @@ #include "opentelemetry/sdk/configuration/otlp_http_span_exporter_builder.h" #include "opentelemetry/sdk/configuration/otlp_http_span_exporter_configuration.h" #include "opentelemetry/sdk/configuration/parent_based_sampler_configuration.h" +#include "opentelemetry/sdk/configuration/periodic_metric_reader_builder.h" #include "opentelemetry/sdk/configuration/periodic_metric_reader_configuration.h" #include "opentelemetry/sdk/configuration/prometheus_pull_metric_exporter_builder.h" #include "opentelemetry/sdk/configuration/prometheus_pull_metric_exporter_configuration.h" @@ -145,8 +146,6 @@ #include "opentelemetry/sdk/logs/simple_log_record_processor_factory.h" #include "opentelemetry/sdk/metrics/aggregation/aggregation_config.h" #include "opentelemetry/sdk/metrics/export/metric_producer.h" -#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_factory.h" -#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_options.h" #include "opentelemetry/sdk/metrics/instruments.h" #include "opentelemetry/sdk/metrics/meter_config.h" #include "opentelemetry/sdk/metrics/meter_context.h" @@ -1555,11 +1554,6 @@ std::unique_ptr SdkBuilder::CreatePer { std::unique_ptr sdk; - opentelemetry::sdk::metrics::PeriodicExportingMetricReaderOptions options; - - options.export_interval_millis = std::chrono::milliseconds(model->interval); - options.export_timeout_millis = std::chrono::milliseconds(model->timeout); - auto exporter_sdk = CreatePushMetricExporter(model->exporter); if (model->producers.size() > 0) @@ -1572,10 +1566,17 @@ std::unique_ptr SdkBuilder::CreatePer OTEL_INTERNAL_LOG_WARN("cardinality limits not supported, ignoring"); } - sdk = opentelemetry::sdk::metrics::PeriodicExportingMetricReaderFactory::Create( - std::move(exporter_sdk), options); + const PeriodicMetricReaderBuilder *builder = registry_->GetPeriodicMetricReaderBuilder(); - return sdk; + if (builder != nullptr) + { + OTEL_INTERNAL_LOG_DEBUG("CreatePeriodicMetricReader() using registered builder"); + sdk = builder->Build(model, std::move(exporter_sdk)); + return sdk; + } + + static const std::string die("No builder for PeriodicMetricReader"); + throw UnsupportedException(die); } std::unique_ptr SdkBuilder::CreatePullMetricReader( diff --git a/sdk/test/configuration/BUILD b/sdk/test/configuration/BUILD index 7b3f6ddd6..6ae854dec 100644 --- a/sdk/test/configuration/BUILD +++ b/sdk/test/configuration/BUILD @@ -6,6 +6,7 @@ load("@rules_cc//cc:cc_test.bzl", "cc_test") cc_test( name = "sdk_builder_test", srcs = [ + "config_test_common.h", "sdk_builder_test.cc", ], tags = [ @@ -26,6 +27,7 @@ cc_test( cc_test( name = "configured_sdk_test", srcs = [ + "config_test_common.h", "configured_sdk_test.cc", ], tags = [ @@ -46,6 +48,7 @@ cc_test( cc_test( name = "programmatic_configuration_test", srcs = [ + "config_test_common.h", "programmatic_configuration_test.cc", ], tags = [ diff --git a/sdk/test/configuration/config_test_common.h b/sdk/test/configuration/config_test_common.h new file mode 100644 index 000000000..02629fa1a --- /dev/null +++ b/sdk/test/configuration/config_test_common.h @@ -0,0 +1,448 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Shared test helpers for the SDK configuration tests +// +// Provides: +// Noop Exporters and Builders: +// - NoopSpanExporter / NoopSpanExporterBuilder +// - NoopLogRecordExporter / NoopLogRecordExporterBuilder +// - NoopPushMetricExporter / NoopPeriodicMetricReaderBuilder +// +// Recording Exporters and Builders: (data collection with no threading) +// - RecordingLogRecordExporter / RecordingLogRecordExporterBuilder +// - RecordingSpanExporter / RecordingSpanExporterBuilder +// - SyncMetricReader / SyncPeriodicMetricReaderBuilder +// - CapturedPeriodicReaderArgs / CapturingPeriodicMetricReaderBuilder +// +// Propagator: +// - MapCarrier + +#pragma once + +#include +#include +#include +#include + +#include "opentelemetry/context/propagation/text_map_propagator.h" +#include "opentelemetry/nostd/span.h" +#include "opentelemetry/sdk/common/exporter_utils.h" +#include "opentelemetry/sdk/configuration/extension_log_record_exporter_builder.h" +#include "opentelemetry/sdk/configuration/extension_log_record_exporter_configuration.h" +#include "opentelemetry/sdk/configuration/extension_push_metric_exporter_builder.h" +#include "opentelemetry/sdk/configuration/extension_push_metric_exporter_configuration.h" +#include "opentelemetry/sdk/configuration/extension_span_exporter_builder.h" +#include "opentelemetry/sdk/configuration/extension_span_exporter_configuration.h" +#include "opentelemetry/sdk/configuration/periodic_metric_reader_builder.h" +#include "opentelemetry/sdk/configuration/periodic_metric_reader_configuration.h" +#include "opentelemetry/sdk/logs/exporter.h" +#include "opentelemetry/sdk/logs/read_write_log_record.h" +#include "opentelemetry/sdk/metrics/data/metric_data.h" +#include "opentelemetry/sdk/metrics/export/metric_producer.h" +#include "opentelemetry/sdk/metrics/instruments.h" +#include "opentelemetry/sdk/metrics/metric_reader.h" +#include "opentelemetry/sdk/metrics/push_metric_exporter.h" +#include "opentelemetry/sdk/trace/exporter.h" +#include "opentelemetry/sdk/trace/span_data.h" + +namespace config_test +{ + +// --------------------------------------------------------------------------- +// Export buffer type aliases + +using SpanBuffer = std::vector>; +using LogRecordBuffer = std::vector>; +using MetricBuffer = std::vector; + +// --------------------------------------------------------------------------- +// No-op exporters + +class NoopSpanExporter : public opentelemetry::sdk::trace::SpanExporter +{ +public: + std::unique_ptr MakeRecordable() noexcept override + { + return std::make_unique(); + } + opentelemetry::sdk::common::ExportResult Export( + const opentelemetry::nostd::span> + &) noexcept override + { + return opentelemetry::sdk::common::ExportResult::kSuccess; + } + bool ForceFlush(std::chrono::microseconds) noexcept override { return true; } + bool Shutdown(std::chrono::microseconds) noexcept override { return true; } +}; + +class NoopLogRecordExporter : public opentelemetry::sdk::logs::LogRecordExporter +{ +public: + std::unique_ptr MakeRecordable() noexcept override + { + return std::make_unique(); + } + opentelemetry::sdk::common::ExportResult Export( + const opentelemetry::nostd::span> + &) noexcept override + { + return opentelemetry::sdk::common::ExportResult::kSuccess; + } + bool ForceFlush(std::chrono::microseconds) noexcept override { return true; } + bool Shutdown(std::chrono::microseconds) noexcept override { return true; } +}; + +class NoopPushMetricExporter : public opentelemetry::sdk::metrics::PushMetricExporter +{ +public: + opentelemetry::sdk::common::ExportResult Export( + const opentelemetry::sdk::metrics::ResourceMetrics &) noexcept override + { + return opentelemetry::sdk::common::ExportResult::kSuccess; + } + opentelemetry::sdk::metrics::AggregationTemporality GetAggregationTemporality( + opentelemetry::sdk::metrics::InstrumentType) const noexcept override + { + return opentelemetry::sdk::metrics::AggregationTemporality::kCumulative; + } + bool ForceFlush(std::chrono::microseconds) noexcept override { return true; } + bool Shutdown(std::chrono::microseconds) noexcept override { return true; } +}; + +// --------------------------------------------------------------------------- +// No-op extension builders + +class NoopSpanExporterBuilder + : public opentelemetry::sdk::configuration::ExtensionSpanExporterBuilder +{ +public: + std::unique_ptr Build( + const opentelemetry::sdk::configuration::ExtensionSpanExporterConfiguration *) const override + { + return std::make_unique(); + } +}; + +class NoopLogRecordExporterBuilder + : public opentelemetry::sdk::configuration::ExtensionLogRecordExporterBuilder +{ +public: + std::unique_ptr Build( + const opentelemetry::sdk::configuration::ExtensionLogRecordExporterConfiguration *) + const override + { + return std::make_unique(); + } +}; + +class NoopPushMetricExporterBuilder + : public opentelemetry::sdk::configuration::ExtensionPushMetricExporterBuilder +{ +public: + std::unique_ptr Build( + const opentelemetry::sdk::configuration::ExtensionPushMetricExporterConfiguration *) + const override + { + return std::make_unique(); + } +}; + +// --------------------------------------------------------------------------- +// No-op metric reader + +class NoopMetricReader : public opentelemetry::sdk::metrics::MetricReader +{ +public: + opentelemetry::sdk::metrics::AggregationTemporality GetAggregationTemporality( + opentelemetry::sdk::metrics::InstrumentType) const noexcept override + { + return opentelemetry::sdk::metrics::AggregationTemporality::kCumulative; + } + +private: + bool OnForceFlush(std::chrono::microseconds) noexcept override { return true; } + bool OnShutDown(std::chrono::microseconds) noexcept override { return true; } +}; + +class NoopPeriodicMetricReaderBuilder + : public opentelemetry::sdk::configuration::PeriodicMetricReaderBuilder +{ +public: + std::unique_ptr Build( + const opentelemetry::sdk::configuration::PeriodicMetricReaderConfiguration *, + std::unique_ptr &&exporter) const override + { + auto unused = std::move(exporter); + return std::make_unique(); + } +}; + +// --------------------------------------------------------------------------- +// Recording exporters: capture exported data into shared buffers for +// inspection in integration tests. + +class RecordingSpanExporter : public opentelemetry::sdk::trace::SpanExporter +{ +public: + explicit RecordingSpanExporter(std::shared_ptr buffer) : buffer_(std::move(buffer)) {} + + std::unique_ptr MakeRecordable() noexcept override + { + return std::make_unique(); + } + + opentelemetry::sdk::common::ExportResult Export( + const opentelemetry::nostd::span> + &spans) noexcept override + { + for (auto &span : spans) + { + buffer_->emplace_back(static_cast(span.release())); + } + return opentelemetry::sdk::common::ExportResult::kSuccess; + } + + bool ForceFlush(std::chrono::microseconds) noexcept override { return true; } + bool Shutdown(std::chrono::microseconds) noexcept override { return true; } + +private: + std::shared_ptr buffer_; +}; + +class RecordingLogRecordExporter : public opentelemetry::sdk::logs::LogRecordExporter +{ +public: + explicit RecordingLogRecordExporter(std::shared_ptr buffer) + : buffer_(std::move(buffer)) + {} + + std::unique_ptr MakeRecordable() noexcept override + { + return std::make_unique(); + } + + opentelemetry::sdk::common::ExportResult Export( + const opentelemetry::nostd::span> + &records) noexcept override + { + for (auto &rec : records) + { + buffer_->emplace_back( + static_cast(rec.release())); + } + return opentelemetry::sdk::common::ExportResult::kSuccess; + } + + bool RecordableEnforcesLogRecordLimits() const noexcept override { return true; } + bool ForceFlush(std::chrono::microseconds) noexcept override { return true; } + bool Shutdown(std::chrono::microseconds) noexcept override { return true; } + +private: + std::shared_ptr buffer_; +}; + +class RecordingPushMetricExporter : public opentelemetry::sdk::metrics::PushMetricExporter +{ +public: + explicit RecordingPushMetricExporter(std::shared_ptr buffer) + : buffer_(std::move(buffer)) + {} + + opentelemetry::sdk::common::ExportResult Export( + const opentelemetry::sdk::metrics::ResourceMetrics &resource_metrics) noexcept override + { + for (const auto &scope : resource_metrics.scope_metric_data_) + { + for (const auto &metric : scope.metric_data_) + { + buffer_->emplace_back(metric); + } + } + return opentelemetry::sdk::common::ExportResult::kSuccess; + } + + opentelemetry::sdk::metrics::AggregationTemporality GetAggregationTemporality( + opentelemetry::sdk::metrics::InstrumentType) const noexcept override + { + return opentelemetry::sdk::metrics::AggregationTemporality::kCumulative; + } + + bool ForceFlush(std::chrono::microseconds) noexcept override { return true; } + bool Shutdown(std::chrono::microseconds) noexcept override { return true; } + +private: + std::shared_ptr buffer_; +}; + +// --------------------------------------------------------------------------- +// Recording extension builders + +class RecordingSpanExporterBuilder + : public opentelemetry::sdk::configuration::ExtensionSpanExporterBuilder +{ +public: + explicit RecordingSpanExporterBuilder(std::shared_ptr buffer) + : buffer_(std::move(buffer)) + {} + std::unique_ptr Build( + const opentelemetry::sdk::configuration::ExtensionSpanExporterConfiguration *) const override + { + return std::make_unique(buffer_); + } + +private: + std::shared_ptr buffer_; +}; + +class RecordingLogRecordExporterBuilder + : public opentelemetry::sdk::configuration::ExtensionLogRecordExporterBuilder +{ +public: + explicit RecordingLogRecordExporterBuilder(std::shared_ptr buffer) + : buffer_(std::move(buffer)) + {} + std::unique_ptr Build( + const opentelemetry::sdk::configuration::ExtensionLogRecordExporterConfiguration *) + const override + { + return std::make_unique(buffer_); + } + +private: + std::shared_ptr buffer_; +}; + +class RecordingPushMetricExporterBuilder + : public opentelemetry::sdk::configuration::ExtensionPushMetricExporterBuilder +{ +public: + explicit RecordingPushMetricExporterBuilder(std::shared_ptr buffer) + : buffer_(std::move(buffer)) + {} + std::unique_ptr Build( + const opentelemetry::sdk::configuration::ExtensionPushMetricExporterConfiguration *) + const override + { + return std::make_unique(buffer_); + } + +private: + std::shared_ptr buffer_; +}; + +// --------------------------------------------------------------------------- +// Synchronous metric reader: collects and exports on ForceFlush in +// the calling thread. +class SyncMetricReader : public opentelemetry::sdk::metrics::MetricReader +{ +public: + explicit SyncMetricReader( + std::unique_ptr exporter) + : exporter_(std::move(exporter)) + {} + + opentelemetry::sdk::metrics::AggregationTemporality GetAggregationTemporality( + opentelemetry::sdk::metrics::InstrumentType instrument_type) const noexcept override + { + return exporter_->GetAggregationTemporality(instrument_type); + } + +private: + bool CollectAndExport() noexcept + { + const bool success = Collect([this](opentelemetry::sdk::metrics::ResourceMetrics &metric_data) { + return (exporter_->Export(metric_data) == opentelemetry::sdk::common::ExportResult::kSuccess); + }); + return success; + } + + bool OnForceFlush(std::chrono::microseconds timeout) noexcept override + { + const bool collect_result = CollectAndExport(); + const bool flush_result = exporter_->ForceFlush(timeout); + return collect_result && flush_result; + } + + bool OnShutDown(std::chrono::microseconds timeout) noexcept override + { + return exporter_->Shutdown(timeout); + } + + std::unique_ptr exporter_; +}; + +class SyncPeriodicMetricReaderBuilder + : public opentelemetry::sdk::configuration::PeriodicMetricReaderBuilder +{ +public: + std::unique_ptr Build( + const opentelemetry::sdk::configuration::PeriodicMetricReaderConfiguration *, + std::unique_ptr &&exporter) const override + { + return std::make_unique(std::move(exporter)); + } +}; + +// --------------------------------------------------------------------------- +// Capturing periodic metric reader builder. Records the configuration +// arguments passed to Build() + +struct CapturedPeriodicReaderArgs +{ + std::size_t interval{0}; + std::size_t timeout{0}; + std::unique_ptr exporter; + // TODO: add cardinality limits and producers when we support them in the builder + bool called{false}; +}; + +class CapturingPeriodicMetricReaderBuilder + : public opentelemetry::sdk::configuration::PeriodicMetricReaderBuilder +{ +public: + explicit CapturingPeriodicMetricReaderBuilder( + std::shared_ptr captured) + : captured_(std::move(captured)) + {} + + std::unique_ptr Build( + const opentelemetry::sdk::configuration::PeriodicMetricReaderConfiguration *model, + std::unique_ptr &&exporter) const override + { + captured_->called = true; + captured_->interval = model->interval; + captured_->timeout = model->timeout; + captured_->exporter = std::move(exporter); + return std::make_unique(); + } + +private: + std::shared_ptr captured_; +}; + +// --------------------------------------------------------------------------- +// TextMapCarrier for propagator tests. + +class MapCarrier : public opentelemetry::context::propagation::TextMapCarrier +{ +public: + opentelemetry::nostd::string_view Get( + opentelemetry::nostd::string_view key) const noexcept override + { + auto it = map_.find(std::string(key)); + return it != map_.end() ? opentelemetry::nostd::string_view(it->second) : ""; + } + void Set(opentelemetry::nostd::string_view key, + opentelemetry::nostd::string_view value) noexcept override + { + map_[std::string(key)] = std::string(value); + } + + const std::map &map() const { return map_; } + +private: + std::map map_; +}; + +} // namespace config_test diff --git a/sdk/test/configuration/configured_sdk_test.cc b/sdk/test/configuration/configured_sdk_test.cc index 449f4e5e6..8ff9532a1 100644 --- a/sdk/test/configuration/configured_sdk_test.cc +++ b/sdk/test/configuration/configured_sdk_test.cc @@ -3,7 +3,6 @@ #include -#include #include #include #include @@ -18,7 +17,6 @@ #include "opentelemetry/trace/noop.h" #include "opentelemetry/trace/provider.h" -#include "opentelemetry/sdk/common/exporter_utils.h" #include "opentelemetry/sdk/common/global_log_handler.h" #include "opentelemetry/sdk/configuration/configuration.h" #include "opentelemetry/sdk/configuration/configured_sdk.h" @@ -33,6 +31,7 @@ #include "opentelemetry/sdk/configuration/logger_provider_configuration.h" #include "opentelemetry/sdk/configuration/meter_provider_configuration.h" #include "opentelemetry/sdk/configuration/metric_reader_configuration.h" +#include "opentelemetry/sdk/configuration/periodic_metric_reader_builder.h" #include "opentelemetry/sdk/configuration/periodic_metric_reader_configuration.h" #include "opentelemetry/sdk/configuration/propagator_configuration.h" #include "opentelemetry/sdk/configuration/push_metric_exporter_configuration.h" @@ -44,114 +43,18 @@ #include "opentelemetry/sdk/configuration/span_exporter_configuration.h" #include "opentelemetry/sdk/configuration/span_processor_configuration.h" #include "opentelemetry/sdk/configuration/tracer_provider_configuration.h" -#include "opentelemetry/sdk/logs/exporter.h" -#include "opentelemetry/sdk/logs/read_write_log_record.h" -#include "opentelemetry/sdk/metrics/instruments.h" -#include "opentelemetry/sdk/metrics/push_metric_exporter.h" -#include "opentelemetry/sdk/trace/exporter.h" -#include "opentelemetry/sdk/trace/span_data.h" -namespace nostd = opentelemetry::nostd; -namespace trace = opentelemetry::trace; -namespace logs = opentelemetry::logs; -namespace metrics = opentelemetry::metrics; -namespace propagation = opentelemetry::context::propagation; +#include "config_test_common.h" -namespace common_sdk = opentelemetry::sdk::common; -namespace logs_sdk = opentelemetry::sdk::logs; -namespace metrics_sdk = opentelemetry::sdk::metrics; -namespace trace_sdk = opentelemetry::sdk::trace; +namespace trace = opentelemetry::trace; +namespace logs = opentelemetry::logs; +namespace metrics = opentelemetry::metrics; +namespace propagation = opentelemetry::context::propagation; namespace config_sdk = opentelemetry::sdk::configuration; namespace internal_log = opentelemetry::sdk::common::internal_log; namespace { -//------------------------------------------------------------------------------ -// Noop Exporters - -class NoopSpanExporter : public trace_sdk::SpanExporter -{ -public: - NoopSpanExporter() = default; - std::unique_ptr MakeRecordable() noexcept override - { - return std::make_unique(); - } - common_sdk::ExportResult Export( - const nostd::span> &) noexcept override - { - return common_sdk::ExportResult::kSuccess; - } - bool ForceFlush(std::chrono::microseconds) noexcept override { return true; } - bool Shutdown(std::chrono::microseconds) noexcept override { return true; } -}; - -class NoopLogRecordExporter : public logs_sdk::LogRecordExporter -{ -public: - NoopLogRecordExporter() = default; - std::unique_ptr MakeRecordable() noexcept override - { - return std::make_unique(); - } - common_sdk::ExportResult Export( - const nostd::span> &) noexcept override - { - return common_sdk::ExportResult::kSuccess; - } - bool ForceFlush(std::chrono::microseconds) noexcept override { return true; } - bool Shutdown(std::chrono::microseconds) noexcept override { return true; } -}; - -class NoopPushMetricExporter : public metrics_sdk::PushMetricExporter -{ -public: - NoopPushMetricExporter() = default; - common_sdk::ExportResult Export(const metrics_sdk::ResourceMetrics &) noexcept override - { - return common_sdk::ExportResult::kSuccess; - } - metrics_sdk::AggregationTemporality GetAggregationTemporality( - metrics_sdk::InstrumentType) const noexcept override - { - return metrics_sdk::AggregationTemporality::kCumulative; - } - bool ForceFlush(std::chrono::microseconds) noexcept override { return true; } - bool Shutdown(std::chrono::microseconds) noexcept override { return true; } -}; - -//------------------------------------------------------------------------------ -// Configuration Builders - -class NoopSpanExporterBuilder : public config_sdk::ExtensionSpanExporterBuilder -{ -public: - std::unique_ptr Build( - const config_sdk::ExtensionSpanExporterConfiguration *) const override - { - return std::make_unique(); - } -}; - -class NoopLogRecordExporterBuilder : public config_sdk::ExtensionLogRecordExporterBuilder -{ -public: - std::unique_ptr Build( - const config_sdk::ExtensionLogRecordExporterConfiguration *) const override - { - return std::make_unique(); - } -}; - -class NoopPushMetricExporterBuilder : public config_sdk::ExtensionPushMetricExporterBuilder -{ -public: - std::unique_ptr Build( - const config_sdk::ExtensionPushMetricExporterConfiguration *) const override - { - return std::make_unique(); - } -}; //------------------------------------------------------------------------------ // ConfiguredSdkTest fixture @@ -211,11 +114,14 @@ class ConfiguredSdkTest : public ::testing::Test void MakeRegistry() { registry_ = std::make_shared(); - registry_->SetExtensionSpanExporterBuilder("noop", std::make_unique()); + registry_->SetExtensionSpanExporterBuilder( + "noop", std::make_unique()); registry_->SetExtensionLogRecordExporterBuilder( - "noop", std::make_unique()); + "noop", std::make_unique()); registry_->SetExtensionPushMetricExporterBuilder( - "noop", std::make_unique()); + "noop", std::make_unique()); + registry_->SetPeriodicMetricReaderBuilder( + std::make_unique()); } static std::unique_ptr MakeTracerProviderConfig() diff --git a/sdk/test/configuration/programmatic_configuration_test.cc b/sdk/test/configuration/programmatic_configuration_test.cc index 6e00c6c52..cee81c182 100644 --- a/sdk/test/configuration/programmatic_configuration_test.cc +++ b/sdk/test/configuration/programmatic_configuration_test.cc @@ -68,6 +68,7 @@ #include "opentelemetry/sdk/configuration/meter_provider_configuration.h" #include "opentelemetry/sdk/configuration/metric_reader_configuration.h" #include "opentelemetry/sdk/configuration/parent_based_sampler_configuration.h" +#include "opentelemetry/sdk/configuration/periodic_metric_reader_builder.h" #include "opentelemetry/sdk/configuration/periodic_metric_reader_configuration.h" #include "opentelemetry/sdk/configuration/propagator_configuration.h" #include "opentelemetry/sdk/configuration/push_metric_exporter_configuration.h" @@ -86,213 +87,33 @@ #include "opentelemetry/sdk/configuration/view_configuration.h" #include "opentelemetry/sdk/configuration/view_selector_configuration.h" #include "opentelemetry/sdk/configuration/view_stream_configuration.h" - -#include "opentelemetry/sdk/common/exporter_utils.h" -#include "opentelemetry/sdk/logs/exporter.h" #include "opentelemetry/sdk/logs/logger_provider.h" #include "opentelemetry/sdk/logs/read_write_log_record.h" #include "opentelemetry/sdk/metrics/data/metric_data.h" #include "opentelemetry/sdk/metrics/data/point_data.h" -#include "opentelemetry/sdk/metrics/export/metric_producer.h" #include "opentelemetry/sdk/metrics/instruments.h" #include "opentelemetry/sdk/metrics/meter_provider.h" -#include "opentelemetry/sdk/metrics/push_metric_exporter.h" #include "opentelemetry/sdk/resource/resource.h" -#include "opentelemetry/sdk/trace/exporter.h" #include "opentelemetry/sdk/trace/span_data.h" #include "opentelemetry/sdk/trace/tracer_provider.h" +#include "config_test_common.h" + +namespace common = opentelemetry::common; namespace nostd = opentelemetry::nostd; +namespace metrics = opentelemetry::metrics; namespace trace = opentelemetry::trace; namespace logs = opentelemetry::logs; -namespace metrics = opentelemetry::metrics; -namespace common = opentelemetry::common; namespace baggage = opentelemetry::baggage; namespace propagation = opentelemetry::context::propagation; namespace context = opentelemetry::context; -namespace common_sdk = opentelemetry::sdk::common; -namespace logs_sdk = opentelemetry::sdk::logs; namespace metrics_sdk = opentelemetry::sdk::metrics; -namespace trace_sdk = opentelemetry::sdk::trace; namespace config_sdk = opentelemetry::sdk::configuration; namespace { -// --------------------------------------------------------------------------- -// Shared export buffers - -using LogRecordBuffer = std::vector>; -using SpanBuffer = std::vector>; -using MetricBuffer = std::vector; - -// --------------------------------------------------------------------------- -// Recording exporters to support integration testing of the configured SDK. -// These exporters record the data they receive into a buffer for later inspection. - -class RecordingSpanExporter : public trace_sdk::SpanExporter -{ -public: - explicit RecordingSpanExporter(std::shared_ptr buffer) : buffer_(std::move(buffer)) {} - - std::unique_ptr MakeRecordable() noexcept override - { - return std::make_unique(); - } - - common_sdk::ExportResult Export( - const nostd::span> &spans) noexcept override - { - for (auto &span : spans) - { - buffer_->emplace_back(static_cast(span.release())); - } - return common_sdk::ExportResult::kSuccess; - } - - bool ForceFlush(std::chrono::microseconds) noexcept override { return true; } - bool Shutdown(std::chrono::microseconds) noexcept override { return true; } - -private: - std::shared_ptr buffer_; -}; - -class RecordingLogRecordExporter : public logs_sdk::LogRecordExporter -{ -public: - explicit RecordingLogRecordExporter(std::shared_ptr buffer) - : buffer_(std::move(buffer)) - {} - - std::unique_ptr MakeRecordable() noexcept override - { - return std::make_unique(); - } - - common_sdk::ExportResult Export( - const nostd::span> &records) noexcept override - { - for (auto &rec : records) - { - buffer_->emplace_back(static_cast(rec.release())); - } - return common_sdk::ExportResult::kSuccess; - } - - bool RecordableEnforcesLogRecordLimits() const noexcept override { return true; } - - bool ForceFlush(std::chrono::microseconds) noexcept override { return true; } - bool Shutdown(std::chrono::microseconds) noexcept override { return true; } - -private: - std::shared_ptr buffer_; -}; - -class RecordingPushMetricExporter : public metrics_sdk::PushMetricExporter -{ -public: - explicit RecordingPushMetricExporter(std::shared_ptr buffer) - : buffer_(std::move(buffer)) - {} - - common_sdk::ExportResult Export( - const metrics_sdk::ResourceMetrics &resource_metrics) noexcept override - { - for (const auto &scope : resource_metrics.scope_metric_data_) - { - for (const auto &metric : scope.metric_data_) - { - buffer_->emplace_back(metric); - } - } - return common_sdk::ExportResult::kSuccess; - } - - metrics_sdk::AggregationTemporality GetAggregationTemporality( - metrics_sdk::InstrumentType) const noexcept override - { - return metrics_sdk::AggregationTemporality::kCumulative; - } - - bool ForceFlush(std::chrono::microseconds) noexcept override { return true; } - bool Shutdown(std::chrono::microseconds) noexcept override { return true; } - -private: - std::shared_ptr buffer_; -}; - -// --------------------------------------------------------------------------- -// Configuration Builders for recording exporters - -class RecordingSpanExporterBuilder : public config_sdk::ExtensionSpanExporterBuilder -{ -public: - explicit RecordingSpanExporterBuilder(std::shared_ptr buffer) - : buffer_(std::move(buffer)) - {} - std::unique_ptr Build( - const config_sdk::ExtensionSpanExporterConfiguration *) const override - { - return std::make_unique(buffer_); - } - -private: - std::shared_ptr buffer_; -}; -class RecordingLogRecordExporterBuilder : public config_sdk::ExtensionLogRecordExporterBuilder -{ -public: - explicit RecordingLogRecordExporterBuilder(std::shared_ptr buffer) - : buffer_(std::move(buffer)) - {} - std::unique_ptr Build( - const config_sdk::ExtensionLogRecordExporterConfiguration *) const override - { - return std::make_unique(buffer_); - } - -private: - std::shared_ptr buffer_; -}; - -class RecordingPushMetricExporterBuilder : public config_sdk::ExtensionPushMetricExporterBuilder -{ -public: - explicit RecordingPushMetricExporterBuilder(std::shared_ptr buffer) - : buffer_(std::move(buffer)) - {} - std::unique_ptr Build( - const config_sdk::ExtensionPushMetricExporterConfiguration *) const override - { - auto exporter = std::make_unique(buffer_); - return exporter; - } - -private: - std::shared_ptr buffer_; -}; - -// --------------------------------------------------------------------------- -// TextMapCarrier for propagator tests. - -class MapCarrier : public propagation::TextMapCarrier -{ -public: - nostd::string_view Get(nostd::string_view key) const noexcept override - { - auto it = map_.find(std::string(key)); - return it != map_.end() ? nostd::string_view(it->second) : ""; - } - void Set(nostd::string_view key, nostd::string_view value) noexcept override - { - map_[std::string(key)] = std::string(value); - } - - const std::map &map() const { return map_; } - -private: - std::map map_; -}; +constexpr std::chrono::milliseconds kProcessTimeout{1000}; //--------------------------------------------------------------------------- // ProgrammaticConfigTest fixture: This supports integration testing of the configured SDK. @@ -333,11 +154,14 @@ class ProgrammaticConfigTest : public ::testing::Test { registry_ = std::make_shared(); registry_->SetExtensionSpanExporterBuilder( - "recording", std::make_unique(span_buffer_)); + "recording", std::make_unique(span_buffer_)); registry_->SetExtensionLogRecordExporterBuilder( - "recording", std::make_unique(log_buffer_)); + "recording", std::make_unique(log_buffer_)); registry_->SetExtensionPushMetricExporterBuilder( - "recording", std::make_unique(metric_buffer_)); + "recording", + std::make_unique(metric_buffer_)); + registry_->SetPeriodicMetricReaderBuilder( + std::make_unique()); } static std::unique_ptr MakeTracerProviderConfig() @@ -368,17 +192,17 @@ class ProgrammaticConfigTest : public ::testing::Test exporter->name = "recording"; auto reader = std::make_unique(); reader->exporter = std::move(exporter); - reader->interval = 3'600'000; // milliseconds. Set to a large value and rely on ForceFlush to - // trigger collection. - reader->timeout = 60'000; // milliseconds - auto config = std::make_unique(); + auto config = std::make_unique(); config->readers.emplace_back(std::move(reader)); return config; } - std::shared_ptr span_buffer_{std::make_shared()}; - std::shared_ptr log_buffer_{std::make_shared()}; - std::shared_ptr metric_buffer_{std::make_shared()}; + std::shared_ptr span_buffer_{ + std::make_shared()}; + std::shared_ptr log_buffer_{ + std::make_shared()}; + std::shared_ptr metric_buffer_{ + std::make_shared()}; std::shared_ptr registry_; std::unique_ptr sdk_; @@ -461,16 +285,15 @@ TEST_F(ProgrammaticConfigTest, LoggerProviderWithDefaults) logs::Severity::kInfo, nostd::string_view("test-message"), common::MakeAttributes({{"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}})); - ASSERT_TRUE(sdk_->logger_provider->ForceFlush(std::chrono::milliseconds(5000))); - ASSERT_TRUE(sdk_->logger_provider->Shutdown(std::chrono::milliseconds(5000))); + ASSERT_TRUE(sdk_->logger_provider->ForceFlush(std::chrono::milliseconds(kProcessTimeout))); + ASSERT_TRUE(sdk_->logger_provider->Shutdown(std::chrono::milliseconds(kProcessTimeout))); - EXPECT_GE(log_buffer_->size(), 1); + EXPECT_EQ(log_buffer_->size(), 1); } TEST_F(ProgrammaticConfigTest, LoggerProviderWithLogRecordLimits) { - config_sdk::LogRecordLimitsConfiguration limits{ - 0, 0}; // TODO: Remove the default initialization once the limit members are initialized. + config_sdk::LogRecordLimitsConfiguration limits; limits.attribute_count_limit = 2; limits.attribute_value_length_limit = 5; @@ -489,10 +312,10 @@ TEST_F(ProgrammaticConfigTest, LoggerProviderWithLogRecordLimits) logs::Severity::kInfo, nostd::string_view("test-message"), common::MakeAttributes({{"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}})); - ASSERT_TRUE(sdk_->logger_provider->ForceFlush(std::chrono::milliseconds(5000))); - ASSERT_TRUE(sdk_->logger_provider->Shutdown(std::chrono::milliseconds(5000))); + ASSERT_TRUE(sdk_->logger_provider->ForceFlush(std::chrono::milliseconds(kProcessTimeout))); + ASSERT_TRUE(sdk_->logger_provider->Shutdown(std::chrono::milliseconds(kProcessTimeout))); - EXPECT_GE(log_buffer_->size(), 1); + EXPECT_EQ(log_buffer_->size(), 1); auto *record = log_buffer_->front().get(); EXPECT_EQ(nostd::get(record->GetBody()), "test-message"); const auto &attributes = record->GetAttributes(); @@ -538,13 +361,16 @@ TEST_F(ProgrammaticConfigTest, LoggerProviderWithLoggerConfigurator) EXPECT_FALSE(error_logger->Enabled(logs::Severity::kInfo)); EXPECT_TRUE(error_logger->Enabled(logs::Severity::kError)); - ASSERT_TRUE(sdk_->logger_provider->ForceFlush(std::chrono::milliseconds(5000))); - ASSERT_TRUE(sdk_->logger_provider->Shutdown(std::chrono::milliseconds(5000))); + ASSERT_TRUE(sdk_->logger_provider->ForceFlush(std::chrono::milliseconds(kProcessTimeout))); + ASSERT_TRUE(sdk_->logger_provider->Shutdown(std::chrono::milliseconds(kProcessTimeout))); - EXPECT_GE(log_buffer_->size(), 2); + EXPECT_EQ(log_buffer_->size(), 2); } -TEST_F(ProgrammaticConfigTest, LoggerProviderWithBatchProcessorDefaults) +// TODO: Re-enable this test once a mock BatchSpanProcessor can be configured. +// All tests that use a BatchProcessor may timeout due to the a race between the background thread +// and the ForceFlush call. +TEST_F(ProgrammaticConfigTest, DISABLED_LoggerProviderWithBatchProcessorDefaults) { auto exporter = std::make_unique(); exporter->name = "recording"; @@ -560,22 +386,23 @@ TEST_F(ProgrammaticConfigTest, LoggerProviderWithBatchProcessorDefaults) ASSERT_NE(sdk_->logger_provider, nullptr); logs::Provider::GetLoggerProvider()->GetLogger("test")->Info("test-message"); - ASSERT_TRUE(sdk_->logger_provider->ForceFlush(std::chrono::milliseconds(5000))); - ASSERT_TRUE(sdk_->logger_provider->Shutdown(std::chrono::milliseconds(5000))); + ASSERT_TRUE(sdk_->logger_provider->ForceFlush(std::chrono::milliseconds(kProcessTimeout))); + ASSERT_TRUE(sdk_->logger_provider->Shutdown(std::chrono::milliseconds(kProcessTimeout))); EXPECT_GE(log_buffer_->size(), 1); } -TEST_F(ProgrammaticConfigTest, LoggerProviderWithBatchProcessorConfigured) +// TODO: Re-enable this test once a mock BatchProcessor can be configured. +TEST_F(ProgrammaticConfigTest, DISABLED_LoggerProviderWithBatchProcessorConfigured) { auto exporter = std::make_unique(); exporter->name = "recording"; auto processor = std::make_unique(); processor->exporter = std::move(exporter); - processor->schedule_delay = 60000; + processor->schedule_delay = 1000; processor->max_queue_size = 100; processor->max_export_batch_size = 50; - processor->export_timeout = 5000; + processor->export_timeout = 1000; auto logger_provider_config = std::make_unique(); logger_provider_config->processors.emplace_back(std::move(processor)); @@ -586,8 +413,8 @@ TEST_F(ProgrammaticConfigTest, LoggerProviderWithBatchProcessorConfigured) ASSERT_NE(sdk_->logger_provider, nullptr); logs::Provider::GetLoggerProvider()->GetLogger("test")->Info("test-message"); - ASSERT_TRUE(sdk_->logger_provider->ForceFlush(std::chrono::milliseconds(5000))); - ASSERT_TRUE(sdk_->logger_provider->Shutdown(std::chrono::milliseconds(5000))); + ASSERT_TRUE(sdk_->logger_provider->ForceFlush(std::chrono::milliseconds(kProcessTimeout))); + ASSERT_TRUE(sdk_->logger_provider->Shutdown(std::chrono::milliseconds(kProcessTimeout))); EXPECT_GE(log_buffer_->size(), 1); } @@ -595,10 +422,7 @@ TEST_F(ProgrammaticConfigTest, LoggerProviderWithBatchProcessorConfigured) //-------------------------------------------------------------------------- // MeterProvider tests -// TODO: These test cases may timeout due to threading in the PeriodicExportingMetricReader -// that cause ForceFlush or Shutdown to block indefinitely. Disabling for now until we can fix the -// underlying issue. -TEST_F(ProgrammaticConfigTest, DISABLED_MeterProviderWithDefaults) +TEST_F(ProgrammaticConfigTest, MeterProviderWithDefaults) { auto model = std::make_unique(); model->meter_provider = MakeMeterProviderConfig(); @@ -611,13 +435,13 @@ TEST_F(ProgrammaticConfigTest, DISABLED_MeterProviderWithDefaults) ->CreateUInt64Counter("test-counter") ->Add(1); - ASSERT_TRUE(sdk_->meter_provider->ForceFlush(std::chrono::milliseconds(5000))); - ASSERT_TRUE(sdk_->meter_provider->Shutdown(std::chrono::milliseconds(5000))); + ASSERT_TRUE(sdk_->meter_provider->ForceFlush(std::chrono::milliseconds(kProcessTimeout))); + ASSERT_TRUE(sdk_->meter_provider->Shutdown(std::chrono::milliseconds(kProcessTimeout))); - EXPECT_GE(metric_buffer_->size(), 1); + EXPECT_EQ(metric_buffer_->size(), 1); } -TEST_F(ProgrammaticConfigTest, DISABLED_MeterProviderWithMeterConfigurator) +TEST_F(ProgrammaticConfigTest, MeterProviderWithMeterConfigurator) { auto disabled_meter_config = config_sdk::MeterMatcherAndConfigConfiguration(); disabled_meter_config.name = "disabled-meter"; @@ -640,17 +464,17 @@ TEST_F(ProgrammaticConfigTest, DISABLED_MeterProviderWithMeterConfigurator) auto disabled_meter = metrics::Provider::GetMeterProvider()->GetMeter(disabled_meter_config.name); disabled_meter->CreateUInt64Counter("disabled-test-counter")->Add(1); - ASSERT_TRUE(sdk_->meter_provider->ForceFlush(std::chrono::milliseconds(5000))); - ASSERT_TRUE(sdk_->meter_provider->Shutdown(std::chrono::milliseconds(5000))); + ASSERT_TRUE(sdk_->meter_provider->ForceFlush(std::chrono::milliseconds(kProcessTimeout))); + ASSERT_TRUE(sdk_->meter_provider->Shutdown(std::chrono::milliseconds(kProcessTimeout))); - EXPECT_GE(metric_buffer_->size(), 1); + EXPECT_EQ(metric_buffer_->size(), 1); for (const auto &metric : *metric_buffer_) { EXPECT_NE(metric.instrument_descriptor.name_, "disabled-test-counter"); } } -TEST_F(ProgrammaticConfigTest, DISABLED_MeterProviderWithViews) +TEST_F(ProgrammaticConfigTest, MeterProviderWithViews) { // View 1: Base2 exponential aggregation const std::size_t max_scale = 10; @@ -716,11 +540,11 @@ TEST_F(ProgrammaticConfigTest, DISABLED_MeterProviderWithViews) meter->CreateDoubleHistogram("exponential-histogram")->Record(42.0, context); meter->CreateDoubleHistogram("explicit-histogram")->Record(42.0, context); meter->CreateUInt64Counter("default-counter")->Add(1, context); - ASSERT_TRUE(sdk_->meter_provider->ForceFlush(std::chrono::milliseconds(5000))); - ASSERT_TRUE(sdk_->meter_provider->Shutdown(std::chrono::milliseconds(5000))); + ASSERT_TRUE(sdk_->meter_provider->ForceFlush(std::chrono::milliseconds(kProcessTimeout))); + ASSERT_TRUE(sdk_->meter_provider->Shutdown(std::chrono::milliseconds(kProcessTimeout))); // check that instances of the three data points were collected and are of the right type. - EXPECT_GE(metric_buffer_->size(), 3); + EXPECT_EQ(metric_buffer_->size(), 3); bool found_base2_histogram = false; bool found_explicit_histogram = false; bool found_default_counter = false; @@ -765,8 +589,8 @@ TEST_F(ProgrammaticConfigTest, TracerProviderWithDefaults) auto default_tracer = trace::Provider::GetTracerProvider()->GetTracer("default-tracer"); default_tracer->StartSpan("test-span")->End(); - ASSERT_TRUE(sdk_->tracer_provider->ForceFlush(std::chrono::milliseconds(5000))); - ASSERT_TRUE(sdk_->tracer_provider->Shutdown(std::chrono::milliseconds(5000))); + ASSERT_TRUE(sdk_->tracer_provider->ForceFlush(std::chrono::milliseconds(kProcessTimeout))); + ASSERT_TRUE(sdk_->tracer_provider->Shutdown(std::chrono::milliseconds(kProcessTimeout))); EXPECT_EQ(span_buffer_->size(), 1); } @@ -794,7 +618,7 @@ TEST_F(ProgrammaticConfigTest, TracerProviderWithTracerConfigurator) auto disabled_tracer = trace::Provider::GetTracerProvider()->GetTracer("disabled-tracer"); disabled_tracer->StartSpan("disabled-test-span")->End(); - ASSERT_TRUE(sdk_->tracer_provider->ForceFlush(std::chrono::milliseconds(5000))); + ASSERT_TRUE(sdk_->tracer_provider->ForceFlush(std::chrono::milliseconds(kProcessTimeout))); ASSERT_EQ(span_buffer_->size(), 1); EXPECT_NE(span_buffer_->at(0)->GetName(), "disabled-test-span"); @@ -811,8 +635,8 @@ TEST_F(ProgrammaticConfigTest, TracerProviderWithSampler) ASSERT_NE(sdk_->tracer_provider, nullptr); trace::Provider::GetTracerProvider()->GetTracer("test")->StartSpan("test-span")->End(); - ASSERT_TRUE(sdk_->tracer_provider->ForceFlush(std::chrono::milliseconds(5000))); - ASSERT_TRUE(sdk_->tracer_provider->Shutdown(std::chrono::milliseconds(5000))); + ASSERT_TRUE(sdk_->tracer_provider->ForceFlush(std::chrono::milliseconds(kProcessTimeout))); + ASSERT_TRUE(sdk_->tracer_provider->Shutdown(std::chrono::milliseconds(kProcessTimeout))); EXPECT_EQ(span_buffer_->size(), 0); } @@ -829,15 +653,14 @@ TEST_F(ProgrammaticConfigTest, TracerProviderWithParentBasedSamplerNullRoot) ASSERT_NE(sdk_->tracer_provider, nullptr); trace::Provider::GetTracerProvider()->GetTracer("test")->StartSpan("test-span")->End(); - ASSERT_TRUE(sdk_->tracer_provider->ForceFlush(std::chrono::milliseconds(5000))); - ASSERT_TRUE(sdk_->tracer_provider->Shutdown(std::chrono::milliseconds(5000))); + ASSERT_TRUE(sdk_->tracer_provider->ForceFlush(std::chrono::milliseconds(kProcessTimeout))); + ASSERT_TRUE(sdk_->tracer_provider->Shutdown(std::chrono::milliseconds(kProcessTimeout))); EXPECT_EQ(span_buffer_->size(), 1); } -// TODO: Re-enable this test once the BatchSpanProcessorConfiguration is initialized with spec -// defaults. -TEST_F(ProgrammaticConfigTest, TracerProviderWithBatchProcessor) +// TODO: Re-enable this test once a mock BatchSpanProcessor can be configured. +TEST_F(ProgrammaticConfigTest, DISABLED_TracerProviderWithBatchProcessor) { auto exporter = std::make_unique(); exporter->name = "recording"; @@ -852,13 +675,14 @@ TEST_F(ProgrammaticConfigTest, TracerProviderWithBatchProcessor) CreateAndInstallSdk(model); trace::Provider::GetTracerProvider()->GetTracer("test")->StartSpan("test-span")->End(); - ASSERT_TRUE(sdk_->tracer_provider->ForceFlush(std::chrono::milliseconds(5000))); - ASSERT_TRUE(sdk_->tracer_provider->Shutdown(std::chrono::milliseconds(5000))); + ASSERT_TRUE(sdk_->tracer_provider->ForceFlush(std::chrono::milliseconds(kProcessTimeout))); + ASSERT_TRUE(sdk_->tracer_provider->Shutdown(std::chrono::milliseconds(kProcessTimeout))); EXPECT_GE(span_buffer_->size(), 1); } -TEST_F(ProgrammaticConfigTest, TracerProviderWithBatchProcessorConfigured) +// TODO: Re-enable this test once a mock BatchSpanProcessor can be configured. +TEST_F(ProgrammaticConfigTest, DISABLED_TracerProviderWithBatchProcessorConfigured) { auto exporter = std::make_unique(); exporter->name = "recording"; @@ -866,7 +690,7 @@ TEST_F(ProgrammaticConfigTest, TracerProviderWithBatchProcessorConfigured) processor->schedule_delay = 60000; processor->max_queue_size = 100; processor->max_export_batch_size = 50; - processor->export_timeout = 5000; + processor->export_timeout = 1000; processor->exporter = std::move(exporter); auto tracer_provider_config = std::make_unique(); tracer_provider_config->processors.emplace_back(std::move(processor)); @@ -877,8 +701,8 @@ TEST_F(ProgrammaticConfigTest, TracerProviderWithBatchProcessorConfigured) CreateAndInstallSdk(model); trace::Provider::GetTracerProvider()->GetTracer("test")->StartSpan("test-span")->End(); - ASSERT_TRUE(sdk_->tracer_provider->ForceFlush(std::chrono::milliseconds(5000))); - ASSERT_TRUE(sdk_->tracer_provider->Shutdown(std::chrono::milliseconds(5000))); + ASSERT_TRUE(sdk_->tracer_provider->ForceFlush(std::chrono::milliseconds(kProcessTimeout))); + ASSERT_TRUE(sdk_->tracer_provider->Shutdown(std::chrono::milliseconds(kProcessTimeout))); EXPECT_GE(span_buffer_->size(), 1); } @@ -900,7 +724,7 @@ void CheckPropagators() auto baggage = baggage::Baggage::GetDefault()->Set("key", "value"); auto ctx = baggage::SetBaggage(ctx1, baggage); - MapCarrier carrier; + config_test::MapCarrier carrier; propagation::GlobalTextMapPropagator::GetGlobalPropagator()->Inject(carrier, ctx); ASSERT_NE(carrier.map().find("traceparent"), carrier.map().end()); // tracecontext diff --git a/sdk/test/configuration/sdk_builder_test.cc b/sdk/test/configuration/sdk_builder_test.cc index b4678b0fd..461f722df 100644 --- a/sdk/test/configuration/sdk_builder_test.cc +++ b/sdk/test/configuration/sdk_builder_test.cc @@ -7,14 +7,22 @@ #include #include #include + +#include "config_test_common.h" #include "opentelemetry/logs/severity.h" #include "opentelemetry/nostd/string_view.h" + #include "opentelemetry/sdk/configuration/always_off_sampler_configuration.h" #include "opentelemetry/sdk/configuration/always_on_sampler_configuration.h" +#include "opentelemetry/sdk/configuration/extension_push_metric_exporter_builder.h" +#include "opentelemetry/sdk/configuration/extension_push_metric_exporter_configuration.h" #include "opentelemetry/sdk/configuration/logger_config_configuration.h" #include "opentelemetry/sdk/configuration/logger_configurator_configuration.h" #include "opentelemetry/sdk/configuration/logger_matcher_and_config_configuration.h" #include "opentelemetry/sdk/configuration/parent_based_sampler_configuration.h" +#include "opentelemetry/sdk/configuration/periodic_metric_reader_builder.h" +#include "opentelemetry/sdk/configuration/periodic_metric_reader_configuration.h" +#include "opentelemetry/sdk/configuration/push_metric_exporter_configuration.h" #include "opentelemetry/sdk/configuration/registry.h" #include "opentelemetry/sdk/configuration/sampler_configuration.h" #include "opentelemetry/sdk/configuration/sdk_builder.h" @@ -22,9 +30,11 @@ #include "opentelemetry/sdk/configuration/span_limits_configuration.h" #include "opentelemetry/sdk/configuration/trace_id_ratio_based_sampler_configuration.h" #include "opentelemetry/sdk/configuration/tracer_provider_configuration.h" + #include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h" #include "opentelemetry/sdk/instrumentationscope/scope_configurator.h" #include "opentelemetry/sdk/logs/logger_config.h" +#include "opentelemetry/sdk/metrics/metric_reader.h" #include "opentelemetry/sdk/resource/resource.h" #include "opentelemetry/sdk/trace/sampler.h" #include "opentelemetry/sdk/trace/span_limits.h" @@ -222,3 +232,31 @@ TEST(SdkBuilder, CreateParentBasedSampler) R"(ParentBased{TraceIdRatioBasedSampler{0.250000}})"); } } + +TEST(SdkBuilder, CreatePeriodicMetricReader) +{ + auto exporter = std::make_unique(); + exporter->name = "noop"; + + config_sdk::PeriodicMetricReaderConfiguration model; + model.exporter = std::move(exporter); + model.interval = 12345; + model.timeout = 678; + + auto captured = std::make_shared(); + + auto registry = std::make_shared(); + registry->SetExtensionPushMetricExporterBuilder( + "noop", std::make_unique()); + registry->SetPeriodicMetricReaderBuilder( + std::make_unique(captured)); + + config_sdk::SdkBuilder builder(registry); + auto reader = builder.CreatePeriodicMetricReader(&model); + ASSERT_NE(reader, nullptr); + + EXPECT_TRUE(captured->called); + EXPECT_EQ(captured->interval, model.interval); + EXPECT_EQ(captured->timeout, model.timeout); + EXPECT_TRUE(captured->exporter != nullptr); +}