Skip to content
Closed
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 @@ -15,6 +15,9 @@ Increment the:

## [Unreleased]

* [EXPORTER] Prometheus: Adding ability to disable timestamps from metric points
[#3894](https://github.com/open-telemetry/opentelemetry-cpp/pull/3894)

* [TEST] Add multi-threaded metrics benchmarks for shared vs per-thread counter
[#3865](https://github.com/open-telemetry/opentelemetry-cpp/pull/3865)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ struct PrometheusExporterOptions

// Option to export metrics without the type suffix
bool without_type_suffix = false;

// Option to export metrics without a timestamp
bool without_timestamps = false;
};

} // namespace metrics
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ class PrometheusExporterUtils
bool populate_target_info = true,
bool without_otel_scope = false,
bool without_units = false,
bool without_type_suffix = false);
bool without_type_suffix = false,
bool without_timestamps = false);

private:
/**
Expand Down Expand Up @@ -154,6 +155,7 @@ class PrometheusExporterUtils
*/
static void SetTarget(const sdk::metrics::ResourceMetrics &data,
std::chrono::nanoseconds time,
bool without_timestamps,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
std::vector<::prometheus::MetricFamily> *output);

Expand All @@ -167,6 +169,7 @@ class PrometheusExporterUtils
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
::prometheus::MetricType type,
std::chrono::nanoseconds time,
bool without_timestamps,
::prometheus::MetricFamily *metric_family,
const opentelemetry::sdk::resource::Resource *resource);

Expand All @@ -181,6 +184,7 @@ class PrometheusExporterUtils
const opentelemetry::sdk::metrics::PointAttributes &labels,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
std::chrono::nanoseconds time,
bool without_timestamps,
::prometheus::MetricFamily *metric_family,
const opentelemetry::sdk::resource::Resource *resource);

Expand All @@ -191,6 +195,7 @@ class PrometheusExporterUtils
::prometheus::ClientMetric &metric,
const opentelemetry::sdk::metrics::PointAttributes &labels,
std::chrono::nanoseconds time,
bool without_timestamps,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
const opentelemetry::sdk::resource::Resource *resource);

Expand Down
13 changes: 12 additions & 1 deletion exporters/prometheus/src/exporter_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,23 @@ static inline bool GetPrometheusWithoutTypeSuffix()
return exists ? setting : false;
}

inline bool GetPrometheusWithoutTimestamps()
{
constexpr char kPrometheusWithoutTypeSuffix[] = "OTEL_CPP_PROMETHEUS_EXPORTER_WITHOUT_TIMESTAMPS";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit - The variable is named kPrometheusWithoutTypeSuffix but holds the timestamps env var. Should be kPrometheusWithoutTimestamps?

bool setting{};
const auto exists =
opentelemetry::sdk::common::GetBoolEnvironmentVariable(kPrometheusWithoutTypeSuffix, setting);

return exists ? setting : false;
}

PrometheusExporterOptions::PrometheusExporterOptions()
: url(GetPrometheusDefaultHttpEndpoint()),
populate_target_info(GetPrometheusPopulateTargetInfo()),
without_otel_scope(GetPrometheusWithoutOtelScope()),
without_units(GetPrometheusWithoutUnits()),
without_type_suffix(GetPrometheusWithoutTypeSuffix())
without_type_suffix(GetPrometheusWithoutTypeSuffix()),
without_timestamps(GetPrometheusWithoutTimestamps())
{}

