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

Add Prometheus Exporter: Step 1 #280

Merged
merged 40 commits into from
Aug 26, 2020

Conversation

CunjunWang
Copy link
Contributor

@CunjunWang CunjunWang commented Aug 17, 2020

This PR implements exporter utils helper functions for the Prometheus Exporter project. The C++ file prometheus_exporter_utils.cc implements all the helper functions that will be called when we translate a OpenTelemetry (OTLP) metric to a Prometheus metric.

Changes

  1. Modified the WORKSPACE file and added C++ Prometheus Client as a dependency to the project.
  2. Modified CMakeLists.txt file in exporters folder to add Prometheus Exporter as a sub-project.
  3. Added BUILD file in exporters/prometheus to support building project and the tests with Bazel.
  4. Added CMakeLists.txt file in exporters/prometheus to support building project with CMake.
  5. Added function header definition in exporters/prometheus/include
  6. Implemented the header in exporters/prometheus/src/prometheus_exporter_utils.cc
  7. Tested the implementation with unit tests in exporters/prometheus/test/prometheus_exporter_utils_test.cc
  8. Added CMakeLists.txt file in exporters/prometheus/test to support building tests with CMake.
  9. Modified ci/setup_cmake.sh to configure Prometheus C++ client as a dependency
  10. Modified .github/workflows/ci.yml to execute Prometheus Exporter test sub-job
  11. Modified ci/do_ci.sh to add Prometheus Exporter test setup scripts, and ignore Prometheus tests in bazel.noexcept

@CunjunWang
Copy link
Contributor Author

For the CI, we actually need to have prometheus-cpp library installed in the CI environment because it's a project dependency

@codecov
Copy link

codecov bot commented Aug 18, 2020

Codecov Report

Merging #280 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #280   +/-   ##
=======================================
  Coverage   94.55%   94.55%           
=======================================
  Files         146      146           
  Lines        6610     6610           
=======================================
  Hits         6250     6250           
  Misses        360      360           

@reyang
Copy link
Member

reyang commented Aug 21, 2020

For the CI, we actually need to have prometheus-cpp library installed in the CI environment because it's a project dependency

Could you add a GitHub Actions to cover that? You can potentially leverage a linux container and install the dependency you need for testing. Here goes and example of how to do that https://github.com/open-telemetry/opentelemetry-dotnet/tree/master/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests.

WORKSPACE Outdated

http_archive(
name = "com_github_jupp0r_prometheus_cpp",
strip_prefix = "prometheus-cpp-master",
Copy link
Contributor

Choose a reason for hiding this comment

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

Please pin to a version (and add sha256), for consistency with other deps.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

pin to v0.9.0, and sha256 added

#include "opentelemetry/sdk/metrics/record.h"
#include "prometheus/metric_family.h"

namespace prometheus_client = ::prometheus;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a way to limit the scope of these? I'm worried about having them in a header file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed it from header, and put it in implementation files

* @return a collection of translated metrics that is acceptable by Prometheus
*/
std::vector<prometheus_client::MetricFamily> PrometheusExporterUtils::TranslateToPrometheus(
std::vector<metric_sdk::Record> &records)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can records be a constref?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

changed to a constref

/**
* Set value to metric family according to record
*/
void PrometheusExporterUtils::SetMetricFamily(metric_sdk::Record &record,
Copy link
Contributor

Choose a reason for hiding this comment

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

Can record be a constref?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I make record a constref here, I need to change all getter functions in Record class const functions. Record class was implemented by previous interns, and also used in other classes.

if (origin_name != sanitized)
{
std::cout << "Sanitized metric name \"" << origin_name << "\" to \"" << sanitized << "\""
<< std::endl;
Copy link
Contributor

Choose a reason for hiding this comment

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

Please use \n over endl.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

std::chrono::nanoseconds time,
const std::string &labels)
{
metric.timestamp_ms = time.count() / 1000;
Copy link
Contributor

Choose a reason for hiding this comment

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

milliseconds = nanoseconds / 1000?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed. thanks

if (origin_name != sanitized)
{
std::cout << "Sanitized label name \"" << origin_name << "\" to \"" << sanitized << "\""
<< std::endl;
Copy link
Contributor

Choose a reason for hiding this comment

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

\n

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

# apt-get install zlib1g-dev
# apt-get -y install libcurl4-openssl-dev
cd third_party
git clone https://github.com/jupp0r/prometheus-cpp
Copy link
Member

Choose a reason for hiding this comment

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

Consider extract this logic to a separate file under the Prometheus exporter folder.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, correct me if I misunderstand something:

  1. keep the elif [[ "$1" == "cmake.exporter.prometheus.test" ]]; block here
  2. move the scripts of installing the Prometheus client (from cd third_party to sudo make install) to a separate script in exporters/prometheus. For example, exporters/prometheus/install_prometheus_client.sh
  3. run install_prometheus_client.sh here

@@ -83,8 +110,8 @@ elif [[ "$1" == "bazel.legacy.test" ]]; then
bazel test $BAZEL_TEST_OPTIONS -- //... -//exporters/otlp/...
exit 0
elif [[ "$1" == "bazel.noexcept" ]]; then
bazel build --copt=-fno-exceptions $BAZEL_OPTIONS //...
bazel test --copt=-fno-exceptions $BAZEL_TEST_OPTIONS //...
bazel build --copt=-fno-exceptions $BAZEL_OPTIONS -- //... -//exporters/prometheus/...
Copy link
Member

Choose a reason for hiding this comment

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

Why would we want to take exception here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When we run the test, we found some error handling and exceptions from the Prometheus client, which made this test always fail. We discussed this problem with Johannes last week, and he suggested us to consider excluding the Prometheus component in the noexcept test.

Copy link
Member

Choose a reason for hiding this comment

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

Please add a comment here.

auto sanitized = SanitizeNames(origin_name);
if (origin_name != sanitized)
{
std::cout << "Sanitized metric name \"" << origin_name << "\" to \"" << sanitized << "\"\n";
Copy link
Member

Choose a reason for hiding this comment

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

Is this intended or just for development/debugging purpose?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We added this printing in order to tell the user we have changed their metrics name or label names. We know this is not in the specification, and we can remove this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed.

auto sanitized = SanitizeNames(origin_name);
if (origin_name != sanitized)
{
std::cout << "Sanitized label name \"" << origin_name << "\" to \"" << sanitized << "\"\n";
Copy link
Member

Choose a reason for hiding this comment

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

Same here, need to understand if we intend to keep the cout lines.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed.

Copy link
Member

@reyang reyang left a comment

Choose a reason for hiding this comment

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

LGTM.

@reyang reyang added the pr:please-merge This PR is ready to be merged by a Maintainer (rebased, CI passed, has enough valid approvals, etc.) label Aug 25, 2020
@reyang reyang merged commit e0a93fd into open-telemetry:master Aug 26, 2020
@lalitb lalitb mentioned this pull request Mar 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr:please-merge This PR is ready to be merged by a Maintainer (rebased, CI passed, has enough valid approvals, etc.)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants