blob: 33c0788988742ff65920e01d20e8f61e2ab64f0b [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
#include <memory>
#include <vector>
#include <algorithm>
#include "unit/Catch.h"
#include "PrometheusMetricsPublisher.h"
#include "properties/Configure.h"
#include "MetricsExposer.h"
#include "core/state/nodes/ResponseNodeLoader.h"
#include "core/RepositoryFactory.h"
#include "range/v3/algorithm/find_if.hpp"
#include "range/v3/algorithm/contains.hpp"
namespace org::apache::nifi::minifi::extensions::prometheus::test {
class DummyMetricsExposer : public MetricsExposer {
public:
void registerMetric(const std::shared_ptr<PublishedMetricGaugeCollection>& metrics) override {
metrics_ = metrics;
}
void removeMetric(const std::shared_ptr<PublishedMetricGaugeCollection>&) override {
}
[[nodiscard]] std::shared_ptr<PublishedMetricGaugeCollection> getMetrics() const {
return metrics_;
}
private:
std::shared_ptr<PublishedMetricGaugeCollection> metrics_;
};
class PrometheusPublisherTestFixture {
public:
explicit PrometheusPublisherTestFixture(bool user_dummy_exposer)
: configuration_(std::make_shared<ConfigureImpl>()),
provenance_repo_(core::createRepository("provenancerepository")),
flow_file_repo_(core::createRepository("flowfilerepository")),
content_repo_(core::createContentRepository("volatilecontentrepository")),
response_node_loader_(std::make_shared<state::response::ResponseNodeLoaderImpl>(configuration_,
std::vector<std::shared_ptr<core::RepositoryMetricsSource>>{provenance_repo_, flow_file_repo_, content_repo_}, nullptr)) {
std::unique_ptr<DummyMetricsExposer> dummy_exposer;
if (user_dummy_exposer) {
dummy_exposer = std::make_unique<DummyMetricsExposer>();
exposer_ = dummy_exposer.get();
}
publisher_ = std::make_unique<PrometheusMetricsPublisher>("publisher", utils::Identifier(), std::move(dummy_exposer));
}
protected:
std::shared_ptr<Configure> configuration_;
std::shared_ptr<core::RepositoryMetricsSource> provenance_repo_;
std::shared_ptr<core::RepositoryMetricsSource> flow_file_repo_;
std::shared_ptr<core::RepositoryMetricsSource> content_repo_;
std::shared_ptr<state::response::ResponseNodeLoader> response_node_loader_;
std::unique_ptr<PrometheusMetricsPublisher> publisher_;
DummyMetricsExposer* exposer_ = nullptr;
};
class PrometheusPublisherTestFixtureWithRealExposer : public PrometheusPublisherTestFixture {
public:
PrometheusPublisherTestFixtureWithRealExposer() : PrometheusPublisherTestFixture(false) {}
};
class PrometheusPublisherTestFixtureWithDummyExposer : public PrometheusPublisherTestFixture {
public:
PrometheusPublisherTestFixtureWithDummyExposer() : PrometheusPublisherTestFixture(true) {}
};
TEST_CASE_METHOD(PrometheusPublisherTestFixtureWithRealExposer, "Test prometheus empty port", "[prometheusPublisherTest]") {
REQUIRE_THROWS_WITH(publisher_->initialize(configuration_, response_node_loader_), "General Operation: Port not configured for Prometheus metrics publisher!");
}
TEST_CASE_METHOD(PrometheusPublisherTestFixtureWithRealExposer, "Test prometheus invalid port", "[prometheusPublisherTest]") {
configuration_->set(Configure::nifi_metrics_publisher_prometheus_metrics_publisher_port, "invalid");
REQUIRE_THROWS_AS(publisher_->initialize(configuration_, response_node_loader_), std::exception);
}
TEST_CASE_METHOD(PrometheusPublisherTestFixtureWithDummyExposer, "Test adding metrics to exposer", "[prometheusPublisherTest]") {
SECTION("Define metrics in general metrics property") {
configuration_->set(Configure::nifi_metrics_publisher_metrics, "QueueMetrics,RepositoryMetrics,DeviceInfoNode,FlowInformation,AgentInformation,InvalidMetrics,GetFileMetrics,GetTCPMetrics");
}
SECTION("Define metrics in publisher specific metrics property") {
configuration_->set(Configure::nifi_metrics_publisher_prometheus_metrics_publisher_metrics,
"QueueMetrics,RepositoryMetrics,DeviceInfoNode,FlowInformation,AgentInformation,InvalidMetrics,GetFileMetrics,GetTCPMetrics");
}
SECTION("Publisher specific metrics property should be prioritized") {
configuration_->set(Configure::nifi_metrics_publisher_prometheus_metrics_publisher_metrics,
"QueueMetrics,RepositoryMetrics,DeviceInfoNode,FlowInformation,AgentInformation,InvalidMetrics,GetFileMetrics,GetTCPMetrics");
configuration_->set(Configure::nifi_metrics_publisher_metrics, "QueueMetrics");
}
SECTION("Empty metrics property should be ignored") {
configuration_->set(Configure::nifi_metrics_publisher_metrics, "QueueMetrics,RepositoryMetrics,DeviceInfoNode,FlowInformation,AgentInformation,InvalidMetrics,GetFileMetrics,GetTCPMetrics");
configuration_->set(Configure::nifi_metrics_publisher_prometheus_metrics_publisher_metrics, "");
}
configuration_->set(Configure::nifi_metrics_publisher_agent_identifier, "AgentId-1");
publisher_->initialize(configuration_, response_node_loader_);
publisher_->loadMetricNodes();
auto stored_metrics = exposer_->getMetrics();
std::vector<std::string> valid_metrics_without_flow = {"QueueMetrics", "RepositoryMetrics", "DeviceInfoNode", "FlowInformation", "AgentInformation"};
REQUIRE(stored_metrics);
auto collection = stored_metrics->Collect();
for (const auto& metric_family : collection) {
for (const auto& prometheus_metric : metric_family.metric) {
auto metric_class_label_it = ranges::find_if(prometheus_metric.label, [](const auto& label) { return label.name == "metric_class"; });
REQUIRE(metric_class_label_it != ranges::end(prometheus_metric.label));
REQUIRE(ranges::contains(valid_metrics_without_flow, metric_class_label_it->value));
auto agent_identifier_label_it = ranges::find_if(prometheus_metric.label, [](const auto& label) { return label.name == "agent_identifier"; });
REQUIRE(agent_identifier_label_it != ranges::end(prometheus_metric.label));
REQUIRE(agent_identifier_label_it->value == "AgentId-1");
}
}
}
} // namespace org::apache::nifi::minifi::extensions::prometheus::test