PrometheusExporterOptions::PrometheusExporterOptions(void *) : url("") {}
Expand Down
36 changes: 23 additions & 13 deletions exporters/prometheus/src/exporter_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ std::vector<prometheus_client::MetricFamily> PrometheusExporterUtils::TranslateT
bool populate_target_info,
bool without_otel_scope,
bool without_units,
bool without_type_suffix)
bool without_type_suffix,
bool without_timestamps)
{

// initialize output vector
Expand All @@ -140,6 +141,7 @@ std::vector<prometheus_client::MetricFamily> PrometheusExporterUtils::TranslateT
{
SetTarget(data,
data.scope_metric_data_.begin()->metric_data_.begin()->end_ts.time_since_epoch(),
without_timestamps,
without_otel_scope ? nullptr : (*data.scope_metric_data_.begin()).scope_, &output);
}

Expand Down Expand Up @@ -185,8 +187,8 @@ std::vector<prometheus_client::MetricFamily> PrometheusExporterUtils::TranslateT
sum = static_cast<double>(nostd::get<int64_t>(histogram_point_data.sum_));
}
SetData(std::vector<double>{sum, static_cast<double>(histogram_point_data.count_)},
boundaries, counts, point_data_attr.attributes, scope, time, &metric_family,
data.resource_);
boundaries, counts, point_data_attr.attributes, scope, time, without_timestamps,
&metric_family, data.resource_);
}
else if (type == prometheus_client::MetricType::Gauge)
{
Expand All @@ -196,16 +198,16 @@ std::vector<prometheus_client::MetricFamily> PrometheusExporterUtils::TranslateT
auto last_value_point_data =
nostd::get<sdk::metrics::LastValuePointData>(point_data_attr.point_data);
std::vector<metric_sdk::ValueType> values{last_value_point_data.value_};
SetData(values, point_data_attr.attributes, scope, type, time, &metric_family,
data.resource_);
SetData(values, point_data_attr.attributes, scope, type, time, without_timestamps,
&metric_family, data.resource_);
}
else if (nostd::holds_alternative<sdk::metrics::SumPointData>(point_data_attr.point_data))
{
auto sum_point_data =
nostd::get<sdk::metrics::SumPointData>(point_data_attr.point_data);
std::vector<metric_sdk::ValueType> values{sum_point_data.value_};
SetData(values, point_data_attr.attributes, scope, type, time, &metric_family,
data.resource_);
SetData(values, point_data_attr.attributes, scope, type, time, without_timestamps,
&metric_family, data.resource_);
}
else
{
Expand All @@ -221,8 +223,8 @@ std::vector<prometheus_client::MetricFamily> PrometheusExporterUtils::TranslateT
auto sum_point_data =
nostd::get<sdk::metrics::SumPointData>(point_data_attr.point_data);
std::vector<metric_sdk::ValueType> values{sum_point_data.value_};
SetData(values, point_data_attr.attributes, scope, type, time, &metric_family,
data.resource_);
SetData(values, point_data_attr.attributes, scope, type, time, without_timestamps,
&metric_family, data.resource_);
}
else
{
Expand Down Expand Up @@ -606,6 +608,7 @@ prometheus_client::MetricType PrometheusExporterUtils::TranslateType(
void PrometheusExporterUtils::SetTarget(
const sdk::metrics::ResourceMetrics &data,
std::chrono::nanoseconds time,
bool without_timestamps,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
std::vector<::prometheus::MetricFamily> *output)
{
Expand All @@ -624,7 +627,7 @@ void PrometheusExporterUtils::SetTarget(
metric.info.value = 1.0;

metric_sdk::PointAttributes empty_attributes;
SetMetricBasic(metric, empty_attributes, time, scope, data.resource_);
SetMetricBasic(metric, empty_attributes, time, without_timestamps, scope, data.resource_);

for (auto &label : data.resource_->GetAttributes())
{
Expand All @@ -646,12 +649,13 @@ void PrometheusExporterUtils::SetData(
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
prometheus_client::MetricType type,
std::chrono::nanoseconds time,
bool without_timestamps,
prometheus_client::MetricFamily *metric_family,
const opentelemetry::sdk::resource::Resource *resource)
{
metric_family->metric.emplace_back();
prometheus_client::ClientMetric &metric = metric_family->metric.back();
SetMetricBasic(metric, labels, time, scope, resource);
SetMetricBasic(metric, labels, time, without_timestamps, scope, resource);
SetValue(values, type, &metric);
}

Expand All @@ -667,12 +671,13 @@ void PrometheusExporterUtils::SetData(
const metric_sdk::PointAttributes &labels,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
std::chrono::nanoseconds time,
bool without_timestamps,
prometheus_client::MetricFamily *metric_family,
const opentelemetry::sdk::resource::Resource *resource)
{
metric_family->metric.emplace_back();
prometheus_client::ClientMetric &metric = metric_family->metric.back();
SetMetricBasic(metric, labels, time, scope, resource);
SetMetricBasic(metric, labels, time, without_timestamps, scope, resource);
SetValue(values, boundaries, counts, &metric);
}

Expand All @@ -683,10 +688,15 @@ void PrometheusExporterUtils::SetMetricBasic(
prometheus_client::ClientMetric &metric,
const metric_sdk::PointAttributes &labels,
std::chrono::nanoseconds time,
bool without_timestamps,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
const opentelemetry::sdk::resource::Resource *resource)
{
metric.timestamp_ms = time.count() / 1000000;
if (!without_timestamps)
{
metric.timestamp_ms = time.count() / 1000000;
}

if (labels.empty() && nullptr == resource)
{
return;
Expand Down
46 changes: 44 additions & 2 deletions exporters/prometheus/test/exporter_utils_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,10 @@ static void assert_basic(prometheus_client::MetricFamily &metric,
ASSERT_EQ(metric.help, description); // description not changed
ASSERT_EQ(metric.type, type); // type translated

// Prometheus metric data points should not have explicit timestamps
for (const prometheus::ClientMetric &cm : metric.metric)
{
ASSERT_EQ(cm.timestamp_ms, 0);
// end_ts is set as 1766662560000
ASSERT_EQ(cm.timestamp_ms, 1766662560);
}

auto metric_data = metric.metric[0];
Expand Down Expand Up @@ -286,6 +286,48 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal)
ASSERT_EQ(checked_label_num, 3);
}

class TimestampTest : public ::testing::Test
{
opentelemetry::sdk::resource::Resource resource_ =
opentelemetry::sdk::resource::Resource::Create({{"service.name", "test_service"}});

protected:
void CheckTimestamp(bool without_timestamps, metric_sdk::ResourceMetrics metrics_data)
{
metrics_data.resource_ = &resource_;
auto translated = PrometheusExporterUtils::TranslateToPrometheus(
metrics_data, false, false, false, false, without_timestamps);

auto metric = translated[0];
for (const prometheus::ClientMetric &cm : metric.metric)
{
if (without_timestamps)
{
// Prometheus metric data points should not have explicit timestamps
ASSERT_EQ(cm.timestamp_ms, 0);
}
else
{
// end_ts is set as 1766662560000
ASSERT_EQ(cm.timestamp_ms, 1766662560);
}
}
}
};

TEST_F(TimestampTest, Timestamp)
{
TestDataPoints dp;
// Without timestamps
CheckTimestamp(true, dp.CreateHistogramPointData());
CheckTimestamp(true, dp.CreateSumPointData());
CheckTimestamp(true, dp.CreateLastValuePointData());
// With timestamps
CheckTimestamp(false, dp.CreateHistogramPointData());
CheckTimestamp(false, dp.CreateSumPointData());
CheckTimestamp(false, dp.CreateLastValuePointData());
}

class SanitizeTest : public ::testing::Test
{
Resource resource_ = Resource::Create({});
Expand Down
17 changes: 9 additions & 8 deletions exporters/prometheus/test/prometheus_test_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ struct TestDataPoints
Resource resource = Resource::Create(ResourceAttributes{});
nostd::unique_ptr<InstrumentationScope> instrumentation_scope =
InstrumentationScope::Create("library_name", "1.2.0");
opentelemetry::common::SystemTimestamp start_ts =
opentelemetry::common::SystemTimestamp{std::chrono::microseconds{1766662500000}};
opentelemetry::common::SystemTimestamp end_ts =
opentelemetry::common::SystemTimestamp{std::chrono::microseconds{1766662560000}};

/**
* Helper function to create ResourceMetrics
Expand All @@ -39,8 +43,7 @@ struct TestDataPoints
metric_sdk::InstrumentDescriptor{"library_name", "description", "unit",
metric_sdk::InstrumentType::kCounter,
metric_sdk::InstrumentValueType::kDouble},
metric_sdk::AggregationTemporality::kDelta, opentelemetry::common::SystemTimestamp{},
opentelemetry::common::SystemTimestamp{},
metric_sdk::AggregationTemporality::kDelta, start_ts, end_ts,
std::vector<metric_sdk::PointDataAttributes>{
{metric_sdk::PointAttributes{{"a1", "b1"}}, sum_point_data},
{metric_sdk::PointAttributes{{"a2", "b2"}}, sum_point_data2}}};
Expand All @@ -67,13 +70,13 @@ struct TestDataPoints
metric_sdk::InstrumentDescriptor{"library_name", "description", "unit",
metric_sdk::InstrumentType::kHistogram,
metric_sdk::InstrumentValueType::kDouble},
metric_sdk::AggregationTemporality::kDelta, opentelemetry::common::SystemTimestamp{},
opentelemetry::common::SystemTimestamp{},
metric_sdk::AggregationTemporality::kDelta, start_ts, end_ts,
std::vector<metric_sdk::PointDataAttributes>{
{metric_sdk::PointAttributes{{"a1", "b1"}}, histogram_point_data},
{metric_sdk::PointAttributes{{"a2", "b2"}}, histogram_point_data2}}};
data.scope_metric_data_ = std::vector<metric_sdk::ScopeMetrics>{
{instrumentation_scope.get(), std::vector<metric_sdk::MetricData>{metric_data}}};

return data;
}

Expand All @@ -93,8 +96,7 @@ struct TestDataPoints
metric_sdk::InstrumentDescriptor{"library_name", "description", "unit",
metric_sdk::InstrumentType::kCounter,
metric_sdk::InstrumentValueType::kDouble},
metric_sdk::AggregationTemporality::kDelta, opentelemetry::common::SystemTimestamp{},
opentelemetry::common::SystemTimestamp{},
metric_sdk::AggregationTemporality::kDelta, start_ts, end_ts,
std::vector<metric_sdk::PointDataAttributes>{
{metric_sdk::PointAttributes{{"a1", "b1"}}, last_value_point_data},
{metric_sdk::PointAttributes{{"a2", "b2"}}, last_value_point_data2}}};
Expand All @@ -113,8 +115,7 @@ struct TestDataPoints
metric_sdk::InstrumentDescriptor{"library_name", "description", "unit",
metric_sdk::InstrumentType::kCounter,
metric_sdk::InstrumentValueType::kDouble},
metric_sdk::AggregationTemporality::kDelta, opentelemetry::common::SystemTimestamp{},
opentelemetry::common::SystemTimestamp{},
metric_sdk::AggregationTemporality::kDelta, start_ts, end_ts,
std::vector<metric_sdk::PointDataAttributes>{
{metric_sdk::PointAttributes{{"a1", "b1"}}, drop_point_data},
{metric_sdk::PointAttributes{{"a2", "b2"}}, drop_point_data2}}};
Expand Down
Loading