Skip to content

Commit

Permalink
prometheus exporter: Add otel_scope_name and otel_scope_version labels (
Browse files Browse the repository at this point in the history
  • Loading branch information
dashpole authored Oct 2, 2023
1 parent bd11434 commit 0803e6a
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 28 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ Increment the:
[#2224](https://github.com/open-telemetry/opentelemetry-cpp/pull/2224)
* [REMOVAL] Drop C++11 support
[#2342](https://github.com/open-telemetry/opentelemetry-cpp/pull/2342)
* [EXPORTER] Add otel_scope_name and otel_scope_version labels to the prometheus
exporter.
[#2293](https://github.com/open-telemetry/opentelemetry-cpp/pull/2293)

Important changes:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class PrometheusExporterUtils
template <typename T>
static void SetData(std::vector<T> values,
const opentelemetry::sdk::metrics::PointAttributes &labels,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
::prometheus::MetricType type,
::prometheus::MetricFamily *metric_family);

Expand All @@ -60,13 +61,16 @@ class PrometheusExporterUtils
const std::vector<double> &boundaries,
const std::vector<uint64_t> &counts,
const opentelemetry::sdk::metrics::PointAttributes &labels,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
::prometheus::MetricFamily *metric_family);

/**
* Set time and labels to metric data
*/
static void SetMetricBasic(::prometheus::ClientMetric &metric,
const opentelemetry::sdk::metrics::PointAttributes &labels);
static void SetMetricBasic(
::prometheus::ClientMetric &metric,
const opentelemetry::sdk::metrics::PointAttributes &labels,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope);

/**
* Convert attribute value to string
Expand Down
67 changes: 49 additions & 18 deletions exporters/prometheus/src/exporter_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ namespace metrics
{
namespace
{

static constexpr const char *kScopeNameKey = "otel_scope_name";
static constexpr const char *kScopeVersionKey = "otel_scope_version";

/**
* Sanitize the given metric name by replacing invalid characters with _,
* ensuring that multiple consecutive _ characters are collapsed to a single _.
Expand Down Expand Up @@ -150,7 +154,7 @@ std::vector<prometheus_client::MetricFamily> PrometheusExporterUtils::TranslateT
sum = nostd::get<int64_t>(histogram_point_data.sum_);
}
SetData(std::vector<double>{sum, (double)histogram_point_data.count_}, boundaries, counts,
point_data_attr.attributes, &metric_family);
point_data_attr.attributes, instrumentation_info.scope_, &metric_family);
}
else if (type == prometheus_client::MetricType::Gauge)
{
Expand All @@ -160,14 +164,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, type, &metric_family);
SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type,
&metric_family);
}
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, type, &metric_family);
SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type,
&metric_family);
}
else
{
Expand All @@ -183,7 +189,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, type, &metric_family);
SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type,
&metric_family);
}
else
{
Expand Down Expand Up @@ -257,14 +264,16 @@ prometheus_client::MetricType PrometheusExporterUtils::TranslateType(
* sum => Prometheus Counter
*/
template <typename T>
void PrometheusExporterUtils::SetData(std::vector<T> values,
const metric_sdk::PointAttributes &labels,
prometheus_client::MetricType type,
prometheus_client::MetricFamily *metric_family)
void PrometheusExporterUtils::SetData(
std::vector<T> values,
const metric_sdk::PointAttributes &labels,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
prometheus_client::MetricType type,
prometheus_client::MetricFamily *metric_family)
{
metric_family->metric.emplace_back();
prometheus_client::ClientMetric &metric = metric_family->metric.back();
SetMetricBasic(metric, labels);
SetMetricBasic(metric, labels, scope);
SetValue(values, type, &metric);
}

Expand All @@ -273,23 +282,27 @@ void PrometheusExporterUtils::SetData(std::vector<T> values,
* Histogram => Prometheus Histogram
*/
template <typename T>
void PrometheusExporterUtils::SetData(std::vector<T> values,
const std::vector<double> &boundaries,
const std::vector<uint64_t> &counts,
const metric_sdk::PointAttributes &labels,
prometheus_client::MetricFamily *metric_family)
void PrometheusExporterUtils::SetData(
std::vector<T> values,
const std::vector<double> &boundaries,
const std::vector<uint64_t> &counts,
const metric_sdk::PointAttributes &labels,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
prometheus_client::MetricFamily *metric_family)
{
metric_family->metric.emplace_back();
prometheus_client::ClientMetric &metric = metric_family->metric.back();
SetMetricBasic(metric, labels);
SetMetricBasic(metric, labels, scope);
SetValue(values, boundaries, counts, &metric);
}

/**
* Set labels to metric data
*/
void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &metric,
const metric_sdk::PointAttributes &labels)
void PrometheusExporterUtils::SetMetricBasic(
prometheus_client::ClientMetric &metric,
const metric_sdk::PointAttributes &labels,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope)
{
if (labels.empty())
{
Expand All @@ -300,7 +313,7 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me
// Note that attribute keys are sorted, but sanitized keys can be out-of-order.
// We could sort the sanitized keys again, but this seems too expensive to do
// in this hot code path. Instead, we ignore out-of-order keys and emit a warning.
metric.label.reserve(labels.size());
metric.label.reserve(labels.size() + 2);
std::string previous_key;
for (auto const &label : labels)
{
Expand All @@ -324,6 +337,24 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me
<< "'. Ignoring this label.");
}
}
if (!scope)
{
return;
}
auto scope_name = scope->GetName();
if (!scope_name.empty())
{
metric.label.emplace_back();
metric.label.back().name = kScopeNameKey;
metric.label.back().value = std::move(scope_name);
}
auto scope_version = scope->GetVersion();
if (!scope_version.empty())
{
metric.label.emplace_back();
metric.label.back().name = kScopeVersionKey;
metric.label.back().value = std::move(scope_version);
}
}

std::string PrometheusExporterUtils::AttributeValueToString(
Expand Down
22 changes: 14 additions & 8 deletions exporters/prometheus/test/exporter_utils_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerCounter)

auto metric1 = translated[0];
std::vector<int> vals = {10};
assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Counter, 1,
assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Counter, 3,
vals);
}

