Skip to content

Commit

Permalink
Fix instance and job exporting
Browse files Browse the repository at this point in the history
  • Loading branch information
owent committed Sep 14, 2023
1 parent a30ddf7 commit 02f4d04
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,6 @@ class PrometheusExporterUtils
*/
static bool ShouldIgnoreResourceAttribute(const std::string &name);

/**
* Some attributes should be renamed when converting resource attributes to
* prometheus labels.
*
* @param name resource attribute name
* @return const std::string&
*/
static const std::string &GetPrometheusAttributeName(const std::string &name);

static opentelemetry::sdk::metrics::AggregationType getAggregationType(
const opentelemetry::sdk::metrics::PointType &point_type);

Expand Down
129 changes: 82 additions & 47 deletions exporters/prometheus/src/exporter_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ namespace metrics
{

static constexpr const char *kPrometheusInstance = "instance";
static constexpr const char *kPrometheusJob = "job";

/**
* Helper function to convert OpenTelemetry metrics data collection
Expand Down Expand Up @@ -205,23 +206,13 @@ bool PrometheusExporterUtils::ShouldIgnoreResourceAttribute(const std::string &n
opentelemetry::sdk::resource::SemanticConventions::kServiceNamespace,
opentelemetry::trace::SemanticConventions::kServerAddress,
opentelemetry::trace::SemanticConventions::kServerPort,
opentelemetry::trace::SemanticConventions::kUrlScheme};
opentelemetry::trace::SemanticConventions::kUrlScheme,
opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId,
kPrometheusJob,
kPrometheusInstance};
return ignores.end() != ignores.find(name);
}

const std::string &PrometheusExporterUtils::GetPrometheusAttributeName(const std::string &name)
{
static std::unordered_map<std::string, std::string> name_mappings{
{opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId, kPrometheusInstance}};
std::unordered_map<std::string, std::string>::const_iterator it = name_mappings.find(name);
if (it == name_mappings.end())
{
return name;
}

return it->second;
}

metric_sdk::AggregationType PrometheusExporterUtils::getAggregationType(
const metric_sdk::PointType &point_type)
{
Expand Down Expand Up @@ -321,9 +312,11 @@ void PrometheusExporterUtils::SetTarget(const sdk::metrics::ResourceMetrics &dat
continue;
}

AddPrometheusLabel(SanitizeNames(GetPrometheusAttributeName(label.first)),
AttributeValueToString(label.second), &metric.label);
AddPrometheusLabel(SanitizeNames(label.first), AttributeValueToString(label.second),
&metric.label);
}

output->emplace_back(std::move(metric_family));
}

/**
Expand Down Expand Up @@ -384,37 +377,9 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me
}
metric.label.reserve(label_size);

// Convert resource to prometheus labels
bool has_instance_label = false;
if (nullptr != resource)
{
opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_name_it =
resource->GetAttributes().find(
opentelemetry::sdk::resource::SemanticConventions::kServiceName);
opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_namespace_it =
resource->GetAttributes().find(
opentelemetry::sdk::resource::SemanticConventions::kServiceNamespace);

if (service_namespace_it != resource->GetAttributes().end() &&
service_name_it != resource->GetAttributes().end())
{
AddPrometheusLabel("job",
AttributeValueToString(service_namespace_it->second) + "/" +
AttributeValueToString(service_name_it->second),
&metric.label);
}
else if (service_name_it != resource->GetAttributes().end())
{
AddPrometheusLabel("job", AttributeValueToString(service_name_it->second), &metric.label);
}
else if (service_namespace_it != resource->GetAttributes().end())
{
AddPrometheusLabel("job", AttributeValueToString(service_namespace_it->second),
&metric.label);
}
}

// auto label_pairs = ParseLabel(labels);
bool has_instance_label = false;
bool has_job_label = false;
if (!labels.empty())
{
for (auto &label : labels)
Expand All @@ -424,16 +389,86 @@ void PrometheusExporterUtils::SetMetricBasic(prometheus_client::ClientMetric &me
continue;
}

std::string label_name = SanitizeNames(GetPrometheusAttributeName(label.first));
std::string label_name = SanitizeNames(label.first);
if (label_name == kPrometheusInstance)
{
has_instance_label = true;
}
else if (label_name == kPrometheusJob)
{
has_job_label = true;
}
AddPrometheusLabel(std::move(label_name), AttributeValueToString(label.second),
&metric.label);
}
}

// Convert resource to prometheus labels
if (nullptr != resource)
{
do
{
if (has_job_label)
{
break;
}

opentelemetry::sdk::resource::ResourceAttributes::const_iterator prometheus_job_it =
resource->GetAttributes().find(kPrometheusJob);
if (prometheus_job_it != resource->GetAttributes().end())
{
AddPrometheusLabel(kPrometheusJob, AttributeValueToString(prometheus_job_it->second),
&metric.label);
break;
}

opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_name_it =
resource->GetAttributes().find(
opentelemetry::sdk::resource::SemanticConventions::kServiceName);
opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_namespace_it =
resource->GetAttributes().find(
opentelemetry::sdk::resource::SemanticConventions::kServiceNamespace);

if (service_namespace_it != resource->GetAttributes().end() &&
service_name_it != resource->GetAttributes().end())
{
AddPrometheusLabel(kPrometheusJob,
AttributeValueToString(service_namespace_it->second) + "/" +
AttributeValueToString(service_name_it->second),
&metric.label);
}
else if (service_name_it != resource->GetAttributes().end())
{
AddPrometheusLabel(kPrometheusJob, AttributeValueToString(service_name_it->second),
&metric.label);
}
else if (service_namespace_it != resource->GetAttributes().end())
{
AddPrometheusLabel(kPrometheusJob,
AttributeValueToString(service_namespace_it->second) + "/",
&metric.label);
}
} while (false);

if (!has_instance_label)
{
opentelemetry::sdk::resource::ResourceAttributes::const_iterator service_instance_id_it =
resource->GetAttributes().find(
opentelemetry::sdk::resource::SemanticConventions::kServiceInstanceId);
if (service_instance_id_it == resource->GetAttributes().end())
{
service_instance_id_it = resource->GetAttributes().find(kPrometheusInstance);
}
if (service_instance_id_it != resource->GetAttributes().end())
{
has_instance_label = true;
AddPrometheusLabel(kPrometheusInstance,
AttributeValueToString(service_instance_id_it->second), &metric.label);
}
}
}

// Add a empty instance label if it's not exist
if (!has_instance_label)
{
AddPrometheusLabel(kPrometheusInstance, "", &metric.label);
Expand Down
2 changes: 1 addition & 1 deletion exporters/prometheus/test/collector_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ TEST(PrometheusCollector, BasicTests)

// Collection size should be the same as the size
// of the records collection produced by MetricProducer.
ASSERT_EQ(data.size(), 1);
ASSERT_EQ(data.size(), 2);
delete reader;
delete producer;
}
98 changes: 86 additions & 12 deletions exporters/prometheus/test/exporter_utils_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,32 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerCounter)
metrics_data.resource_ = &resource;

auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data);
ASSERT_EQ(translated.size(), 1);
ASSERT_EQ(translated.size(), 2);

auto metric1 = translated[0];
auto metric1 = translated[1];
std::vector<int> vals = {10};

assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Counter,
resource.GetAttributes().size(), vals);
assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Counter, 3,
vals);

int checked_label_num = 0;
for (auto &label : metric1.metric[0].label)
{
if (label.name == "job")
{
ASSERT_EQ(label.value, "test_namespace/test_service");
checked_label_num++;
}
else if (label.name == "instance")
{
ASSERT_EQ(label.value, "localhost:8000");
checked_label_num++;
}
}
ASSERT_EQ(checked_label_num, 2);

checked_label_num = 0;
for (auto &label : translated[0].metric[0].label)
{
if (label.name == "job")
{
Expand Down Expand Up @@ -157,15 +173,31 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue)
metrics_data.resource_ = &resource;

auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data);
ASSERT_EQ(translated.size(), 1);
ASSERT_EQ(translated.size(), 2);

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

int checked_label_num = 0;
for (auto &label : metric1.metric[0].label)
{
if (label.name == "job")
{
ASSERT_EQ(label.value, "test_service");
checked_label_num++;
}
else if (label.name == "instance")
{
ASSERT_EQ(label.value, "localhost:8000");
checked_label_num++;
}
}
ASSERT_EQ(checked_label_num, 2);

checked_label_num = 0;
for (auto &label : translated[0].metric[0].label)
{
if (label.name == "job")
{
Expand All @@ -188,16 +220,58 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue)

TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal)
{
opentelemetry::sdk::resource::Resource resource = opentelemetry::sdk::resource::Resource::Create(
{{"job", "test_service2"},
{"instance", "localhost:8001"},
{"custom_resource_attr", "custom_resource_value"}});
metric_sdk::ResourceMetrics metrics_data = CreateHistogramPointData();
metrics_data.resource_ = &resource;

auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data);
ASSERT_EQ(translated.size(), 1);
ASSERT_EQ(translated.size(), 2);

auto metric = translated[0];
auto metric = translated[1];
std::vector<double> vals = {3, 900.5, 4};
assert_basic(metric, "library_name", "description", prometheus_client::MetricType::Histogram,
metrics_data.resource_->GetAttributes().size() + 1, vals);
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});

int checked_label_num = 0;
for (auto &label : metric.metric[0].label)
{
if (label.name == "job")
{
ASSERT_EQ(label.value, "test_service2");
checked_label_num++;
}
else if (label.name == "instance")
{
ASSERT_EQ(label.value, "localhost:8001");
checked_label_num++;
}
}
ASSERT_EQ(checked_label_num, 2);

checked_label_num = 0;
for (auto &label : translated[0].metric[0].label)
{
if (label.name == "job")
{
ASSERT_EQ(label.value, "test_service2");
checked_label_num++;
}
else if (label.name == "instance")
{
ASSERT_EQ(label.value, "localhost:8001");
checked_label_num++;
}
else if (label.name == "custom_resource_attr")
{
ASSERT_EQ(label.value, "custom_resource_value");
checked_label_num++;
}
}
ASSERT_EQ(checked_label_num, 3);
}

TEST(PrometheusExporterUtils, SanitizeName)
Expand Down

0 comments on commit 02f4d04

Please sign in to comment.