Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EXPORTER] Implement in-memory metric exporter #3043

Merged
merged 1 commit into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ Increment the:
* [REMOVAL] Remove build option `WITH_DEPRECATED_SDK_FACTORY`
[#2717](https://github.com/open-telemetry/opentelemetry-cpp/pull/2717)

* [EXPORTER] Add in-memory metric exporter
[#3043](https://github.com/open-telemetry/opentelemetry-cpp/pull/3043)

Breaking changes:

* [REMOVAL] Remove build option `WITH_DEPRECATED_SDK_FACTORY`
Expand Down
78 changes: 77 additions & 1 deletion exporters/memory/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,90 @@
package(default_visibility = ["//visibility:public"])

cc_library(
name = "in_memory_span_data",
name = "in_memory_metric_data",
srcs = [
"src/in_memory_metric_data.cc",
],
hdrs = [
"include/opentelemetry/exporters/memory/in_memory_metric_data.h",
],
strip_include_prefix = "include",
tags = [
"memory",
"test",
],
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",
],
)

cc_library(
name = "in_memory_metric_exporter_factory",
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",
],
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",
],
)

cc_library(
name = "in_memory_data",
hdrs = [
"include/opentelemetry/exporters/memory/in_memory_data.h",
],
strip_include_prefix = "include",
tags = ["memory"],
deps = [
"//sdk:headers",
],
)

cc_library(
name = "in_memory_span_data",
hdrs = [
"include/opentelemetry/exporters/memory/in_memory_span_data.h",
],
strip_include_prefix = "include",
tags = ["memory"],
deps = [
":in_memory_data",
"//api",
"//sdk/src/resource",
"//sdk/src/trace",
Expand Down
38 changes: 38 additions & 0 deletions exporters/memory/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,26 @@ set_target_version(opentelemetry_exporter_in_memory)
target_link_libraries(opentelemetry_exporter_in_memory
PUBLIC opentelemetry_trace)

add_library(
opentelemetry_exporter_in_memory_metric
src/in_memory_metric_exporter_factory.cc src/in_memory_metric_data.cc)

target_include_directories(
opentelemetry_exporter_in_memory_metric
PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
"$<INSTALL_INTERFACE:include>")

set_target_properties(opentelemetry_exporter_in_memory_metric
PROPERTIES EXPORT_NAME in_memory_metric_exporter)
set_target_version(opentelemetry_exporter_in_memory_metric)

target_link_libraries(opentelemetry_exporter_in_memory_metric
PUBLIC opentelemetry_metrics)

if(OPENTELEMETRY_INSTALL)
install(
TARGETS opentelemetry_exporter_in_memory
opentelemetry_exporter_in_memory_metric
EXPORT "${PROJECT_NAME}-target"
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
Expand All @@ -35,16 +52,29 @@ if(BUILD_TESTING)
add_executable(in_memory_span_data_test test/in_memory_span_data_test.cc)
add_executable(in_memory_span_exporter_test
test/in_memory_span_exporter_test.cc)
add_executable(in_memory_metric_data_test test/in_memory_metric_data_test.cc)
add_executable(in_memory_metric_exporter_test
test/in_memory_metric_exporter_test.cc)

target_link_libraries(
in_memory_span_data_test ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}
opentelemetry_exporter_in_memory opentelemetry_resources)

target_link_libraries(
in_memory_metric_data_test ${GTEST_BOTH_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT} opentelemetry_exporter_in_memory_metric
opentelemetry_resources)

target_link_libraries(
in_memory_span_exporter_test ${GTEST_BOTH_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT} opentelemetry_exporter_in_memory
opentelemetry_resources)

target_link_libraries(
in_memory_metric_exporter_test ${GTEST_BOTH_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT} opentelemetry_exporter_in_memory_metric
opentelemetry_resources)

gtest_add_tests(
TARGET in_memory_span_data_test
TEST_PREFIX exporter.
Expand All @@ -53,4 +83,12 @@ if(BUILD_TESTING)
TARGET in_memory_span_exporter_test
TEST_PREFIX exporter.
TEST_LIST in_memory_span_exporter_test)
gtest_add_tests(
TARGET in_memory_metric_data_test
TEST_PREFIX exporter.
TEST_LIST in_memory_metric_data_test)
gtest_add_tests(
TARGET in_memory_metric_exporter_test
TEST_PREFIX exporter.
TEST_LIST in_memory_metric_exporter_test)
endif()
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
54 changes: 54 additions & 0 deletions exporters/memory/src/in_memory_metric_data.cc
Original file line number Diff line number Diff line change
@@ -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
Loading
Loading