Expand All @@ -119,7 +119,7 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue)

auto metric1 = translated[0];
std::vector<int> vals = {10};
assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Gauge, 1,
assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Gauge, 3,
vals);
}

Expand All @@ -133,7 +133,7 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal)

auto metric = translated[0];
std::vector<double> vals = {3, 900.5, 4};
assert_basic(metric, "library_name", "description", prometheus_client::MetricType::Histogram, 1,
assert_basic(metric, "library_name", "description", prometheus_client::MetricType::Histogram, 3,
vals);
assert_histogram(metric, std::list<double>{10.1, 20.2, 30.2}, {200, 300, 400, 500});
}
Expand Down Expand Up @@ -211,20 +211,26 @@ class AttributeCollisionTest : public ::testing::Test

TEST_F(AttributeCollisionTest, SeparatesDistinctKeys)
{
CheckTranslation({{"foo.a", "value1"}, {"foo.b", "value2"}},
{{"foo_a", "value1"}, {"foo_b", "value2"}});
CheckTranslation({{"foo.a", "value1"}, {"foo.b", "value2"}}, {{"foo_a", "value1"},
{"foo_b", "value2"},
{"otel_scope_name", "library_name"},
{"otel_scope_version", "1.2.0"}});
}

TEST_F(AttributeCollisionTest, JoinsCollidingKeys)
{
CheckTranslation({{"foo.a", "value1"}, {"foo_a", "value2"}}, //
{{"foo_a", "value1;value2"}});
CheckTranslation({{"foo.a", "value1"}, {"foo_a", "value2"}}, {{"foo_a", "value1;value2"},
{"otel_scope_name", "library_name"},
{"otel_scope_version", "1.2.0"}});
}

TEST_F(AttributeCollisionTest, DropsInvertedKeys)
{
CheckTranslation({{"foo.a", "value1"}, {"foo.b", "value2"}, {"foo__a", "value3"}},
{{"foo_a", "value1"}, {"foo_b", "value2"}});
{{"foo_a", "value1"},
{"foo_b", "value2"},
{"otel_scope_name", "library_name"},
{"otel_scope_version", "1.2.0"}});
}

OPENTELEMETRY_END_NAMESPACE

0 comments on commit 0803e6a

Please sign in to comment.