diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ecbc24737..de2f099dce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/examples/prometheus/README.md b/examples/prometheus/README.md index 782e874644..d36228a5b7 100644 --- a/examples/prometheus/README.md +++ b/examples/prometheus/README.md @@ -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 exporter{ - new exportermetrics::OStreamMetricExporter}; - -``` - -with - -```cpp -std::unique_ptr exporter{ - new metrics_exporter::PrometheusExporter(opts)}; -``` - OpenTelemetry `PrometheusExporter` will export data via the endpoint defined by `metrics_exporter::PrometheusExporterOptions::url`, @@ -46,8 +27,7 @@ graph LR subgraph SDK MeterProvider - MetricReader[PeriodicExportingMetricReader] - PrometheusExporter["PrometheusExporter
(http://localhost:9464/)"] + MetricReader["PrometheusExporter
(http://localhost:9464/)"] end subgraph API @@ -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 diff --git a/examples/prometheus/main.cc b/examples/prometheus/main.cc index 7a23006b6a..243e58e723 100644 --- a/examples/prometheus/main.cc +++ b/examples/prometheus/main.cc @@ -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 "); diff --git a/exporters/prometheus/src/collector.cc b/exporters/prometheus/src/collector.cc index 77d4255679..29c0bc8db2 100644 --- a/exporters/prometheus/src/collector.cc +++ b/exporters/prometheus/src/collector.cc @@ -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; @@ -27,6 +28,9 @@ std::vector PrometheusCollector::Collect() cons { if (reader_->IsShutdown()) { + OTEL_INTERNAL_LOG_WARN( + "[Prometheus Exporter] Collect: " + "Exporter is shutdown, can not invoke collect operation."); return {}; } collection_lock_.lock(); diff --git a/exporters/prometheus/src/exporter.cc b/exporters/prometheus/src/exporter.cc index 946d84bf91..7691e32f39 100644 --- a/exporters/prometheus/src/exporter.cc +++ b/exporters/prometheus/src/exporter.cc @@ -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 @@ -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(new PrometheusCollector(this)); exposer_->RegisterCollectable(collector_); @@ -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; } diff --git a/sdk/src/logs/logger.cc b/sdk/src/logs/logger.cc index 5fc58cf0ad..190bfe6f5a 100644 --- a/sdk/src/logs/logger.cc +++ b/sdk/src/logs/logger.cc @@ -40,6 +40,9 @@ nostd::unique_ptr Logger::CreateLogRecord() noex } auto recordable = context_->GetProcessor().MakeRecordable(); + + recordable->SetObservedTimestamp(std::chrono::system_clock::now()); + if (include_trace_context_ && opentelemetry::context::RuntimeContext::GetCurrent().HasKey(opentelemetry::trace::kSpanKey)) { diff --git a/sdk/test/logs/logger_sdk_test.cc b/sdk/test/logs/logger_sdk_test.cc index 848d9f19df..5f6467cd91 100644 --- a/sdk/test/logs/logger_sdk_test.cc +++ b/sdk/test/logs/logger_sdk_test.cc @@ -3,6 +3,7 @@ #ifdef ENABLE_LOGS_PREVIEW +# include # include # include "opentelemetry/nostd/string_view.h" @@ -43,7 +44,16 @@ class MockLogRecordable final : public opentelemetry::sdk::logs::Recordable public: void SetTimestamp(opentelemetry::common::SystemTimestamp) noexcept override {} - void SetObservedTimestamp(opentelemetry::common::SystemTimestamp) noexcept override {} + void SetObservedTimestamp( + opentelemetry::common::SystemTimestamp observed_timestamp) noexcept override + { + observed_timestamp_ = observed_timestamp; + } + + const opentelemetry::common::SystemTimestamp &GetObservedTimestamp() const noexcept + { + return observed_timestamp_; + } opentelemetry::logs::Severity GetSeverity() const noexcept { return severity_; } @@ -121,13 +131,14 @@ class MockLogRecordable final : public opentelemetry::sdk::logs::Recordable void CopyFrom(const MockLogRecordable &other) { - severity_ = other.severity_; - body_ = other.body_; - trace_id_ = other.trace_id_; - span_id_ = other.span_id_; - trace_flags_ = other.trace_flags_; - event_name_ = other.event_name_; - event_domain_ = other.event_domain_; + severity_ = other.severity_; + body_ = other.body_; + trace_id_ = other.trace_id_; + span_id_ = other.span_id_; + trace_flags_ = other.trace_flags_; + event_name_ = other.event_name_; + event_domain_ = other.event_domain_; + observed_timestamp_ = other.observed_timestamp_; } private: @@ -138,6 +149,8 @@ class MockLogRecordable final : public opentelemetry::sdk::logs::Recordable opentelemetry::trace::TraceFlags trace_flags_; std::string event_name_; std::string event_domain_; + opentelemetry::common::SystemTimestamp observed_timestamp_ = + std::chrono::system_clock::from_time_t(0); }; class MockProcessor final : public LogRecordProcessor @@ -196,6 +209,8 @@ TEST(LoggerSDK, LogToAProcessor) } opentelemetry::trace::Scope trace_scope{include_span}; + auto now = std::chrono::system_clock::now(); + auto sdk_logger = static_cast(logger.get()); ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetName(), "opentelelemtry_library"); ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetVersion(), ""); @@ -226,6 +241,10 @@ TEST(LoggerSDK, LogToAProcessor) std::string span_id_text_in_span{span_id_in_span, sizeof(span_id_in_span)}; ASSERT_EQ(trace_id_text_in_logger, trace_id_text_in_span); ASSERT_EQ(span_id_text_in_logger, span_id_text_in_span); + + ASSERT_GE( + static_cast(shared_recordable->GetObservedTimestamp()), + now); } TEST(LoggerSDK, EventLog)