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] Prometheus: Add unit to names, convert to word #2213

Merged
merged 17 commits into from
Nov 22, 2023

Conversation

esigo
Copy link
Member

@esigo esigo commented Jul 1, 2023

Fixes #1840 Fixes #2317 (issue)

Changes

Please provide a brief description of the changes here.

For significant contributions please make sure you have completed the following items:

  • CHANGELOG.md updated for non-trivial changes
  • Unit tests have been added
  • Changes in public API reviewed

@codecov
Copy link

codecov bot commented Jul 1, 2023

Codecov Report

Merging #2213 (c80ebb9) into main (9b89843) will not change coverage.
The diff coverage is n/a.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #2213   +/-   ##
=======================================
  Coverage   87.43%   87.43%           
=======================================
  Files         199      199           
  Lines        6052     6052           
=======================================
  Hits         5291     5291           
  Misses        761      761           

@esigo esigo added the area:exporter:prometheus Prometheus Exporter label Jul 1, 2023
@esigo esigo force-pushed the 1840-Prometheus-unit-name branch from 940fed8 to 06b2288 Compare July 2, 2023 09:02
@esigo esigo marked this pull request as ready for review July 8, 2023 09:11
@esigo esigo requested a review from a team July 8, 2023 09:11
@esigo esigo changed the title [WIP] Prometheus: Add unit to names, convert to word Prometheus: Add unit to names, convert to word Jul 8, 2023
Copy link
Member

@marcalff marcalff left a comment

Choose a reason for hiding this comment

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

I don't understand the inner loops of
PrometheusExporterUtils::TranslateToPrometheus(),
and the change there, please clarify.

It seems the name mapping is done for every data point of a metric, instead of once per metric.

}

std::vector<std::string> rate_entities;
size_t pos = rate_expressed_unit.find("/");
Copy link
Member

Choose a reason for hiding this comment

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

nit

do not execute the find twice, save the result in pos and test for pos == std::string::npos at the start of this method.

Comment on lines 54 to 58
prometheus_client::MetricFamily metric_family;
metric_family.type = type;
metric_family.name = MapToPrometheusName(metric_data.instrument_descriptor.name_,
metric_data.instrument_descriptor.unit_, type);
metric_family.help = metric_data.instrument_descriptor.description_;
Copy link
Member

Choose a reason for hiding this comment

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

This code moved inside the loop on data points.

The metric name, type, help, etc should be constant for all data points, so can this be moved outside ?

Even if type is needed and not available elsewhere, peek at the first data point before entering the loop on data points ?

Copy link
Contributor

Choose a reason for hiding this comment

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

+1. As long as it is safe to assume all data points have the same type, peeking at the first seems like the right thing to do. I took that approach in https://github.com/open-telemetry/opentelemetry-cpp/pull/2288/files#diff-e92aebc994eed5c134b09ecde972d9db39a9bfc46edc6d93b0b5a4c98e4ff27fR46.

Copy link
Member Author

Choose a reason for hiding this comment

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

thanks, moved back to where it was.

Copy link
Contributor

@dashpole dashpole left a comment

Choose a reason for hiding this comment

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

Apologies for duplicating work, and thanks for working on this! It looks like this fixes #2287 as well, so i'll close my PR.

Comment on lines 54 to 58
prometheus_client::MetricFamily metric_family;
metric_family.type = type;
metric_family.name = MapToPrometheusName(metric_data.instrument_descriptor.name_,
metric_data.instrument_descriptor.unit_, type);
metric_family.help = metric_data.instrument_descriptor.description_;
Copy link
Contributor

Choose a reason for hiding this comment

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

+1. As long as it is safe to assume all data points have the same type, peeking at the first seems like the right thing to do. I took that approach in https://github.com/open-telemetry/opentelemetry-cpp/pull/2288/files#diff-e92aebc994eed5c134b09ecde972d9db39a9bfc46edc6d93b0b5a4c98e4ff27fR46.

@@ -114,8 +114,8 @@ std::vector<prometheus_client::MetricFamily> PrometheusExporterUtils::TranslateT
"invalid SumPointData type");
}
}
output.emplace_back(metric_family);
Copy link
Contributor

Choose a reason for hiding this comment

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

Does the prometheus C++ library merge metric families? We definitely don't want one metric family for each data point.

Copy link
Member Author

@esigo esigo Sep 2, 2023

Choose a reason for hiding this comment

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

thanks, creating new family only if it doesn't exist already.

Comment on lines 210 to 214
{"B", "bytes"},
{"KB", "kilobytes"},
{"MB", "megabytes"},
{"GB", "gigabytes"},
{"TB", "terabytes"},
Copy link
Contributor

Choose a reason for hiding this comment

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

We've removed B and $ from mappings elsewhere, as B means bel in UCUM. See open-telemetry/opentelemetry-java#5719

Copy link
Member Author

Choose a reason for hiding this comment

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

thanks, removed.

}

// Special case - counter
if (prometheus_type == prometheus_client::MetricType::Counter &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Counters MUST end in _total, so we need to be less tolerant here. We can only skip the _total suffix if the name ends in _total. Since we need unit suffixes to come before type suffixes, one approach would be to trim _total suffixes from the name before appending the unit suffix, and finally append the final _total suffix.

Copy link
Member Author

Choose a reason for hiding this comment

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

thanks, will not add total unless if it has already.

if (prometheus_type == prometheus_client::MetricType::Counter)
{
auto t_pos = sanitized_name.rfind("_total");
bool ends_with_total = t_pos == sanitized_name.size() - 6;
Copy link
Contributor

Choose a reason for hiding this comment

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

Will this work if the metric has a unit? E.g. if I have a metric: foo.bar.total, with unit s, will I get foo_bar_total_seconds_total or foo_bar_seconds_total?

Copy link
Member Author

Choose a reason for hiding this comment

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

@dashpole the output will be foo_bar_total_seconds_total.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ideally, you would trim _total from counters before appending the unit, and then always add _total after the unit for counters.

@punya
Copy link
Member

punya commented Sep 23, 2023

I believe this would also fix #2317.

@marcalff
Copy link
Member

Hi @esigo

Please merge with a recent main to resolve conflicts, so this PR can be reviewed and merged.

Thanks.

@esigo
Copy link
Member Author

esigo commented Oct 19, 2023

Hi @esigo

Please merge with a recent main to resolve conflicts, so this PR can be reviewed and merged.

Thanks.

Hi @marcalff thanks for the reminder. I finish this over the weekend.

@@ -39,7 +39,7 @@ std::vector<prometheus_client::MetricFamily> PrometheusCollector::Collect() cons
reader_->Collect([&result](sdk::metrics::ResourceMetrics &metric_data) {
auto prometheus_metric_data = PrometheusExporterUtils::TranslateToPrometheus(metric_data);
for (auto &data : prometheus_metric_data)
result.emplace_back(data);
result.emplace_back(data.second);
Copy link
Member

Choose a reason for hiding this comment

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

Is it better to use std::move(data.second) here? ::prometheus::MetricFamily may contains a lot of data, and copy these data may have performance problem.

{

// initialize output vector
std::vector<prometheus_client::MetricFamily> output;
std::unordered_map<std::string, prometheus_client::MetricFamily> output;
Copy link
Member

Choose a reason for hiding this comment

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

Can we use output.reserve() first to reduce rehash?

@dashpole
Copy link
Contributor

@esigo Is there any way I can help with this? I would love to get this over the finish line soon.

@esigo
Copy link
Member Author

esigo commented Nov 15, 2023

@esigo Is there any way I can help with this? I would love to get this over the finish line soon.

@dashpole thanks for the reminder. Becasue of the conflict I need to redo the PR. I finish this over the weekend.

Copy link
Contributor

@dashpole dashpole left a comment

Choose a reason for hiding this comment

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

Thanks!

Copy link
Member

@lalitb lalitb left a comment

Choose a reason for hiding this comment

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

Thanks for the fix.

@marcalff marcalff changed the title Prometheus: Add unit to names, convert to word [EXPORTER] Prometheus: Add unit to names, convert to word Nov 22, 2023
@marcalff marcalff merged commit 71d0e50 into open-telemetry:main Nov 22, 2023
45 checks passed
copybara-service bot pushed a commit to grpc/grpc that referenced this pull request Dec 1, 2023
This is mainly to get the fix made in open-telemetry/opentelemetry-cpp#2213
When opentelemetry-cpp makes a stable release with this fix, we'll switch to that.

Closes #35151

COPYBARA_INTEGRATE_REVIEW=#35151 from yashykt:UpdateOTel 1041fbc
PiperOrigin-RevId: 586815878
paulosjca pushed a commit to paulosjca/grpc that referenced this pull request Dec 8, 2023
This is mainly to get the fix made in open-telemetry/opentelemetry-cpp#2213
When opentelemetry-cpp makes a stable release with this fix, we'll switch to that.

Closes grpc#35151

COPYBARA_INTEGRATE_REVIEW=grpc#35151 from yashykt:UpdateOTel 1041fbc
PiperOrigin-RevId: 586815878
Yxang added a commit to Yxang/opentelemetry-cpp that referenced this pull request Sep 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:exporter:prometheus Prometheus Exporter
Projects
None yet
6 participants