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

Fix Prometheus server crash on listening to already used port #1986

Merged
merged 12 commits into from
Feb 16, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Increment the:
* [CI] Enforce copyright check in CI [#1965](https://github.com/open-telemetry/opentelemetry-cpp/pull/1965)
* [SEMANTIC CONVENTIONS] Upgrade to version 1.18.0
[#1974](https://github.com/open-telemetry/opentelemetry-cpp/pull/1974)
* Fix Prometheus server crash on listening to already used port [#1986](https://github.com/open-telemetry/opentelemetry-cpp/pull/1986)

## [1.8.2] 2023-01-31

Expand Down
24 changes: 2 additions & 22 deletions examples/prometheus/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,12 @@

## Export metrics from the application

It is highly recommended to go over the [ostream-metrics](../metrics_simple/README.md)
doc before following along this document.

Run the application with:

```sh
bazel run //examples/prometheus:prometheus_example
```

The main difference between the [ostream-metrics](../metrics_simple/README.md)
example with this one is that the line below is replaced:

```cpp
std::unique_ptr<metric_sdk::PushMetricExporter> exporter{
new exportermetrics::OStreamMetricExporter};

```

with

```cpp
std::unique_ptr<metrics_sdk::PushMetricExporter> exporter{
new metrics_exporter::PrometheusExporter(opts)};
```

OpenTelemetry `PrometheusExporter` will export
data via the endpoint defined by
`metrics_exporter::PrometheusExporterOptions::url`,
Expand All @@ -46,8 +27,7 @@ graph LR

subgraph SDK
MeterProvider
MetricReader[PeriodicExportingMetricReader]
PrometheusExporter["PrometheusExporter<br/>(http://localhost:9464/)"]
MetricReader["PrometheusExporter<br/>(http://localhost:9464/)"]
end

subgraph API
Expand All @@ -56,7 +36,7 @@ end

Instrument --> | Measurements | MeterProvider

MeterProvider --> | Metrics | MetricReader --> | Pull | PrometheusExporter
MeterProvider --> | Metrics | MetricReader
```

Also, for our learning purpose, we use a while-loop to keep recoring random
Expand Down
2 changes: 1 addition & 1 deletion examples/prometheus/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ void CleanupMetrics()
int main(int argc, char **argv)
{
std::string example_type;
std::string addr{"localhost:8080"};
std::string addr{"localhost:9464"};
if (argc == 1)
{
std::puts("usage: $prometheus_example <example type> <url>");
Expand Down
4 changes: 4 additions & 0 deletions exporters/prometheus/src/collector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

#include "opentelemetry/exporters/prometheus/collector.h"
#include "opentelemetry/sdk/common/global_log_handler.h"

namespace metric_sdk = opentelemetry::sdk::metrics;

Expand All @@ -27,6 +28,9 @@ std::vector<prometheus_client::MetricFamily> PrometheusCollector::Collect() cons
{
if (reader_->IsShutdown())
{
OTEL_INTERNAL_LOG_WARN(
"[Prometheus Exporter] Collect: "
"Exporter is shutdown, cann't invoke collect operation.");
lalitb marked this conversation as resolved.
Show resolved Hide resolved
return {};
}
collection_lock_.lock();
Expand Down
18 changes: 16 additions & 2 deletions exporters/prometheus/src/exporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

#include "opentelemetry/exporters/prometheus/exporter.h"
#include "opentelemetry/sdk/common/global_log_handler.h"

OPENTELEMETRY_BEGIN_NAMESPACE

Expand All @@ -16,7 +17,19 @@ namespace metrics
*/
PrometheusExporter::PrometheusExporter(const PrometheusExporterOptions &options) : options_(options)
{
exposer_ = std::unique_ptr<::prometheus::Exposer>(new ::prometheus::Exposer{options_.url});
try
{
exposer_ = std::unique_ptr<::prometheus::Exposer>(new ::prometheus::Exposer{options_.url});
}
catch (const std::exception &ex)
{
exposer_.reset(nullptr);
OTEL_INTERNAL_LOG_ERROR("[Prometheus Exporter] "
<< "Can't initialize prometheus exposer with endpoint: " << options_.url
<< "\nError: " << ex.what());
Shutdown(); // set MetricReader in shutdown state.
return;
}
collector_ = std::shared_ptr<PrometheusCollector>(new PrometheusCollector(this));

exposer_->RegisterCollectable(collector_);
Expand All @@ -36,7 +49,8 @@ bool PrometheusExporter::OnForceFlush(std::chrono::microseconds /* timeout */) n

bool PrometheusExporter::OnShutDown(std::chrono::microseconds /* timeout */) noexcept
{
exposer_->RemoveCollectable(collector_);
if (exposer_ != nullptr)
exposer_->RemoveCollectable(collector_);
return true;
}

Expand Down
5 changes: 3 additions & 2 deletions exporters/prometheus/test/exporter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ using opentelemetry::sdk::metrics::InstrumentType;
TEST(PrometheusExporter, InitializeConstructorIsNotShutdown)
{
PrometheusExporterOptions options;
options.url = "localhost:8081";
options.url = "localhost:8084";
PrometheusExporter exporter(options);
// // Asserts that the exporter is not shutdown.
// ASSERT_TRUE(!exporter.IsShutdown());
ASSERT_TRUE(exporter.IsShutdown());
exporter.Shutdown();
ASSERT_TRUE(exporter.IsShutdown());
}

/**
Expand Down