Skip to content

Commit

Permalink
Add Prometheus Exporter (#1031)
Browse files Browse the repository at this point in the history
  • Loading branch information
esigo authored Nov 9, 2021
1 parent c3f3042 commit 994c08a
Show file tree
Hide file tree
Showing 10 changed files with 483 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Increment the:

## [Unreleased]

* [EXPORTER] Prometheus Exporter ([#1031](https://github.com/open-telemetry/opentelemetry-cpp/pull/1031))
* [EXPORTER] Add OTLP/HTTP Log Exporter ([#1030](https://github.com/open-telemetry/opentelemetry-cpp/pull/1030))

## [1.0.1] 2021-10-21
Expand Down
18 changes: 18 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,24 @@ if((NOT WITH_API_ONLY)
endif()
endif()

if(WITH_PROMETHEUS)
find_package(prometheus-cpp CONFIG QUIET)
if(NOT prometheus-cpp_FOUND)
message("Trying to use local prometheus-cpp from submodule")
if(EXISTS ${PROJECT_SOURCE_DIR}/third_party/prometheus-cpp/.git)
add_subdirectory(third_party/prometheus-cpp)
else()
message(
FATAL_ERROR
"\nprometheus-cpp package was not found. Please either provide it manually or clone with submodules. "
"To initialize, fetch and checkout any nested submodules, you can use the following command:\n"
"git submodule update --init --recursive")
endif()
else()
message("Using external prometheus-cpp")
endif()
endif()

if(WITH_OTLP)
set(protobuf_MODULE_COMPATIBLE ON)
find_package(Protobuf)
Expand Down
1 change: 0 additions & 1 deletion ci/do_ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ BAZEL_STARTUP_OPTIONS="--output_user_root=$HOME/.cache/bazel"
export CTEST_OUTPUT_ON_FAILURE=1

if [[ "$1" == "cmake.test" ]]; then
install_prometheus_cpp_client
cd "${BUILD_DIR}"
rm -rf *
cmake -DCMAKE_BUILD_TYPE=Debug \
Expand Down
37 changes: 23 additions & 14 deletions exporters/prometheus/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,26 @@
package(default_visibility = ["//visibility:public"])

cc_library(
name = "prometheus_collector",
name = "prometheus_exporter",
srcs = [
"src/prometheus_collector.cc",
"src/prometheus_exporter.cc",
],
hdrs = [
"include/opentelemetry/exporters/prometheus/prometheus_collector.h",
"include/opentelemetry/exporters/prometheus/prometheus_exporter_utils.h",
"include/opentelemetry/exporters/prometheus/prometheus_exporter.h",
],
strip_include_prefix = "include",
deps = [
":prometheus_utils",
":prometheus_collector",
":prometheus_exporter_utils",
"//api",
"//sdk:headers",
"@com_github_jupp0r_prometheus_cpp//core",
"@com_github_jupp0r_prometheus_cpp//pull",
],
)

cc_library(
name = "prometheus_utils",
name = "prometheus_exporter_utils",
srcs = [
"src/prometheus_exporter_utils.cc",
],
Expand All @@ -45,27 +46,35 @@ cc_library(
"//api",
"//sdk:headers",
"@com_github_jupp0r_prometheus_cpp//core",
"@com_github_jupp0r_prometheus_cpp//pull",
],
)

cc_test(
name = "prometheus_collector_test",
cc_library(
name = "prometheus_collector",
srcs = [
"test/prometheus_collector_test.cc",
"src/prometheus_collector.cc",
],
hdrs = [
"include/opentelemetry/exporters/prometheus/prometheus_collector.h",
],
strip_include_prefix = "include",
deps = [
":prometheus_collector",
"@com_google_googletest//:gtest_main",
":prometheus_exporter_utils",
"//api",
"//sdk:headers",
"@com_github_jupp0r_prometheus_cpp//core",
"@com_github_jupp0r_prometheus_cpp//pull",
],
)

cc_test(
name = "prometheus_exporter_utils_test",
name = "prometheus_exporter_test",
srcs = [
"test/prometheus_exporter_utils_test.cc",
"test/prometheus_exporter_test.cc",
],
deps = [
":prometheus_utils",
":prometheus_exporter",
"@com_google_googletest//:gtest_main",
],
)
20 changes: 12 additions & 8 deletions exporters/prometheus/CMakeLists.txt
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,26 @@
# limitations under the License.

include_directories(include)
find_package(prometheus-cpp CONFIG REQUIRED)

add_library(prometheus_exporter_deprecated src/prometheus_collector.cc
src/prometheus_exporter_utils.cc)
if(NOT TARGET prometheus-cpp::core)
find_package(prometheus-cpp CONFIG REQUIRED)
endif()

add_library(
prometheus_exporter_deprecated
src/prometheus_exporter.cc src/prometheus_collector.cc
src/prometheus_exporter_utils.cc)
target_include_directories(
prometheus_exporter_deprecated
PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
"$<INSTALL_INTERFACE:include>")

set(PROMETHEUS_EXPORTER_TARGETS prometheus_exporter_deprecated pull core)
target_link_libraries(
prometheus_exporter_deprecated PUBLIC opentelemetry_metrics_deprecated
prometheus-cpp::core)

prometheus_exporter_deprecated
PUBLIC opentelemetry_metrics_deprecated prometheus-cpp::pull
prometheus-cpp::core)
install(
TARGETS prometheus_exporter_deprecated
TARGETS ${PROMETHEUS_EXPORTER_TARGETS}
EXPORT "${PROJECT_NAME}-target"
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
# include <mutex>
# include <vector>

# include "opentelemetry/exporters/prometheus/prometheus_exporter_utils.h"
# include "opentelemetry/sdk/_metrics/record.h"
# include "prometheus/collectable.h"
# include "prometheus/metric_family.h"
# include "prometheus_exporter_utils.h"

namespace prometheus_client = ::prometheus;
namespace metric_sdk = opentelemetry::sdk::metrics;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#pragma once
#ifdef ENABLE_METRICS_PREVIEW
# include <memory>
# include <string>
# include <vector>

# include "opentelemetry/exporters/prometheus/prometheus_collector.h"
# include "opentelemetry/sdk/_metrics/exporter.h"
# include "opentelemetry/sdk/_metrics/record.h"
# include "opentelemetry/version.h"
# include "prometheus/exposer.h"

/**
* This class is an implementation of the MetricsExporter interface and
* exports Prometheus metrics data. Functions in this class should be
* called by the Controller in our data pipeline.
*/

OPENTELEMETRY_BEGIN_NAMESPACE

namespace exporter
{
namespace prometheus
{
class PrometheusExporter : public sdk::metrics::MetricsExporter
{
public:
/**
* Constructor - binds an exposer and collector to the exporter
* @param address: an address for an exposer that exposes
* an HTTP endpoint for the exporter to connect to
*/
PrometheusExporter(std::string &address);

/**
* Exports a batch of Metric Records.
* @param records: a collection of records to export
* @return: returns a ReturnCode detailing a success, or type of failure
*/
sdk::common::ExportResult Export(
const std::vector<sdk::metrics::Record> &records) noexcept override;

/**
* Shuts down the exporter and does cleanup.
* Since Prometheus is a pull based interface,
* we cannot serve data remaining in the intermediate
* collection to to client an HTTP request being sent,
* so we flush the data.
*/
void Shutdown() noexcept;

/**
* @return: returns a shared_ptr to
* the PrometheusCollector instance
*/
std::shared_ptr<PrometheusCollector> &GetCollector();

/**
* @return: Gets the shutdown status of the exporter
*/
bool IsShutdown() const;

private:
/**
* exporter shutdown status
*/
bool is_shutdown_;

/**
* Pointer to a
* PrometheusCollector instance
*/
std::shared_ptr<PrometheusCollector> collector_;

/**
* Pointer to an
* Exposer instance
*/
std::unique_ptr<::prometheus::Exposer> exposer_;

/**
* friend class for testing
*/
friend class PrometheusExporterTest;

/**
* PrometheusExporter constructor with no parameters
* Used for testing only
*/
PrometheusExporter();
};
} // namespace prometheus
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE
#endif // ENABLE_METRICS_PREVIEW
110 changes: 110 additions & 0 deletions exporters/prometheus/src/prometheus_exporter.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifdef ENABLE_METRICS_PREVIEW
# include "opentelemetry/exporters/prometheus/prometheus_exporter.h"

OPENTELEMETRY_BEGIN_NAMESPACE

namespace exporter
{
namespace prometheus
{
/**
* Constructor - binds an exposer and collector to the exporter
* @param address: an address for an exposer that exposes
* an HTTP endpoint for the exporter to connect to
*/
PrometheusExporter::PrometheusExporter(std::string &address) : is_shutdown_(false)
{
exposer_ = std::unique_ptr<::prometheus::Exposer>(new ::prometheus::Exposer{address});
collector_ = std::shared_ptr<PrometheusCollector>(new PrometheusCollector);

exposer_->RegisterCollectable(collector_);
}

/**
* PrometheusExporter constructor with no parameters
* Used for testing only
*/
PrometheusExporter::PrometheusExporter() : is_shutdown_(false)
{
collector_ = std::unique_ptr<PrometheusCollector>(new PrometheusCollector);
}

/**
* Exports a batch of Metric Records.
* @param records: a collection of records to export
* @return: returns a ReturnCode detailing a success, or type of failure
*/
sdk::common::ExportResult PrometheusExporter::Export(
const std::vector<sdk::metrics::Record> &records) noexcept
{
if (is_shutdown_)
{
return sdk::common::ExportResult::kFailure;
}
else if (records.empty())
{
return sdk::common::ExportResult::kFailureInvalidArgument;
}
else if (collector_->GetCollection().size() + records.size() >
(size_t)collector_->GetMaxCollectionSize())
{
return sdk::common::ExportResult::kFailureFull;
}
else
{
collector_->AddMetricData(records);
return sdk::common::ExportResult::kSuccess;
}
}

/**
* Shuts down the exporter and does cleanup.
* Since Prometheus is a pull based interface,
* we cannot serve data remaining in the intermediate
* collection to to client an HTTP request being sent,
* so we flush the data.
*/
void PrometheusExporter::Shutdown() noexcept
{
is_shutdown_ = true;

collector_->GetCollection().clear();
}

/**
* @return: returns a shared_ptr to
* the PrometheusCollector instance
*/
std::shared_ptr<PrometheusCollector> &PrometheusExporter::GetCollector()
{
return collector_;
}

/**
* @return: Gets the shutdown status of the exporter
*/
bool PrometheusExporter::IsShutdown() const
{
return is_shutdown_;
}

} // namespace prometheus
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE
#endif // ENABLE_METRICS_PREVIEW
3 changes: 2 additions & 1 deletion exporters/prometheus/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
foreach(testname prometheus_collector_test prometheus_exporter_utils_test)
foreach(testname prometheus_exporter_test prometheus_collector_test
prometheus_exporter_utils_test)
add_executable(${testname} "${testname}.cc")
target_link_libraries(
${testname} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}
Expand Down
Loading

0 comments on commit 994c08a

Please sign in to comment.