Skip to content

Base2 exponential histogram aggregation #3346

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

Merged
merged 63 commits into from
Apr 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
b62565f
add base2 expo histo aggregation
euroelessar Apr 4, 2025
338cce4
add base2 expo histo, test, benchmark
ethandmd Apr 4, 2025
b03d915
add prom, otlp exporter and example
felipesantosk Apr 4, 2025
423e92d
add ostream exporter and example
ethandmd Apr 4, 2025
a9737bf
update vscode launch
felipesantosk Apr 4, 2025
b2dee01
run tools/format.sh
ethandmd Apr 4, 2025
0f54022
Merge branch 'main' into expo-histo-aggregation-4
ethandmd Apr 4, 2025
250de89
add grpc exporter target switch for unix sockets
ethandmd Apr 4, 2025
4376128
Added ConvertExponentialHistogramMetric unit test
felipesantosk Apr 4, 2025
4408d33
Update the osstream_metric_test with ExponentialHistogram
felipesantosk Apr 4, 2025
21e1d34
update CHANGELOG.md
ethandmd Apr 4, 2025
4397886
markdown lint
ethandmd Apr 4, 2025
9b9d8c1
Comment non-used function add missing includes
felipesantosk Apr 7, 2025
db95400
Merge branch 'main' into expo-histo-aggregation-4
ThomsonTan Apr 7, 2025
775688a
add metrics dependency to otlp exporters test build
ethandmd Apr 8, 2025
b2d7a02
run format
ethandmd Apr 8, 2025
bc96a2f
Merge branch 'main' into expo-histo-aggregation-4
ethandmd Apr 8, 2025
712e538
remove unused function definition
ethandmd Apr 8, 2025
531ac16
Added empty line in the end of a test file and removed comments
felipesantosk Apr 8, 2025
43c0e00
Merge branch 'main' into expo-histo-aggregation-4
lalitb Apr 8, 2025
9146925
Fix windows build errors
felipesantosk Apr 8, 2025
ea3190d
fix iwyu warnings
ethandmd Apr 8, 2025
0fc7071
add comment to trigger pr update
ethandmd Apr 9, 2025
8f2130c
fix additional iwyu warnings
ethandmd Apr 9, 2025
de04603
Fix iwyu warning
felipesantosk Apr 10, 2025
8cf15c4
Fix include order in base2_exponential_histogram_aggregation.h
felipesantosk Apr 10, 2025
f98d198
Merge branch 'main' into expo-histo-aggregation-4
ThomsonTan Apr 14, 2025
66c5a6b
Merge branch 'main' into expo-histo-aggregation-4
ethandmd Apr 15, 2025
84c09d1
Add kcumulative and kdelta aggregation temporality test with collect …
ethandmd Apr 15, 2025
b9e5df6
add prelim bucketing checks
ethandmd Apr 15, 2025
e4daa7b
Tested the exp2 constructor with point data
felipesantosk Apr 16, 2025
c7ca650
Fix missing include in sync histogram test
felipesantosk Apr 16, 2025
81ea997
move diff and merge to use union of all buckets approach
ethandmd Apr 17, 2025
055d331
make get a const method
ethandmd Apr 17, 2025
e5e7b20
update base2 expo hiso diff test
ethandmd Apr 17, 2025
556eb89
add base2 expo histo test with sync storage collect
ethandmd Apr 17, 2025
dc5d956
Merge branch 'expo-histo-aggregation-4' of http://github.com/ethandmd…
ethandmd Apr 17, 2025
e69e73c
uncomment examples
ethandmd Apr 17, 2025
ca542f7
format
ethandmd Apr 17, 2025
9040c38
use static_cast
ethandmd Apr 17, 2025
a7a1234
fix comments
ethandmd Apr 17, 2025
53e025e
update changelog
ethandmd Apr 17, 2025
293e2dd
Fix comments and errors in the pipeline
felipesantosk Apr 21, 2025
9adcfac
Merge branch 'main' into expo-histo-aggregation-4
lalitb Apr 21, 2025
f917c08
Merge branch 'main' into expo-histo-aggregation-4
ethandmd Apr 22, 2025
f184cec
Update sdk/src/metrics/aggregation/base2_exponential_histogram_aggreg…
ethandmd Apr 22, 2025
50ca1c0
remove unused code
ethandmd Apr 22, 2025
ab5441e
set max_buckets minimum to 2
ethandmd Apr 22, 2025
42a904e
Revert otlp grpc client changes
ethandmd Apr 22, 2025
5641bbd
[wip] make buckets unique ptr
ethandmd Apr 22, 2025
e550710
Merge branch 'main' into expo-histo-aggregation-4
ThomsonTan Apr 23, 2025
20ba935
refactor unique_ptr for buckets with deep copies
ethandmd Apr 23, 2025
ea50726
merge
ethandmd Apr 23, 2025
6468765
format
ethandmd Apr 23, 2025
2bfd9da
update otlp serialization test with unique ptr
ethandmd Apr 24, 2025
262425e
Merge branch 'main' into expo-histo-aggregation-4
lalitb Apr 24, 2025
71855a9
format
ethandmd Apr 24, 2025
b1f54d4
Small pipeline fixes
felipesantosk Apr 24, 2025
1d96b3e
iwyu fix
ethandmd Apr 24, 2025
17c94ca
remove boundary and format
ethandmd Apr 24, 2025
d4cbcbc
Merge branch 'main' into expo-histo-aggregation-4
ethandmd Apr 25, 2025
ffbd2fd
Merge branch 'main' into expo-histo-aggregation-4
felipesantosk Apr 25, 2025
beb9227
Merge branch 'main' into expo-histo-aggregation-4
lalitb Apr 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 28 additions & 19 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug on Windows",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build/<path-to-bin-file>",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false
},
{
"name": "Debug on Linux",
"type": "gdb",
"request": "launch",
"target": "${workspaceFolder}/bazel-bin/<path to the bin file>",
"cwd": "${workspaceRoot}",
"valuesFormatting": "parseText"
}
{
"name": "(ctest) Launch",
"type": "cppdbg",
"cwd": "${cmake.testWorkingDirectory}",
"request": "launch",
"program": "${cmake.testProgram}",
"args": [ "${cmake.testArgs}" ],
// other options...
},
{
"name": "Debug on Windows",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build/<path-to-bin-file>",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false
},
{
"name": "Debug on Linux",
"type": "gdb",
"request": "launch",
"target": "${workspaceFolder}/bazel-bin/<path to the bin file>",
"cwd": "${workspaceRoot}",
"valuesFormatting": "parseText"
}
]
}
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ Increment the:

## [Unreleased]

* [SDK] Base2 exponential histogram aggregation
[#3175](https://github.com/open-telemetry/opentelemetry-cpp/pull/3346)

New Features:

Add base2 exponential histogram aggregation. Includes a new aggregation type,
ostream exporter, and otlp/grpc exporter. Updated histogram aggregation and
benchmark tests.

* [API] Remove `WITH_ABSEIL` and `HAVE_ABSEIL`
[#3318](https://github.com/open-telemetry/opentelemetry-cpp/pull/3318)

Expand Down
19 changes: 18 additions & 1 deletion examples/common/metrics_foo_library/foo_library.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,24 @@ void foo_library::histogram_example(const std::string &name)
std::string histogram_name = name + "_histogram";
auto provider = metrics_api::Provider::GetMeterProvider();
opentelemetry::nostd::shared_ptr<metrics_api::Meter> meter = provider->GetMeter(name, "1.2.0");
auto histogram_counter = meter->CreateDoubleHistogram(histogram_name, "des", "unit");
auto histogram_counter = meter->CreateDoubleHistogram(histogram_name, "des", "histogram-unit");
auto context = opentelemetry::context::Context{};
for (uint32_t i = 0; i < 20; ++i)
{
double val = (rand() % 700) + 1.1;
std::map<std::string, std::string> labels = get_random_attr();
auto labelkv = opentelemetry::common::KeyValueIterableView<decltype(labels)>{labels};
histogram_counter->Record(val, labelkv, context);
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
}

void foo_library::histogram_exp_example(const std::string &name)
{
std::string histogram_name = name + "_exponential_histogram";
auto provider = metrics_api::Provider::GetMeterProvider();
auto meter = provider->GetMeter(name, "1.2.0");
auto histogram_counter = meter->CreateDoubleHistogram(histogram_name, "des", "histogram-unit");
auto context = opentelemetry::context::Context{};
for (uint32_t i = 0; i < 20; ++i)
{
Expand Down
1 change: 1 addition & 0 deletions examples/common/metrics_foo_library/foo_library.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class foo_library
public:
static void counter_example(const std::string &name);
static void histogram_example(const std::string &name);
static void histogram_exp_example(const std::string &name);
static void observable_counter_example(const std::string &name);
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
static void gauge_example(const std::string &name);
Expand Down
38 changes: 35 additions & 3 deletions examples/metrics_simple/metrics_ostream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#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_context.h"
#include "opentelemetry/sdk/metrics/meter_context_factory.h"
#include "opentelemetry/sdk/metrics/meter_provider.h"
#include "opentelemetry/sdk/metrics/meter_provider_factory.h"
#include "opentelemetry/sdk/metrics/metric_reader.h"
Expand Down Expand Up @@ -56,9 +58,9 @@ void InitMetrics(const std::string &name)
auto reader =
metrics_sdk::PeriodicExportingMetricReaderFactory::Create(std::move(exporter), options);

auto provider = opentelemetry::sdk::metrics::MeterProviderFactory::Create();

provider->AddMetricReader(std::move(reader));
auto context = metrics_sdk::MeterContextFactory::Create();
context->AddMetricReader(std::move(reader));
auto provider = opentelemetry::sdk::metrics::MeterProviderFactory::Create(std::move(context));

// counter view
std::string counter_name = name + "_counter";
Expand Down Expand Up @@ -112,6 +114,30 @@ void InitMetrics(const std::string &name)
provider->AddView(std::move(histogram_instrument_selector), std::move(histogram_meter_selector),
std::move(histogram_view));

// hisogram view with base2 exponential aggregation
std::string histogram_base2_name = name + "_exponential_histogram";
unit = "histogram-unit";
auto histogram_base2_instrument_selector = metrics_sdk::InstrumentSelectorFactory::Create(
metrics_sdk::InstrumentType::kHistogram, histogram_base2_name, unit);
auto histogram_base2_meter_selector =
metrics_sdk::MeterSelectorFactory::Create(name, version, schema);
auto histogram_base2_aggregation_config =
std::unique_ptr<metrics_sdk::Base2ExponentialHistogramAggregationConfig>(
new metrics_sdk::Base2ExponentialHistogramAggregationConfig);
histogram_base2_aggregation_config->max_scale_ = 3;
histogram_base2_aggregation_config->record_min_max_ = true;
histogram_base2_aggregation_config->max_buckets_ = 100;

std::shared_ptr<metrics_sdk::AggregationConfig> base2_aggregation_config(
std::move(histogram_base2_aggregation_config));

auto histogram_base2_view = metrics_sdk::ViewFactory::Create(
name, "description", unit, metrics_sdk::AggregationType::kBase2ExponentialHistogram,
base2_aggregation_config);

provider->AddView(std::move(histogram_base2_instrument_selector),
std::move(histogram_base2_meter_selector), std::move(histogram_base2_view));

std::shared_ptr<opentelemetry::metrics::MeterProvider> api_provider(std::move(provider));

metrics_sdk::Provider::SetMeterProvider(api_provider);
Expand Down Expand Up @@ -147,6 +173,10 @@ int main(int argc, char **argv)
{
foo_library::histogram_example(name);
}
else if (example_type == "exponential_histogram")
{
foo_library::histogram_exp_example(name);
}
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
else if (example_type == "gauge")
{
Expand All @@ -170,6 +200,7 @@ int main(int argc, char **argv)
std::thread counter_example{&foo_library::counter_example, name};
std::thread observable_counter_example{&foo_library::observable_counter_example, name};
std::thread histogram_example{&foo_library::histogram_example, name};
std::thread histogram_exp_example{&foo_library::histogram_exp_example, name};
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
std::thread gauge_example{&foo_library::gauge_example, name};
#endif
Expand All @@ -181,6 +212,7 @@ int main(int argc, char **argv)
counter_example.join();
observable_counter_example.join();
histogram_example.join();
histogram_exp_example.join();
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
gauge_example.join();
#endif
Expand Down
53 changes: 48 additions & 5 deletions examples/otlp/grpc_metric_main.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#include "grpcpp/grpcpp.h"
#include "opentelemetry/exporters/otlp/otlp_grpc_exporter.h"

#include "opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_factory.h"
#include "opentelemetry/metrics/provider.h"
#include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h"
Expand All @@ -11,6 +14,9 @@
#include "opentelemetry/sdk/metrics/meter_provider.h"
#include "opentelemetry/sdk/metrics/meter_provider_factory.h"
#include "opentelemetry/sdk/metrics/provider.h"
#include "opentelemetry/sdk/metrics/view/instrument_selector_factory.h"
#include "opentelemetry/sdk/metrics/view/meter_selector_factory.h"
#include "opentelemetry/sdk/metrics/view/view_factory.h"

#include <memory>
#include <thread>
Expand All @@ -31,7 +37,7 @@ namespace

otlp_exporter::OtlpGrpcMetricExporterOptions exporter_options;

void InitMetrics()
void InitMetrics(std::string &name)
{
auto exporter = otlp_exporter::OtlpGrpcMetricExporterFactory::Create(exporter_options);

Expand All @@ -49,10 +55,34 @@ void InitMetrics()
auto context = metric_sdk::MeterContextFactory::Create();
context->AddMetricReader(std::move(reader));

auto u_provider = metric_sdk::MeterProviderFactory::Create(std::move(context));
std::shared_ptr<opentelemetry::metrics::MeterProvider> provider(std::move(u_provider));
auto provider = metric_sdk::MeterProviderFactory::Create(std::move(context));

// histogram view
std::string histogram_name = name + "_exponential_histogram";
std::string unit = "histogram-unit";

auto histogram_instrument_selector = metric_sdk::InstrumentSelectorFactory::Create(
metric_sdk::InstrumentType::kHistogram, histogram_name, unit);

auto histogram_meter_selector = metric_sdk::MeterSelectorFactory::Create(name, version, schema);

auto histogram_aggregation_config =
std::unique_ptr<metric_sdk::Base2ExponentialHistogramAggregationConfig>(
new metric_sdk::Base2ExponentialHistogramAggregationConfig);

std::shared_ptr<metric_sdk::AggregationConfig> aggregation_config(
std::move(histogram_aggregation_config));

auto histogram_view = metric_sdk::ViewFactory::Create(
name, "des", unit, metric_sdk::AggregationType::kBase2ExponentialHistogram,
aggregation_config);

metric_sdk::Provider::SetMeterProvider(provider);
provider->AddView(std::move(histogram_instrument_selector), std::move(histogram_meter_selector),
std::move(histogram_view));

std::shared_ptr<opentelemetry::metrics::MeterProvider> api_provider(std::move(provider));

metric_sdk::Provider::SetMeterProvider(api_provider);
}

void CleanupMetrics()
Expand All @@ -78,10 +108,17 @@ int main(int argc, char *argv[])
}
}
}
std::cout << "Using endpoint: " << exporter_options.endpoint << std::endl;
std::cout << "Using example type: " << example_type << std::endl;
std::cout << "Using cacert path: " << exporter_options.ssl_credentials_cacert_path << std::endl;
std::cout << "Using ssl credentials: " << exporter_options.use_ssl_credentials << std::endl;

// Removing this line will leave the default noop MetricProvider in place.
InitMetrics();

std::string name{"otlp_grpc_metric_example"};

InitMetrics(name);

if (example_type == "counter")
{
foo_library::counter_example(name);
Expand All @@ -94,6 +131,10 @@ int main(int argc, char *argv[])
{
foo_library::histogram_example(name);
}
else if (example_type == "exponential_histogram")
{
foo_library::histogram_exp_example(name);
}
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
else if (example_type == "gauge")
{
Expand All @@ -105,13 +146,15 @@ int main(int argc, char *argv[])
std::thread counter_example{&foo_library::counter_example, name};
std::thread observable_counter_example{&foo_library::observable_counter_example, name};
std::thread histogram_example{&foo_library::histogram_example, name};
std::thread histogram_exp_example{&foo_library::histogram_exp_example, name};
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
std::thread gauge_example{&foo_library::gauge_example, name};
#endif

counter_example.join();
observable_counter_example.join();
histogram_example.join();
histogram_exp_example.join();
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
gauge_example.join();
#endif
Expand Down
39 changes: 39 additions & 0 deletions exporters/ostream/src/metric_exporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <ctime>
#include <iterator>
#include <map>
#include <memory>
#include <mutex>
#include <ostream>
#include <string>
Expand All @@ -24,6 +25,7 @@
#include "opentelemetry/sdk/common/exporter_utils.h"
#include "opentelemetry/sdk/common/global_log_handler.h"
#include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
#include "opentelemetry/sdk/metrics/data/circular_buffer.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"
Expand Down Expand Up @@ -247,6 +249,43 @@ void OStreamMetricExporter::printPointData(const opentelemetry::sdk::metrics::Po
sout_ << nostd::get<int64_t>(last_point_data.value_);
}
}
else if (nostd::holds_alternative<sdk::metrics::Base2ExponentialHistogramPointData>(point_data))
{
auto histogram_point_data =
nostd::get<sdk::metrics::Base2ExponentialHistogramPointData>(point_data);
if (!histogram_point_data.positive_buckets_ && !histogram_point_data.negative_buckets_)
{
return;
}
sout_ << "\n type: Base2ExponentialHistogramPointData";
sout_ << "\n count: " << histogram_point_data.count_;
sout_ << "\n sum: " << histogram_point_data.sum_;
sout_ << "\n zero_count: " << histogram_point_data.zero_count_;
if (histogram_point_data.record_min_max_)
{
sout_ << "\n min: " << histogram_point_data.min_;
sout_ << "\n max: " << histogram_point_data.max_;
}
sout_ << "\n scale: " << histogram_point_data.scale_;
sout_ << "\n positive buckets:";
if (!histogram_point_data.positive_buckets_->Empty())
{
for (auto i = histogram_point_data.positive_buckets_->StartIndex();
i <= histogram_point_data.positive_buckets_->EndIndex(); ++i)
{
sout_ << "\n\t" << i << ": " << histogram_point_data.positive_buckets_->Get(i);
}
}
sout_ << "\n negative buckets:";
if (!histogram_point_data.negative_buckets_->Empty())
{
for (auto i = histogram_point_data.negative_buckets_->StartIndex();
i <= histogram_point_data.negative_buckets_->EndIndex(); ++i)
{
sout_ << "\n\t" << i << ": " << histogram_point_data.negative_buckets_->Get(i);
}
}
}
}

void OStreamMetricExporter::printPointAttributes(
Expand Down
Loading
Loading