SERVER-115315 Set up MockExporter for unit testing the Metrics Service (#45192)

GitOrigin-RevId: ed27957a906158f6e382e6e94c4ca56ce4db7419
This commit is contained in:
Erin McNulty 2025-12-15 17:57:08 -05:00 committed by MongoDB Bot
parent ba84a4c0a6
commit bf61a77f0b
23 changed files with 1211 additions and 137 deletions

View File

@ -513,6 +513,7 @@ def mongo_cc_library(
visibility = visibility,
deps = deps + cc_deps,
exec_properties = exec_properties,
testonly = testonly,
)
def _mongo_cc_binary_and_test(

View File

@ -18,38 +18,12 @@ idl_generator(
src = "metrics_settings.idl",
)
mongo_cc_unit_test(
name = "metrics_counter_test",
srcs = [
"metrics_counter_test.cpp",
],
tags = ["mongo_unittest_third_group"],
)
mongo_cc_library(
name = "metrics_service",
srcs = [
"metrics_service.cpp",
],
deps = [
"//src/mongo/db:server_base",
] + select(
{
"@//bazel/config:build_otel_enabled": [
"//src/third_party/opentelemetry-cpp/api",
],
"//conditions:default": [],
},
),
)
mongo_cc_library(
name = "metrics_initialization",
srcs = [
"metrics_initialization.cpp",
"metrics_settings_gen",
],
no_undefined_ref_DO_NOT_USE = False,
deps = [
"//src/mongo/db:server_base",
] + select(
@ -79,10 +53,28 @@ mongo_cc_unit_test(
tags = ["mongo_unittest_second_group"],
target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
deps = [
":in_memory_metrics_exporter",
":metrics_initialization",
],
)
mongo_cc_library(
name = "metrics_service",
srcs = [
"metrics_service.cpp",
],
deps = [
"//src/mongo/db:server_base",
] + select(
{
"@//bazel/config:build_otel_enabled": [
"//src/third_party/opentelemetry-cpp/api",
],
"//conditions:default": [],
},
),
)
mongo_cc_unit_test(
name = "metrics_service_test",
srcs = [
@ -91,6 +83,7 @@ mongo_cc_unit_test(
tags = ["mongo_unittest_first_group"],
target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
deps = [
":in_memory_metrics_exporter",
":metrics_initialization",
":metrics_service",
"//src/mongo/db:service_context_test_fixture",
@ -99,18 +92,6 @@ mongo_cc_unit_test(
],
)
mongo_cc_unit_test(
name = "metrics_histogram_test",
srcs = [
"metrics_histogram_test.cpp",
],
tags = ["mongo_unittest_sixth_group"],
target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
deps = [
"//src/third_party/opentelemetry-cpp/api",
],
)
mongo_cc_library(
name = "metric_units",
srcs = ["metric_units.cpp"],
@ -123,3 +104,34 @@ mongo_cc_unit_test(
tags = ["mongo_unittest_second_group"],
deps = [":metric_units"],
)
mongo_cc_unit_test(
name = "metrics_counter_test",
srcs = [
"metrics_counter_test.cpp",
],
tags = ["mongo_unittest_third_group"],
)
mongo_cc_unit_test(
name = "metrics_histogram_test",
srcs = [
"metrics_histogram_test.cpp",
],
tags = ["mongo_unittest_sixth_group"],
target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
deps = [
"//src/third_party/opentelemetry-cpp/api",
],
)
mongo_cc_library(
name = "in_memory_metrics_exporter",
testonly = True,
target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
deps = [
"//src/third_party/opentelemetry-cpp/exporters/memory:in_memory_data",
"//src/third_party/opentelemetry-cpp/exporters/memory:in_memory_metric_data",
"//src/third_party/opentelemetry-cpp/exporters/memory:in_memory_metric_exporter_factory",
],
)

View File

@ -34,14 +34,14 @@
#include "mongo/idl/server_parameter_test_controller.h"
#include "mongo/otel/metrics/metrics_initialization.h"
#include "mongo/otel/metrics/metrics_settings_gen.h"
#include "mongo/otel/metrics/metrics_test_util.h"
#include "mongo/unittest/temp_dir.h"
#include "mongo/unittest/unittest.h"
#include <opentelemetry/metrics/noop.h>
#include <opentelemetry/metrics/provider.h>
namespace mongo {
namespace otel {
namespace mongo::otel::metrics {
namespace {
class OtelMetricsInitializationTest : public unittest::Test {
@ -64,44 +64,40 @@ private:
RAIIServerParameterControllerForTest _featureFlagController{"featureFlagOtelMetrics", true};
};
bool isNoop(opentelemetry::metrics::MeterProvider* provider) {
return !!dynamic_cast<opentelemetry::metrics::NoopMeterProvider*>(provider);
}
TEST_F(OtelMetricsInitializationTest, NoMeterProvider) {
ASSERT_OK(metrics::initialize());
ASSERT_OK(initialize());
auto provider = opentelemetry::metrics::Provider::GetMeterProvider();
ASSERT_TRUE(isNoop(provider.get()));
ASSERT_TRUE(isNoopMeterProvider(provider.get()));
}
TEST_F(OtelMetricsInitializationTest, Shutdown) {
RAIIServerParameterControllerForTest param{"openTelemetryMetricsDirectory", getMetricsPath()};
ASSERT_OK(metrics::initialize());
ASSERT_OK(initialize());
auto provider = opentelemetry::metrics::Provider::GetMeterProvider();
ASSERT_FALSE(isNoop(provider.get()));
ASSERT_FALSE(isNoopMeterProvider(provider.get()));
ASSERT_NOT_EQUALS(provider.get(), nullptr);
metrics::shutdown();
shutdown();
provider = opentelemetry::metrics::Provider::GetMeterProvider();
ASSERT_EQ(provider.get(), nullptr);
}
TEST_F(OtelMetricsInitializationTest, FileMeterProvider) {
RAIIServerParameterControllerForTest param{"openTelemetryMetricsDirectory", getMetricsPath()};
ASSERT_OK(metrics::initialize());
ASSERT_OK(initialize());
auto provider = opentelemetry::metrics::Provider::GetMeterProvider();
ASSERT_FALSE(isNoop(provider.get()));
ASSERT_FALSE(isNoopMeterProvider(provider.get()));
}
TEST_F(OtelMetricsInitializationTest, HttpMeterProvider) {
RAIIServerParameterControllerForTest param{"openTelemetryMetricsHttpEndpoint",
"http://localhost:4318/v1/traces"};
ASSERT_OK(metrics::initialize());
ASSERT_OK(initialize());
auto provider = opentelemetry::metrics::Provider::GetMeterProvider();
ASSERT_FALSE(isNoop(provider.get()));
ASSERT_FALSE(isNoopMeterProvider(provider.get()));
}
TEST_F(OtelMetricsInitializationTest, HttpAndDirectory) {
@ -109,37 +105,37 @@ TEST_F(OtelMetricsInitializationTest, HttpAndDirectory) {
"http://localhost:4318/v1/traces"};
RAIIServerParameterControllerForTest directoryParam{"openTelemetryMetricsDirectory",
getMetricsPath()};
auto status = metrics::initialize();
auto status = initialize();
ASSERT_FALSE(status.isOK());
ASSERT_EQ(status.codeString(), "InvalidOptions");
auto provider = opentelemetry::metrics::Provider::GetMeterProvider();
ASSERT_TRUE(isNoop(provider.get()));
ASSERT_TRUE(isNoopMeterProvider(provider.get()));
}
TEST_F(OtelMetricsInitializationTest, FeatureFlagDisabledNoParams) {
RAIIServerParameterControllerForTest featureFlagController{"featureFlagOtelMetrics", false};
ASSERT_OK(metrics::initialize());
ASSERT_OK(initialize());
auto provider = opentelemetry::metrics::Provider::GetMeterProvider();
ASSERT_TRUE(isNoop(provider.get()));
ASSERT_TRUE(isNoopMeterProvider(provider.get()));
}
TEST_F(OtelMetricsInitializationTest, FeatureFlagDisabledDirectorySet) {
RAIIServerParameterControllerForTest featureFlagController{"featureFlagOtelMetrics", false};
RAIIServerParameterControllerForTest param{"openTelemetryMetricsDirectory", getMetricsPath()};
ASSERT_EQ(metrics::initialize().code(), ErrorCodes::InvalidOptions);
ASSERT_EQ(initialize().code(), ErrorCodes::InvalidOptions);
auto provider = opentelemetry::metrics::Provider::GetMeterProvider();
ASSERT_TRUE(isNoop(provider.get()));
ASSERT_TRUE(isNoopMeterProvider(provider.get()));
}
TEST_F(OtelMetricsInitializationTest, FeatureFlagDisabledHttpSet) {
RAIIServerParameterControllerForTest featureFlagController{"featureFlagOtelMetrics", false};
RAIIServerParameterControllerForTest param{"openTelemetryMetricsHttpEndpoint",
"http://localhost:4318/v1/traces"};
ASSERT_EQ(metrics::initialize().code(), ErrorCodes::InvalidOptions);
ASSERT_EQ(initialize().code(), ErrorCodes::InvalidOptions);
auto provider = opentelemetry::metrics::Provider::GetMeterProvider();
ASSERT_TRUE(isNoop(provider.get()));
ASSERT_TRUE(isNoopMeterProvider(provider.get()));
}
TEST_F(OtelMetricsInitializationTest, InvalidCompressionParam) {
@ -148,9 +144,9 @@ TEST_F(OtelMetricsInitializationTest, InvalidCompressionParam) {
"http://localhost:4318/v1/traces"};
RAIIServerParameterControllerForTest compressionParam{"openTelemetryMetricsCompression",
"foo"};
ASSERT_EQ(metrics::initialize().code(), ErrorCodes::InvalidOptions);
ASSERT_EQ(initialize().code(), ErrorCodes::InvalidOptions);
auto provider = opentelemetry::metrics::Provider::GetMeterProvider();
ASSERT_TRUE(isNoop(provider.get()));
ASSERT_TRUE(isNoopMeterProvider(provider.get()));
}
RAIIServerParameterControllerForTest directoryParam{"openTelemetryMetricsDirectory",
@ -158,9 +154,9 @@ TEST_F(OtelMetricsInitializationTest, InvalidCompressionParam) {
for (const auto& value : {"gzip", "foo"}) {
RAIIServerParameterControllerForTest compressionParam{"openTelemetryMetricsCompression",
value};
ASSERT_EQ(metrics::initialize().code(), ErrorCodes::InvalidOptions);
ASSERT_EQ(initialize().code(), ErrorCodes::InvalidOptions);
auto provider = opentelemetry::metrics::Provider::GetMeterProvider();
ASSERT_TRUE(isNoop(provider.get()));
ASSERT_TRUE(isNoopMeterProvider(provider.get()));
}
}
@ -171,13 +167,13 @@ TEST_F(OtelMetricsInitializationTest, ValidCompressionParam) {
for (const auto& value : {"gzip", "none"}) {
RAIIServerParameterControllerForTest compressionParam{"openTelemetryMetricsCompression",
value};
ASSERT_OK(metrics::initialize());
ASSERT_OK(initialize());
auto provider = opentelemetry::metrics::Provider::GetMeterProvider();
ASSERT_FALSE(isNoop(provider.get()));
ASSERT_FALSE(isNoopMeterProvider(provider.get()));
ASSERT_NOT_EQUALS(provider.get(), nullptr);
metrics::shutdown();
shutdown();
}
}
@ -185,16 +181,15 @@ TEST_F(OtelMetricsInitializationTest, ValidCompressionParam) {
getMetricsPath()};
RAIIServerParameterControllerForTest compressionParam{"openTelemetryMetricsCompression",
"none"};
ASSERT_OK(metrics::initialize());
ASSERT_OK(initialize());
auto provider = opentelemetry::metrics::Provider::GetMeterProvider();
ASSERT_FALSE(isNoop(provider.get()));
ASSERT_FALSE(isNoopMeterProvider(provider.get()));
ASSERT_NOT_EQUALS(provider.get(), nullptr);
metrics::shutdown();
shutdown();
}
} // namespace
} // namespace otel
} // namespace mongo
} // namespace mongo::otel::metrics
#endif

View File

@ -30,26 +30,12 @@
#include "mongo/otel/metrics/metrics_service.h"
#ifdef MONGO_CONFIG_OTEL
#include <opentelemetry/metrics/provider.h>
#endif
namespace mongo::otel::metrics {
namespace {
const auto& getMetricsService = ServiceContext::declareDecoration<MetricsService>();
} // namespace
#ifdef MONGO_CONFIG_OTEL
MetricsService::MetricsService() {
auto provider = opentelemetry::metrics::Provider::GetMeterProvider();
invariant(provider, "Attempted to get the MeterProvider after shutdown() was called");
_meter = provider->GetMeter(std::string{kMeterName});
}
#else
MetricsService::MetricsService() {}
#endif
MetricsService& MetricsService::get(ServiceContext* serviceContext) {
return getMetricsService(serviceContext);
}

View File

@ -36,7 +36,7 @@
#ifdef MONGO_CONFIG_OTEL
#include <opentelemetry/metrics/meter.h>
#include <opentelemetry/metrics/provider.h>
namespace mongo::otel::metrics {
@ -51,21 +51,18 @@ public:
static MetricsService& get(ServiceContext*);
MetricsService();
// TODO SERVER-114945 Remove this method once we can validate meter construction succeeded via
// the Instruments it produces
opentelemetry::metrics::Meter* getMeter_forTest() const {
return _meter.get();
auto provider = opentelemetry::metrics::Provider::GetMeterProvider();
invariant(provider, "Attempted to get the MeterProvider after shutdown() was called");
return provider->GetMeter(std::string{kMeterName}).get();
}
// TODO SERVER-114945 Add MetricsService::createUInt64Counter method
// TODO SERVER-114954 Implement MetricsService::createUInt64Gauge
// TODO SERVER-114955 Implement MetricsService::createDoubleGauge
// TODO SERVER-115164 Implement MetricsService::createHistogram method
private:
std::shared_ptr<opentelemetry::metrics::Meter> _meter{nullptr};
};
} // namespace mongo::otel::metrics
#else
@ -75,8 +72,6 @@ public:
static constexpr StringData kMeterName = "mongodb";
static MetricsService& get(ServiceContext*);
MetricsService();
};
} // namespace mongo::otel::metrics
#endif

View File

@ -31,9 +31,8 @@
#include "mongo/config.h"
#include "mongo/db/service_context_test_fixture.h"
#include "mongo/idl/server_parameter_test_controller.h"
#include "mongo/otel/metrics/metrics_initialization.h"
#include "mongo/unittest/temp_dir.h"
#include "mongo/otel/metrics/metrics_test_util.h"
#include "mongo/unittest/unittest.h"
#include <opentelemetry/metrics/provider.h>
@ -42,41 +41,19 @@
namespace mongo::otel::metrics {
namespace {
/**
* Helper class that initializes OpenTelemetry metrics before ServiceContextTest
* creates the ServiceContext. This ensures MetricsService decoration gets a real
* SDK MeterProvider instead of a NoopMeterProvider.
*/
class MetricsInitializationHelper {
public:
MetricsInitializationHelper()
: _featureFlagController("featureFlagOtelMetrics", true),
_directoryController("openTelemetryMetricsDirectory", _tempMetricsDir.path()) {
// Initialize metrics before ServiceContext is created
auto status = metrics::initialize();
invariant(status.isOK(), status.reason());
}
~MetricsInitializationHelper() {
metrics::shutdown();
}
private:
unittest::TempDir _tempMetricsDir{"otel_metrics_test"};
RAIIServerParameterControllerForTest _featureFlagController;
RAIIServerParameterControllerForTest _directoryController;
};
// MetricsInitializationHelper must come before ServiceContextTest in inheritance
// so that metrics are initialized before ServiceContext is created.
class MetricsServiceTest : public MetricsInitializationHelper, public ServiceContextTest {};
class MetricsServiceTest : public ServiceContextTest {};
// Assert that when a valid MeterProvider in place, we create a working Meter implementation with
// the expected metadata.
TEST_F(MetricsServiceTest, MeterIsInitialized) {
// Set up a valid MeterProvider.
OtelMetricsCapturer metricsCapturer;
const auto& metricsService = MetricsService::get(getServiceContext());
auto* meter = metricsService.getMeter_forTest();
ASSERT_TRUE(meter);
// Cast to SDK Meter to access GetInstrumentationScope
auto* sdkMeter = dynamic_cast<opentelemetry::sdk::metrics::Meter*>(meter);
ASSERT_TRUE(sdkMeter);
@ -85,18 +62,11 @@ TEST_F(MetricsServiceTest, MeterIsInitialized) {
ASSERT_EQ(scope->GetName(), std::string{MetricsService::kMeterName});
}
// Assert that we create a NoopMeter if the global MeterProvider hasn't been set before
// initialization.
class MetricsServiceBadInitializationTest : public ServiceContextTest {};
bool isNoop(opentelemetry::metrics::Meter* provider) {
return !!dynamic_cast<opentelemetry::metrics::NoopMeter*>(provider);
}
TEST_F(MetricsServiceBadInitializationTest, ServiceContextInitBeforeMeterProvider) {
// Assert that we create a NoopMeter if the global MeterProvider hasn't been set.
TEST_F(MetricsServiceTest, ServiceContextInitBeforeMeterProvider) {
const auto& metricsService = MetricsService::get(getServiceContext());
auto* meter = metricsService.getMeter_forTest();
ASSERT_TRUE(isNoop(meter));
ASSERT_TRUE(isNoopMeter(meter));
}
} // namespace

View File

@ -0,0 +1,136 @@
/**
* Copyright (C) 2025-present MongoDB, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the Server Side Public License in all respects for
* all of the code used other than as permitted herein. If you modify file(s)
* with this exception, you may extend this exception to your version of the
* file(s), but you are not obligated to do so. If you do not wish to do so,
* delete this exception statement from your version. If you delete this
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
#pragma once
#include "mongo/idl/server_parameter_test_controller.h"
#include "mongo/util/modules.h"
#include <opentelemetry/exporters/memory/in_memory_data.h>
#include <opentelemetry/exporters/memory/in_memory_metric_data.h>
#include <opentelemetry/exporters/memory/in_memory_metric_exporter_factory.h>
#include <opentelemetry/metrics/noop.h>
#include <opentelemetry/metrics/provider.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/meter_provider.h>
#include <opentelemetry/sdk/metrics/meter_provider_factory.h>
#include <opentelemetry/sdk/metrics/metric_reader.h>
namespace mongo::otel::metrics {
namespace {
/**
* The MetricReader is the OTel component that connects the exporter with each registered
* Instrument. This implementation allows callers to trigger collection on-demand so that unit tests
* can collect metrics in a predictable fashion.
*/
class OnDemandMetricReader : public opentelemetry::sdk::metrics::MetricReader {
public:
OnDemandMetricReader(std::unique_ptr<opentelemetry::sdk::metrics::PushMetricExporter> exporter)
: _exporter{std::move(exporter)} {}
opentelemetry::sdk::metrics::AggregationTemporality GetAggregationTemporality(
opentelemetry::sdk::metrics::InstrumentType instrument_type) const noexcept override {
return _exporter->GetAggregationTemporality(instrument_type);
}
void triggerMetricExport() {
this->Collect([this](opentelemetry::sdk::metrics::ResourceMetrics& metric_data) {
this->_exporter->Export(metric_data);
return true;
});
}
private:
bool OnForceFlush(std::chrono::microseconds) noexcept override {
return true;
}
bool OnShutDown(std::chrono::microseconds) noexcept override {
return true;
}
std::unique_ptr<opentelemetry::sdk::metrics::PushMetricExporter> _exporter;
};
} // namespace
bool isNoopMeter(opentelemetry::metrics::Meter* provider) {
return !!dynamic_cast<opentelemetry::metrics::NoopMeter*>(provider);
}
bool isNoopMeterProvider(opentelemetry::metrics::MeterProvider* provider) {
return !!dynamic_cast<opentelemetry::metrics::NoopMeterProvider*>(provider);
}
/**
* Sets up a MetricProvider with an in-memory exporter so tests can create and inspect metrics.
* This must be constructed before creating any metrics in order to capture them.
*/
class MONGO_MOD_PUBLIC OtelMetricsCapturer {
public:
OtelMetricsCapturer() {
invariant(isNoopMeterProvider(opentelemetry::metrics::Provider::GetMeterProvider().get()));
auto metrics =
std::make_shared<opentelemetry::exporter::memory::SimpleAggregateInMemoryMetricData>();
_metrics = metrics.get();
auto exporter = opentelemetry::exporter::memory::InMemoryMetricExporterFactory::Create(
std::move(metrics));
auto reader = std::make_shared<OnDemandMetricReader>(std::move(exporter));
_reader = reader.get();
std::shared_ptr<opentelemetry::sdk::metrics::MeterProvider> provider =
opentelemetry::sdk::metrics::MeterProviderFactory::Create();
provider->AddMetricReader(std::move(reader));
opentelemetry::metrics::Provider::SetMeterProvider(std::move(provider));
}
~OtelMetricsCapturer() {
opentelemetry::metrics::Provider::SetMeterProvider(
opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider>(
new opentelemetry::metrics::NoopMeterProvider()));
}
// TODO SERVER-115538 When we actually have instrument reading to consume, implement a wrapper
// around SimpleAggregateInMemoryMetricData::Get that easily exposes the data we need.
private:
RAIIServerParameterControllerForTest _featureFlagController{"featureFlagOtelMetrics", true};
// Stash the reader so that callers can trigger on-demand metric collection.
OnDemandMetricReader* _reader;
// This is the in-memory data structure that holds the collected metrics. The exporter writes to
// this DS, and the get() function will read from it.
opentelemetry::exporter::memory::SimpleAggregateInMemoryMetricData* _metrics;
};
} // namespace mongo::otel::metrics

View File

@ -0,0 +1,107 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
load("//bazel:mongo_src_rules.bzl", "mongo_cc_library")
load("//src/third_party/opentelemetry-cpp:otel_rules.bzl", "OTEL_COPTS", "OTEL_TARGET_COMPATIBLE_WITH")
package(default_visibility = ["//visibility:public"])
mongo_cc_library(
name = "in_memory_metric_data",
testonly = True,
srcs = [
"src/in_memory_metric_data.cc",
],
hdrs = [
"include/opentelemetry/exporters/memory/in_memory_metric_data.h",
],
strip_include_prefix = "include",
tags = [
"memory",
"test",
],
target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
copts = OTEL_COPTS,
deps = [
":in_memory_data",
"//src/third_party/opentelemetry-cpp/sdk/src/metrics",
],
)
mongo_cc_library(
name = "in_memory_metric_exporter_factory",
testonly = True,
srcs = [
"src/in_memory_metric_exporter_factory.cc",
],
hdrs = [
"include/opentelemetry/exporters/memory/in_memory_metric_exporter_factory.h",
],
strip_include_prefix = "include",
tags = [
"memory",
"test",
],
target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
copts = OTEL_COPTS,
deps = [
":in_memory_metric_data",
"//src/third_party/opentelemetry-cpp/sdk/src/metrics",
],
)
mongo_cc_library(
name = "in_memory_data",
testonly = True,
hdrs = [
"include/opentelemetry/exporters/memory/in_memory_data.h",
],
strip_include_prefix = "include",
tags = ["memory"],
target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
copts = OTEL_COPTS,
deps = [
"//src/third_party/opentelemetry-cpp/sdk/src/metrics",
],
)
mongo_cc_library(
name = "in_memory_span_data",
testonly = True,
hdrs = [
"include/opentelemetry/exporters/memory/in_memory_span_data.h",
],
strip_include_prefix = "include",
tags = ["memory"],
target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
copts = OTEL_COPTS,
deps = [
":in_memory_data",
"//src/third_party/opentelemetry-cpp/api",
"//src/third_party/opentelemetry-cpp/sdk/src/resource",
"//src/third_party/opentelemetry-cpp/sdk/src/trace",
],
)
mongo_cc_library(
name = "in_memory_span_exporter",
testonly = True,
srcs = [
"src/in_memory_span_exporter_factory.cc",
],
hdrs = [
"include/opentelemetry/exporters/memory/in_memory_span_exporter.h",
"include/opentelemetry/exporters/memory/in_memory_span_exporter_factory.h",
],
strip_include_prefix = "include",
tags = [
"memory",
"test",
],
target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
copts = OTEL_COPTS,
deps = [
":in_memory_span_data",
"//src/third_party/opentelemetry-cpp/sdk/src/trace",
],
)

View File

@ -0,0 +1,62 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/sdk/common/circular_buffer.h"
#include <vector>
OPENTELEMETRY_BEGIN_NAMESPACE
namespace exporter
{
namespace memory
{
/**
* A wrapper class holding in memory exporter data
*/
template <typename T>
class InMemoryData
{
public:
/**
* @param buffer_size a required value that sets the size of the CircularBuffer
*/
InMemoryData(size_t buffer_size) : data_(buffer_size) {}
/**
* @param data a required unique pointer to the data to add to the CircularBuffer
*/
void Add(std::unique_ptr<T> data) noexcept { data_.Add(data); }
/**
* @return Returns a vector of unique pointers containing all the data in the
* CircularBuffer. This operation will empty the Buffer, which is why the data
* is returned as unique pointers
*/
std::vector<std::unique_ptr<T>> Get() noexcept
{
std::vector<std::unique_ptr<T>> res;
// Pointer swap is required because the Consume function requires that the
// AtomicUniquePointer be set to null
data_.Consume(
data_.size(), [&](opentelemetry::sdk::common::CircularBufferRange<
opentelemetry::sdk::common::AtomicUniquePtr<T>> range) noexcept {
range.ForEach([&](opentelemetry::sdk::common::AtomicUniquePtr<T> &ptr) noexcept {
std::unique_ptr<T> swap_ptr = nullptr;
ptr.Swap(swap_ptr);
res.push_back(std::move(swap_ptr));
return true;
});
});
return res;
}
private:
opentelemetry::sdk::common::CircularBuffer<T> data_;
};
} // namespace memory
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE

View File

@ -0,0 +1,72 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <map>
#include <memory>
#include <string>
#include <tuple>
#include "opentelemetry/exporters/memory/in_memory_data.h"
#include "opentelemetry/sdk/metrics/data/metric_data.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace sdk
{
namespace metrics
{
struct ResourceMetrics;
}
} // namespace sdk
namespace exporter
{
namespace memory
{
/// The abstract base class for types used to store in-memory data backing an
/// InMemoryMetricExporter.
class InMemoryMetricData
{
public:
InMemoryMetricData() = default;
virtual ~InMemoryMetricData() = default;
InMemoryMetricData(const InMemoryMetricData &) = delete;
InMemoryMetricData(InMemoryMetricData &&) = delete;
InMemoryMetricData &operator=(const InMemoryMetricData &) = delete;
InMemoryMetricData &operator=(InMemoryMetricData &&) = delete;
virtual void Add(std::unique_ptr<sdk::metrics::ResourceMetrics> resource_metrics) = 0;
};
/// An implementation of InMemoryMetricData that stores full-fidelity data points in a circular
/// buffer. This allows tests to inspect every aspect of exported data, in exchange for a somewhat
/// cumbersome API.
class CircularBufferInMemoryMetricData final : public InMemoryMetricData,
public InMemoryData<sdk::metrics::ResourceMetrics>
{
public:
explicit CircularBufferInMemoryMetricData(size_t buffer_size);
void Add(std::unique_ptr<sdk::metrics::ResourceMetrics> resource_metrics) override;
};
/// An implementation of InMemoryMetricData that stores only the most recent data point in each time
/// series, and allows convenient lookups of time series. This makes simple tests easier to write.
class SimpleAggregateInMemoryMetricData final : public InMemoryMetricData
{
public:
using AttributeToPoint = std::map<opentelemetry::sdk::metrics::PointAttributes,
opentelemetry::sdk::metrics::PointType>;
void Add(std::unique_ptr<sdk::metrics::ResourceMetrics> resource_metrics) override;
const AttributeToPoint &Get(const std::string &scope, const std::string &metric);
void Clear();
private:
std::map<std::tuple<std::string, std::string>, AttributeToPoint> data_;
};
} // namespace memory
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE

View File

@ -0,0 +1,44 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <memory>
#include "opentelemetry/sdk/metrics/instruments.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace sdk
{
namespace metrics
{
class PushMetricExporter;
} // namespace metrics
} // namespace sdk
namespace exporter
{
namespace memory
{
class InMemoryMetricData;
/// A factory for InMemoryMetricExporter
class InMemoryMetricExporterFactory
{
public:
/// Create a InMemoryMetricExporter with a default buffer size and aggregation
/// temporality selector.
/// @param [out] data the InMemoryMetricData the exporter will write to,
/// for the caller to inspect
/// @param [in] buffer_size number of entries to save in the circular buffer
/// @param [in] temporality output temporality as a function of instrument kind
static std::unique_ptr<opentelemetry::sdk::metrics::PushMetricExporter> Create(
const std::shared_ptr<InMemoryMetricData> &data,
const sdk::metrics::AggregationTemporalitySelector &temporality);
static std::unique_ptr<opentelemetry::sdk::metrics::PushMetricExporter> Create(
const std::shared_ptr<InMemoryMetricData> &data);
};
} // namespace memory
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE

View File

@ -0,0 +1,33 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <stddef.h>
#include <memory>
#include <vector>
#include "opentelemetry/exporters/memory/in_memory_data.h"
#include "opentelemetry/sdk/trace/span_data.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace exporter
{
namespace memory
{
class InMemorySpanData final : public exporter::memory::InMemoryData<sdk::trace::SpanData>
{
public:
/**
* @param buffer_size a required value that sets the size of the CircularBuffer
*/
explicit InMemorySpanData(size_t buffer_size)
: exporter::memory::InMemoryData<sdk::trace::SpanData>(buffer_size)
{}
std::vector<std::unique_ptr<sdk::trace::SpanData>> GetSpans() noexcept { return Get(); }
};
} // namespace memory
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE

View File

@ -0,0 +1,101 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <stddef.h>
#include <atomic>
#include <chrono>
#include <memory>
#include <ostream>
#include <utility>
#include "opentelemetry/exporters/memory/in_memory_span_data.h"
#include "opentelemetry/nostd/span.h"
#include "opentelemetry/sdk/common/exporter_utils.h"
#include "opentelemetry/sdk/common/global_log_handler.h"
#include "opentelemetry/sdk/trace/exporter.h"
#include "opentelemetry/sdk/trace/recordable.h"
#include "opentelemetry/sdk/trace/span_data.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace exporter
{
namespace memory
{
const size_t MAX_BUFFER_SIZE = 100;
/**
* A in memory exporter that switches a flag once a valid recordable was received
* and keeps track of all received spans in memory.
*/
class InMemorySpanExporter final : public opentelemetry::sdk::trace::SpanExporter
{
public:
/**
* @param buffer_size an optional value that sets the size of the InMemorySpanData
*/
InMemorySpanExporter(size_t buffer_size = MAX_BUFFER_SIZE)
: data_(new InMemorySpanData(buffer_size))
{}
/**
* @return Returns a unique pointer to an empty recordable object
*/
std::unique_ptr<sdk::trace::Recordable> MakeRecordable() noexcept override
{
return std::unique_ptr<sdk::trace::Recordable>(new sdk::trace::SpanData());
}
/**
* @param recordables a required span containing unique pointers to the data
* to add to the InMemorySpanData
* @return Returns the result of the operation
*/
sdk::common::ExportResult Export(
const nostd::span<std::unique_ptr<sdk::trace::Recordable>> &recordables) noexcept override
{
if (isShutdown())
{
OTEL_INTERNAL_LOG_ERROR("[In Memory Span Exporter] Exporting "
<< recordables.size() << " span(s) failed, exporter is shutdown");
return sdk::common::ExportResult::kFailure;
}
for (auto &recordable : recordables)
{
auto span = std::unique_ptr<sdk::trace::SpanData>(
static_cast<sdk::trace::SpanData *>(recordable.release()));
if (span != nullptr)
{
data_->Add(std::move(span));
}
}
return sdk::common::ExportResult::kSuccess;
}
/**
* @param timeout an optional value containing the timeout of the exporter
* note: passing custom timeout values is not currently supported for this exporter
* @return Returns the status of the operation
*/
bool Shutdown(std::chrono::microseconds /* timeout */) noexcept override
{
is_shutdown_ = true;
return true;
}
/**
* @return Returns a shared pointer to this exporters InMemorySpanData
*/
std::shared_ptr<InMemorySpanData> GetData() noexcept { return data_; }
private:
std::shared_ptr<InMemorySpanData> data_;
std::atomic<bool> is_shutdown_{false};
bool isShutdown() const noexcept { return is_shutdown_; }
};
} // namespace memory
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE

View File

@ -0,0 +1,46 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <stddef.h>
#include <memory>
#include "opentelemetry/exporters/memory/in_memory_span_data.h"
#include "opentelemetry/sdk/trace/exporter.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace exporter
{
namespace memory
{
/**
* Factory class for InMemorySpanExporter.
*/
class InMemorySpanExporterFactory
{
public:
/**
* Create a InMemorySpanExporter with a default buffer size.
* @param [out] data the InMemorySpanData the exporter will write to,
* for the caller to inspect
*/
static std::unique_ptr<opentelemetry::sdk::trace::SpanExporter> Create(
std::shared_ptr<InMemorySpanData> &data);
/**
* Create a InMemorySpanExporter with a default buffer size.
* @param [out] data the InMemorySpanData the exporter will write to,
* for the caller to inspect
* @param [in] buffer_size size of the underlying InMemorySpanData
*/
static std::unique_ptr<opentelemetry::sdk::trace::SpanExporter> Create(
std::shared_ptr<InMemorySpanData> &data,
size_t buffer_size);
};
} // namespace memory
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE

View File

@ -0,0 +1,54 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#include "opentelemetry/exporters/memory/in_memory_metric_data.h"
#include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
#include "opentelemetry/sdk/metrics/export/metric_producer.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace exporter
{
namespace memory
{
using sdk::metrics::ResourceMetrics;
CircularBufferInMemoryMetricData::CircularBufferInMemoryMetricData(size_t buffer_size)
: InMemoryData(buffer_size)
{}
void CircularBufferInMemoryMetricData::Add(std::unique_ptr<ResourceMetrics> resource_metrics)
{
InMemoryData::Add(std::move(resource_metrics));
}
void SimpleAggregateInMemoryMetricData::Add(std::unique_ptr<ResourceMetrics> resource_metrics)
{
for (const auto &sm : resource_metrics->scope_metric_data_)
{
const auto &scope = sm.scope_->GetName();
for (const auto &m : sm.metric_data_)
{
const auto &metric = m.instrument_descriptor.name_;
for (const auto &pda : m.point_data_attr_)
{
data_[{scope, metric}].insert({pda.attributes, pda.point_data});
}
}
}
}
const SimpleAggregateInMemoryMetricData::AttributeToPoint &SimpleAggregateInMemoryMetricData::Get(
const std::string &scope,
const std::string &metric)
{
return data_[{scope, metric}];
}
void SimpleAggregateInMemoryMetricData::Clear()
{
data_.clear();
}
} // namespace memory
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE

View File

@ -0,0 +1,93 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#include "opentelemetry/exporters/memory/in_memory_metric_exporter_factory.h"
#include "opentelemetry/exporters/memory/in_memory_metric_data.h"
#include "opentelemetry/sdk/common/global_log_handler.h"
#include "opentelemetry/sdk/metrics/export/metric_producer.h"
#include "opentelemetry/sdk/metrics/push_metric_exporter.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace exporter
{
namespace memory
{
using opentelemetry::sdk::metrics::PushMetricExporter;
using sdk::common::ExportResult;
using sdk::metrics::AggregationTemporality;
using sdk::metrics::AggregationTemporalitySelector;
using sdk::metrics::InstrumentType;
using sdk::metrics::ResourceMetrics;
namespace
{
/// A Push Metric Exporter which accumulates metrics data in memory and allows it to be inspected.
/// It is not thread-safe.
class InMemoryMetricExporter final : public sdk::metrics::PushMetricExporter
{
public:
/// @param buffer_size a required value that sets the size of the CircularBuffer
/// @param temporality Output temporality as a function of instrument kind.
InMemoryMetricExporter(const std::shared_ptr<InMemoryMetricData> &data,
const sdk::metrics::AggregationTemporalitySelector &temporality)
: data_(data), temporality_(temporality)
{}
~InMemoryMetricExporter() override = default;
InMemoryMetricExporter(const InMemoryMetricExporter &) = delete;
InMemoryMetricExporter(const InMemoryMetricExporter &&) = delete;
void operator=(const InMemoryMetricExporter &) = delete;
void operator=(const InMemoryMetricExporter &&) = delete;
ExportResult Export(const ResourceMetrics &data) noexcept override
{
if (is_shutdown_)
{
OTEL_INTERNAL_LOG_ERROR("[In Memory Metric Exporter] Exporting failed, exporter is shutdown");
return ExportResult::kFailure;
}
data_->Add(std::make_unique<ResourceMetrics>(data));
return ExportResult::kSuccess;
}
AggregationTemporality GetAggregationTemporality(
InstrumentType instrument_type) const noexcept override
{
return temporality_(instrument_type);
}
bool ForceFlush(std::chrono::microseconds /* timeout */) noexcept override { return true; }
bool Shutdown(std::chrono::microseconds /* timeout */) noexcept override
{
is_shutdown_ = true;
return true;
}
private:
std::shared_ptr<InMemoryMetricData> data_;
std::atomic<bool> is_shutdown_{false};
sdk::metrics::AggregationTemporalitySelector temporality_;
};
} // namespace
std::unique_ptr<PushMetricExporter> InMemoryMetricExporterFactory::Create(
const std::shared_ptr<InMemoryMetricData> &data)
{
return Create(data, [](auto) { return AggregationTemporality::kCumulative; });
}
std::unique_ptr<PushMetricExporter> InMemoryMetricExporterFactory::Create(
const std::shared_ptr<InMemoryMetricData> &data,
const AggregationTemporalitySelector &temporality)
{
return std::make_unique<InMemoryMetricExporter>(data, temporality);
}
} // namespace memory
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE

View File

@ -0,0 +1,33 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#include "opentelemetry/exporters/memory/in_memory_span_exporter_factory.h"
#include "opentelemetry/exporters/memory/in_memory_span_data.h"
#include "opentelemetry/exporters/memory/in_memory_span_exporter.h"
#include "opentelemetry/sdk/trace/exporter.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace exporter
{
namespace memory
{
std::unique_ptr<opentelemetry::sdk::trace::SpanExporter> InMemorySpanExporterFactory::Create(
std::shared_ptr<InMemorySpanData> &data)
{
return Create(data, MAX_BUFFER_SIZE);
}
std::unique_ptr<opentelemetry::sdk::trace::SpanExporter> InMemorySpanExporterFactory::Create(
std::shared_ptr<InMemorySpanData> &data,
size_t buffer_size)
{
InMemorySpanExporter *memory_exporter = new InMemorySpanExporter(buffer_size);
data = memory_exporter->GetData();
std::unique_ptr<opentelemetry::sdk::trace::SpanExporter> exporter(memory_exporter);
return exporter;
}
} // namespace memory
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE

View File

@ -0,0 +1,55 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#include "opentelemetry/exporters/memory/in_memory_metric_data.h"
#include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
#include "opentelemetry/sdk/metrics/export/metric_producer.h"
#include "opentelemetry/sdk/resource/resource.h"
#include <gtest/gtest.h>
#include <vector>
using opentelemetry::exporter::memory::CircularBufferInMemoryMetricData;
using opentelemetry::exporter::memory::SimpleAggregateInMemoryMetricData;
using opentelemetry::sdk::metrics::MetricData;
using opentelemetry::sdk::metrics::PointDataAttributes;
using opentelemetry::sdk::metrics::ResourceMetrics;
using opentelemetry::sdk::metrics::ScopeMetrics;
using opentelemetry::sdk::metrics::SumPointData;
using opentelemetry::sdk::resource::Resource;
TEST(InMemoryMetricDataTest, CircularBuffer)
{
CircularBufferInMemoryMetricData buf(10);
Resource resource = Resource::GetEmpty();
buf.Add(std::make_unique<ResourceMetrics>(
&resource, std::vector<ScopeMetrics>{{nullptr, std::vector<MetricData>{}}}));
EXPECT_EQ((*buf.Get().begin())->resource_, &resource);
}
TEST(InMemoryMetricDataTest, SimpleAggregate)
{
SimpleAggregateInMemoryMetricData agg;
Resource resource = Resource::GetEmpty();
auto scope = opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create(
"my-scope", "1.0.0", "http://example.com");
SumPointData spd;
spd.value_ = 42.0;
PointDataAttributes pda{{{"hello", "world"}}, spd};
MetricData md;
md.instrument_descriptor.name_ = "my-metric";
md.point_data_attr_.push_back(pda);
agg.Add(std::make_unique<ResourceMetrics>(
&resource, std::vector<ScopeMetrics>{{scope.get(), std::vector<MetricData>{md}}}));
auto it = agg.Get("my-scope", "my-metric").begin();
auto saved_point = opentelemetry::nostd::get<SumPointData>(it->second);
EXPECT_EQ(opentelemetry::nostd::get<double>(saved_point.value_), 42.0);
}

View File

@ -0,0 +1,60 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#include "opentelemetry/exporters/memory/in_memory_metric_data.h"
#include "opentelemetry/exporters/memory/in_memory_metric_exporter_factory.h"
#include "opentelemetry/sdk/metrics/export/metric_producer.h"
#include "opentelemetry/sdk/metrics/instruments.h"
#include "opentelemetry/sdk/metrics/push_metric_exporter.h"
#include "opentelemetry/sdk/resource/resource.h"
#include <gtest/gtest.h>
using opentelemetry::exporter::memory::CircularBufferInMemoryMetricData;
using opentelemetry::exporter::memory::InMemoryMetricExporterFactory;
using opentelemetry::sdk::common::ExportResult;
using opentelemetry::sdk::metrics::AggregationTemporality;
using opentelemetry::sdk::metrics::InstrumentType;
using opentelemetry::sdk::metrics::PushMetricExporter;
using opentelemetry::sdk::metrics::ResourceMetrics;
using opentelemetry::sdk::metrics::ScopeMetrics;
using opentelemetry::sdk::resource::Resource;
class InMemoryMetricExporterTest : public ::testing::Test
{
protected:
InMemoryMetricExporterTest() { exporter_ = InMemoryMetricExporterFactory::Create(data_); }
std::unique_ptr<PushMetricExporter> exporter_;
std::shared_ptr<CircularBufferInMemoryMetricData> data_ =
std::make_shared<CircularBufferInMemoryMetricData>(10);
Resource resource_ = Resource::GetEmpty();
ResourceMetrics resource_metrics_{&resource_, std::vector<ScopeMetrics>{}};
};
TEST_F(InMemoryMetricExporterTest, Export)
{
EXPECT_EQ(exporter_->Export(resource_metrics_), ExportResult::kSuccess);
auto data = data_->Get();
EXPECT_EQ(data.size(), 1);
EXPECT_EQ((*data.begin())->resource_, &resource_);
}
TEST_F(InMemoryMetricExporterTest, ForceFlush)
{
EXPECT_TRUE(exporter_->ForceFlush());
}
TEST_F(InMemoryMetricExporterTest, Shutdown)
{
EXPECT_TRUE(exporter_->Shutdown());
EXPECT_EQ(exporter_->Export(resource_metrics_), ExportResult::kFailure);
}
TEST_F(InMemoryMetricExporterTest, TemporalitySelector)
{
EXPECT_EQ(exporter_->GetAggregationTemporality(InstrumentType::kCounter),
AggregationTemporality::kCumulative);
}

View File

@ -0,0 +1,27 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#include "opentelemetry/exporters/memory/in_memory_span_data.h"
#include "opentelemetry/nostd/span.h"
#include "opentelemetry/sdk/trace/span_data.h"
#include <gtest/gtest.h>
using opentelemetry::exporter::memory::InMemorySpanData;
using opentelemetry::sdk::trace::SpanData;
TEST(InMemorySpanData, AddRecordable)
{
InMemorySpanData data(100);
ASSERT_EQ(0, data.GetSpans().size());
std::unique_ptr<SpanData> spandata(new SpanData());
data.Add(std::move(spandata));
// Consumes all spans in exporter
ASSERT_EQ(1, data.GetSpans().size());
ASSERT_EQ(0, data.GetSpans().size());
}

View File

@ -0,0 +1,29 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#include "opentelemetry/exporters/memory/in_memory_span_exporter.h"
#include "opentelemetry/nostd/span.h"
#include "opentelemetry/sdk/trace/span_data.h"
#include <gtest/gtest.h>
using opentelemetry::exporter::memory::InMemorySpanExporter;
using opentelemetry::sdk::trace::Recordable;
using opentelemetry::sdk::trace::SpanData;
TEST(InMemorySpanExporter, ExportBatch)
{
InMemorySpanExporter exporter;
ASSERT_EQ(0, exporter.GetData().get()->GetSpans().size());
std::unique_ptr<Recordable> spandata(new SpanData());
opentelemetry::nostd::span<std::unique_ptr<Recordable>> batch(&spandata, 1);
exporter.Export(batch);
ASSERT_EQ(1, exporter.GetData().get()->GetSpans().size());
// Consumes all spans in exporter
ASSERT_EQ(0, exporter.GetData().get()->GetSpans().size());
}

View File

@ -0,0 +1,163 @@
diff --git a/src/third_party/opentelemetry-cpp/dist/exporters/memory/BUILD b/src/third_party/opentelemetry-cpp/dist/exporters/memory/BUILD
index 033c85d3698..377d6025f77 100644
--- a/src/third_party/opentelemetry-cpp/dist/exporters/memory/BUILD
+++ b/src/third_party/opentelemetry-cpp/dist/exporters/memory/BUILD
@@ -1,10 +1,14 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
+load("//bazel:mongo_src_rules.bzl", "mongo_cc_library")
+load("//src/third_party/opentelemetry-cpp:otel_rules.bzl", "OTEL_COPTS", "OTEL_TARGET_COMPATIBLE_WITH")
+
package(default_visibility = ["//visibility:public"])
-cc_library(
+mongo_cc_library(
name = "in_memory_metric_data",
+ testonly = True,
srcs = [
"src/in_memory_metric_data.cc",
],
@@ -16,27 +20,17 @@ cc_library(
"memory",
"test",
],
+ target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
+ copts = OTEL_COPTS,
deps = [
":in_memory_data",
- "//sdk/src/metrics",
- ],
-)
-
-cc_test(
- name = "in_memory_metric_data_test",
- srcs = ["test/in_memory_metric_data_test.cc"],
- tags = [
- "memory",
- "test",
- ],
- deps = [
- ":in_memory_metric_data",
- "@com_google_googletest//:gtest_main",
+ "//src/third_party/opentelemetry-cpp/sdk/src/metrics",
],
)
-cc_library(
+mongo_cc_library(
name = "in_memory_metric_exporter_factory",
+ testonly = True,
srcs = [
"src/in_memory_metric_exporter_factory.cc",
],
@@ -48,67 +42,50 @@ cc_library(
"memory",
"test",
],
+ target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
+ copts = OTEL_COPTS,
deps = [
":in_memory_metric_data",
- "//sdk/src/metrics",
- ],
-)
-
-cc_test(
- name = "in_memory_metric_exporter_test",
- srcs = ["test/in_memory_metric_exporter_test.cc"],
- tags = [
- "memory",
- "test",
- ],
- deps = [
- ":in_memory_metric_exporter_factory",
- "@com_google_googletest//:gtest_main",
+ "//src/third_party/opentelemetry-cpp/sdk/src/metrics",
],
)
-cc_library(
+mongo_cc_library(
name = "in_memory_data",
+ testonly = True,
hdrs = [
"include/opentelemetry/exporters/memory/in_memory_data.h",
],
strip_include_prefix = "include",
tags = ["memory"],
+ target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
+ copts = OTEL_COPTS,
deps = [
- "//sdk:headers",
+ "//src/third_party/opentelemetry-cpp/sdk/src/metrics",
],
)
-cc_library(
+mongo_cc_library(
name = "in_memory_span_data",
+ testonly = True,
hdrs = [
"include/opentelemetry/exporters/memory/in_memory_span_data.h",
],
strip_include_prefix = "include",
tags = ["memory"],
+ target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
+ copts = OTEL_COPTS,
deps = [
":in_memory_data",
- "//api",
- "//sdk/src/resource",
- "//sdk/src/trace",
+ "//src/third_party/opentelemetry-cpp/api",
+ "//src/third_party/opentelemetry-cpp/sdk/src/resource",
+ "//src/third_party/opentelemetry-cpp/sdk/src/trace",
],
)
-cc_test(
- name = "in_memory_span_data_test",
- srcs = ["test/in_memory_span_data_test.cc"],
- tags = [
- "memory",
- "test",
- ],
- deps = [
- ":in_memory_span_data",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_library(
+mongo_cc_library(
name = "in_memory_span_exporter",
+ testonly = True,
srcs = [
"src/in_memory_span_exporter_factory.cc",
],
@@ -121,21 +98,10 @@ cc_library(
"memory",
"test",
],
+ target_compatible_with = OTEL_TARGET_COMPATIBLE_WITH,
+ copts = OTEL_COPTS,
deps = [
":in_memory_span_data",
- "//sdk/src/trace",
- ],
-)
-
-cc_test(
- name = "in_memory_span_exporter_test",
- srcs = ["test/in_memory_span_exporter_test.cc"],
- tags = [
- "memory",
- "test",
- ],
- deps = [
- ":in_memory_span_exporter",
- "@com_google_googletest//:gtest_main",
+ "//src/third_party/opentelemetry-cpp/sdk/src/trace",
],
)

View File

@ -54,7 +54,6 @@ rm -rf sdk/src/logs
# Uneeded exporters
rm -rf exporters/elasticsearch
rm -rf exporters/etw
rm -rf exporters/memory
rm -rf exporters/ostream
rm -rf exporters/prometheus
rm -rf exporters/zipkin
@ -72,6 +71,7 @@ git apply "${PATCHES_DIR}/0002-Build-system-changes-for-opentelemetry-cpp.patch"
git apply "${PATCHES_DIR}/0003-Build-system-changes-for-opentelemetry-cpp.patch"
git apply "${PATCHES_DIR}/0001-SERVER-100631-update-api-BUILD.patch"
git apply "${PATCHES_DIR}/0001-SERVER-106258-vendor-OpenTelemetry-gRPC-exporter.patch"
git apply "${PATCHES_DIR}/0004-SERVER-115315-vendor-memory-exporter.patch"
cp -R ${DIST}/* ${LIBDIR}/
echo ${DIST}