This is an automated email from the ASF dual-hosted git repository.

szaszm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git

commit 77a6c3519be5b62038595e08d909a5836618f9af
Author: Gabor Gyimesi <[email protected]>
AuthorDate: Thu Sep 22 15:44:12 2022 +0200

    MINIFICPP-1901 Add agent identity to Prometheus metrics
    
    Closes #1385
    Signed-off-by: Marton Szasz <[email protected]>
---
 METRICS.md                                         | 84 ++++++++++++----------
 conf/minifi.properties                             |  1 +
 .../integration/minifi/core/DockerTestCluster.py   |  1 +
 docker/test/integration/minifi/core/ImageStore.py  |  1 +
 encrypt-config/tests/ConfigFileEncryptorTests.cpp  |  2 +-
 encrypt-config/tests/ConfigFileTests.cpp           |  8 +--
 encrypt-config/tests/resources/minifi.properties   |  1 +
 ...th-additional-sensitive-props.minifi.properties |  1 +
 .../prometheus/PrometheusMetricsPublisher.cpp      | 15 +++-
 extensions/prometheus/PrometheusMetricsPublisher.h |  2 +
 .../prometheus/PublishedMetricGaugeCollection.cpp  |  5 +-
 .../prometheus/PublishedMetricGaugeCollection.h    |  4 +-
 .../tests/PrometheusMetricsPublisherTest.cpp       | 15 ++--
 libminifi/include/properties/Configuration.h       |  1 +
 libminifi/include/utils/OsUtils.h                  | 22 ++----
 libminifi/src/Configuration.cpp                    |  1 +
 libminifi/src/utils/OsUtils.cpp                    | 20 +++---
 .../test/resources/encrypted.minifi.properties     |  1 +
 18 files changed, 105 insertions(+), 80 deletions(-)

diff --git a/METRICS.md b/METRICS.md
index b53465a28..fa4b4c7b5 100644
--- a/METRICS.md
+++ b/METRICS.md
@@ -46,32 +46,46 @@ To use the publisher a port should also be configured where 
the metrics will be
 
        nifi.metrics.publisher.PrometheusMetricsPublisher.port=9936
 
-The last option defines which metric classes should be exposed through the 
metrics publisher in configured with a comma separated value:
+The following option defines which metric classes should be exposed through 
the metrics publisher in configured with a comma separated value:
 
        # in minifi.properties
 
        
nifi.metrics.publisher.metrics=QueueMetrics,RepositoryMetrics,GetFileMetrics,DeviceInfoNode,FlowInformation
 
+An agent identifier should also be defined to identify which agent the metric 
is exposed from. If not set, the hostname is used as the identifier.
+
+       # in minifi.properties
+
+       nifi.metrics.publisher.agent.identifier=Agent1
+
 ## Metrics
 
 The following section defines the currently available metrics to be published 
by the MiNiFi C++ agent.
 
 NOTE: In Prometheus all metrics are extended with a `minifi_` prefix to mark 
the domain of the metric. For example the `connection_name` metric is published 
as `minifi_connection_name` in Prometheus.
 
+### Generic labels
+
+The following labels are set for every single metric and are not listed 
separately in the labels of the metrics below.
+
+| Label                    | Description                                       
                                                                                
      |
+|--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|
+| metric_class             | Class name to filter for this metric, set to the 
name of the metric e.g. QueueMetrics, GetFileMetrics                            
       |
+| agent_identifier         | Set to the identifier set in minifi.properties in 
the nifi.metrics.publisher.agent.identifier property. If not set the hostname 
is used |
+
 ### QueueMetrics
 
 QueueMetrics is a system level metric that reports queue metrics for every 
connection in the flow.
 
-| Metric name          | Labels                                         | 
Description                                |
-|----------------------|------------------------------------------------|--------------------------------------------|
-| queue_data_size      | metric_class, connection_uuid, connection_name | 
Current queue data size                    |
-| queue_data_size_max  | metric_class, connection_uuid, connection_name | Max 
queue data size to apply back pressure |
-| queue_size           | metric_class, connection_uuid, connection_name | 
Current queue size                         |
-| queue_size_max       | metric_class, connection_uuid, connection_name | Max 
queue size to apply back pressure      |
+| Metric name          | Labels                           | Description        
                        |
+|----------------------|----------------------------------|--------------------------------------------|
+| queue_data_size      | connection_uuid, connection_name | Current queue data 
size                    |
+| queue_data_size_max  | connection_uuid, connection_name | Max queue data 
size to apply back pressure |
+| queue_size           | connection_uuid, connection_name | Current queue size 
                        |
+| queue_size_max       | connection_uuid, connection_name | Max queue size to 
apply back pressure      |
 
 | Label                    | Description                                       
         |
 
|--------------------------|------------------------------------------------------------|
-| metric_class             | Class name to filter for this metric, set to 
QueueMetrics  |
 | connection_uuid          | UUID of the connection defined in the flow 
configuration   |
 | connection_name          | Name of the connection defined in the flow 
configuration   |
 
@@ -79,30 +93,28 @@ QueueMetrics is a system level metric that reports queue 
metrics for every conne
 
 RepositoryMetrics is a system level metric that reports metrics for the 
registered repositories (by default flowfile and provenance repository)
 
-| Metric name          | Labels                        | Description           
                |
-|----------------------|-------------------------------|---------------------------------------|
-| is_running           | metric_class, repository_name | Is the repository 
running (1 or 0)    |
-| is_full              | metric_class, repository_name | Is the repository 
full (1 or 0)       |
-| repository_size      | metric_class, repository_name | Current size of the 
repository        |
+| Metric name          | Labels          | Description                         
  |
+|----------------------|-----------------|---------------------------------------|
+| is_running           | repository_name | Is the repository running (1 or 0)  
  |
+| is_full              | repository_name | Is the repository full (1 or 0)     
  |
+| repository_size      | repository_name | Current size of the repository      
  |
 
 | Label                    | Description                                       
              |
 
|--------------------------|-----------------------------------------------------------------|
-| metric_class             | Class name to filter for this metric, set to 
RepositoryMetrics  |
 | repository_name          | Name of the reported repository                   
              |
 
 ### GetFileMetrics
 
 Processor level metric that reports metrics for the GetFile processor if 
defined in the flow configuration
 
-| Metric name           | Labels                                       | 
Description                                    |
-|-----------------------|----------------------------------------------|------------------------------------------------|
-| onTrigger_invocations | metric_class, processor_name, processor_uuid | 
Number of times the processor was triggered    |
-| accepted_files        | metric_class, processor_name, processor_uuid | 
Number of files that matched the set criterias |
-| input_bytes           | metric_class, processor_name, processor_uuid | Sum 
of file sizes processed                    |
+| Metric name           | Labels                         | Description         
                           |
+|-----------------------|--------------------------------|------------------------------------------------|
+| onTrigger_invocations | processor_name, processor_uuid | Number of times the 
processor was triggered    |
+| accepted_files        | processor_name, processor_uuid | Number of files 
that matched the set criterias |
+| input_bytes           | processor_name, processor_uuid | Sum of file sizes 
processed                    |
 
 | Label          | Description                                                 
   |
 
|----------------|----------------------------------------------------------------|
-| metric_class   | Class name to filter for this metric, set to GetFileMetrics 
   |
 | processor_name | Name of the processor                                       
   |
 | processor_uuid | UUID of the processor                                       
   |
 
@@ -110,13 +122,12 @@ Processor level metric that reports metrics for the 
GetFile processor if defined
 
 Processor level metric that reports metrics for the GetTCPMetrics processor if 
defined in the flow configuration
 
-| Metric name           | Labels                                       | 
Description                                    |
-|-----------------------|----------------------------------------------|------------------------------------------------|
-| onTrigger_invocations | metric_class, processor_name, processor_uuid | 
Number of times the processor was triggered    |
+| Metric name           | Labels                         | Description         
                           |
+|-----------------------|--------------------------------|------------------------------------------------|
+| onTrigger_invocations | processor_name, processor_uuid | Number of times the 
processor was triggered    |
 
 | Label          | Description                                                 
   |
 
|----------------|----------------------------------------------------------------|
-| metric_class   | Class name to filter for this metric, set to GetTCPMetrics  
   |
 | processor_name | Name of the processor                                       
   |
 | processor_uuid | UUID of the processor                                       
   |
 
@@ -126,29 +137,24 @@ DeviceInfoNode is a system level metric that reports 
metrics about the system re
 
 | Metric name     | Labels       | Description               |
 |-----------------|--------------|---------------------------|
-| physical_mem    | metric_class | Physical memory available |
-| memory_usage    | metric_class | Memory used by the agent  |
-| cpu_utilization | metric_class | CPU utilized by the agent |
-
-| Label          | Description                                                 
|
-|----------------|-------------------------------------------------------------|
-| metric_class   | Class name to filter for this metric, set to DeviceInfoNode 
|
+| physical_mem    | -            | Physical memory available |
+| memory_usage    | -            | Memory used by the agent  |
+| cpu_utilization | -            | CPU utilized by the agent |
 
 ### FlowInformation
 
 DeviceInfoNode is a system level metric that reports metrics about the system 
resources used and available
 
-| Metric name          | Labels                                         | 
Description                                |
-|----------------------|------------------------------------------------|--------------------------------------------|
-| queue_data_size      | metric_class, connection_uuid, connection_name | 
Current queue data size                    |
-| queue_data_size_max  | metric_class, connection_uuid, connection_name | Max 
queue data size to apply back pressure |
-| queue_size           | metric_class, connection_uuid, connection_name | 
Current queue size                         |
-| queue_size_max       | metric_class, connection_uuid, connection_name | Max 
queue size to apply back pressure      |
-| is_running           | metric_class, component_uuid, component_name   | 
Check if the component is running (1 or 0) |
+| Metric name          | Labels                           | Description        
                        |
+|----------------------|----------------------------------|--------------------------------------------|
+| queue_data_size      | connection_uuid, connection_name | Current queue data 
size                    |
+| queue_data_size_max  | connection_uuid, connection_name | Max queue data 
size to apply back pressure |
+| queue_size           | connection_uuid, connection_name | Current queue size 
                        |
+| queue_size_max       | connection_uuid, connection_name | Max queue size to 
apply back pressure      |
+| is_running           | component_uuid, component_name   | Check if the 
component is running (1 or 0) |
 
 | Label           | Description                                                
  |
 
|-----------------|--------------------------------------------------------------|
-| metric_class    | Class name to filter for this metric, set to 
FlowInformation |
 | connection_uuid | UUID of the connection defined in the flow configuration   
  |
 | connection_name | Name of the connection defined in the flow configuration   
  |
 | component_uuid  | UUID of the component                                      
  |
diff --git a/conf/minifi.properties b/conf/minifi.properties
index 0dbf918a9..18190c096 100644
--- a/conf/minifi.properties
+++ b/conf/minifi.properties
@@ -123,6 +123,7 @@ nifi.jvm.options=-Xmx1G
 nifi.python.processor.dir=${MINIFI_HOME}/minifi-python/
 
 # Publish metrics to external consumers
+# nifi.metrics.publisher.agent.identifier=
 # nifi.metrics.publisher.class=PrometheusMetricsPublisher
 # nifi.metrics.publisher.PrometheusMetricsPublisher.port=9936
 # 
nifi.metrics.publisher.metrics=QueueMetrics,RepositoryMetrics,GetFileMetrics,DeviceInfoNode,FlowInformation
diff --git a/docker/test/integration/minifi/core/DockerTestCluster.py 
b/docker/test/integration/minifi/core/DockerTestCluster.py
index 7aba844a7..51fa9fd30 100644
--- a/docker/test/integration/minifi/core/DockerTestCluster.py
+++ b/docker/test/integration/minifi/core/DockerTestCluster.py
@@ -387,4 +387,5 @@ class DockerTestCluster(SingleNodeDockerCluster):
 
     def verify_metric_exists(self, prometheus_client, metric_name, 
metric_class, labels={}):
         labels['metric_class'] = metric_class
+        labels['agent_identifier'] = "Agent1"
         return 
len(prometheus_client.get_current_metric_value(metric_name=metric_name, 
label_config=labels)) > 0
diff --git a/docker/test/integration/minifi/core/ImageStore.py 
b/docker/test/integration/minifi/core/ImageStore.py
index d5ec680cc..23d46afaa 100644
--- a/docker/test/integration/minifi/core/ImageStore.py
+++ b/docker/test/integration/minifi/core/ImageStore.py
@@ -102,6 +102,7 @@ class ImageStore:
                     echo "Database = postgres" >> /etc/odbc.ini
                 RUN sed -i -e 's/INFO/DEBUG/g' 
{minifi_root}/conf/minifi-log.properties
                 RUN echo nifi.flow.engine.threads=5 >> 
{minifi_root}/conf/minifi.properties
+                RUN echo nifi.metrics.publisher.agent.identifier=Agent1 >> 
{minifi_root}/conf/minifi.properties
                 RUN echo 
nifi.metrics.publisher.class=PrometheusMetricsPublisher >> 
{minifi_root}/conf/minifi.properties
                 RUN echo 
nifi.metrics.publisher.PrometheusMetricsPublisher.port=9936 >> 
{minifi_root}/conf/minifi.properties
                 RUN echo 
nifi.metrics.publisher.metrics=RepositoryMetrics,QueueMetrics,GetFileMetrics,GetTCPMetrics,FlowInformation,DeviceInfoNode
 >> {minifi_root}/conf/minifi.properties
diff --git a/encrypt-config/tests/ConfigFileEncryptorTests.cpp 
b/encrypt-config/tests/ConfigFileEncryptorTests.cpp
index c9aa62cd2..f4a0b3d93 100644
--- a/encrypt-config/tests/ConfigFileEncryptorTests.cpp
+++ b/encrypt-config/tests/ConfigFileEncryptorTests.cpp
@@ -77,7 +77,7 @@ TEST_CASE("ConfigFileEncryptor can encrypt the sensitive 
properties", "[encrypt-
     uint32_t num_properties_encrypted = 
encryptSensitivePropertiesInFile(test_file, KEY);
 
     REQUIRE(num_properties_encrypted == 1);
-    REQUIRE(test_file.size() == 106);
+    REQUIRE(test_file.size() == 107);
     REQUIRE(check_encryption(test_file, Configuration::nifi_rest_api_password, 
original_password.length()));
 
     SECTION("calling encryptSensitiveProperties a second time does nothing") {
diff --git a/encrypt-config/tests/ConfigFileTests.cpp 
b/encrypt-config/tests/ConfigFileTests.cpp
index b8b24ccc0..e187b7edc 100644
--- a/encrypt-config/tests/ConfigFileTests.cpp
+++ b/encrypt-config/tests/ConfigFileTests.cpp
@@ -90,7 +90,7 @@ TEST_CASE("ConfigFile creates an empty object from a 
nonexistent file", "[encryp
 
 TEST_CASE("ConfigFile can parse a simple config file", 
"[encrypt-config][constructor]") {
   ConfigFile test_file{std::ifstream{"resources/minifi.properties"}};
-  REQUIRE(test_file.size() == 105);
+  REQUIRE(test_file.size() == 106);
 }
 
 TEST_CASE("ConfigFile can test whether a key is present", 
"[encrypt-config][hasValue]") {
@@ -102,7 +102,7 @@ TEST_CASE("ConfigFile can test whether a key is present", 
"[encrypt-config][hasV
 
 TEST_CASE("ConfigFile can read empty properties correctly", 
"[encrypt-config][constructor]") {
   ConfigFile 
test_file{std::ifstream{"resources/with-additional-sensitive-props.minifi.properties"}};
-  REQUIRE(test_file.size() == 107);
+  REQUIRE(test_file.size() == 108);
 
   auto empty_property = 
test_file.getValue(Configuration::nifi_security_need_ClientAuth);
   REQUIRE(empty_property);
@@ -143,7 +143,7 @@ TEST_CASE("ConfigFile can add a new setting after an 
existing setting", "[encryp
 
   SECTION("valid key") {
     test_file.insertAfter(Configuration::nifi_rest_api_password, 
"nifi.rest.api.password.protected", "my-cipher-name");
-    REQUIRE(test_file.size() == 106);
+    REQUIRE(test_file.size() == 107);
     REQUIRE(test_file.getValue("nifi.rest.api.password.protected") == 
"my-cipher-name");
   }
 
@@ -158,7 +158,7 @@ TEST_CASE("ConfigFile can add a new setting at the end", 
"[encrypt-config][appen
   const std::string KEY = "nifi.bootstrap.sensitive.key";
   const std::string VALUE = 
"aa411f289c91685ef9d5a9e5a4fad9393ff4c7a78ab978484323488caed7a9ab";
   test_file.append(KEY, VALUE);
-  REQUIRE(test_file.size() == 106);
+  REQUIRE(test_file.size() == 107);
   REQUIRE(test_file.getValue(KEY) == std::make_optional(VALUE));
 }
 
diff --git a/encrypt-config/tests/resources/minifi.properties 
b/encrypt-config/tests/resources/minifi.properties
index 7d1c73b01..ae12394b7 100644
--- a/encrypt-config/tests/resources/minifi.properties
+++ b/encrypt-config/tests/resources/minifi.properties
@@ -100,6 +100,7 @@ nifi.c2.flow.id=
 nifi.c2.flow.url=
 
 # Publish metrics to external consumers
+# nifi.metrics.publisher.agent.identifier=
 # nifi.metrics.publisher.class=PrometheusMetricsPublisher
 # nifi.metrics.publisher.PrometheusMetricsPublisher.port=9936
 # 
nifi.metrics.publisher.metrics=QueueMetrics,RepositoryMetrics,GetFileMetrics,DeviceInfoNode,FlowInformation
diff --git 
a/encrypt-config/tests/resources/with-additional-sensitive-props.minifi.properties
 
b/encrypt-config/tests/resources/with-additional-sensitive-props.minifi.properties
index b3c7d8559..551029af2 100644
--- 
a/encrypt-config/tests/resources/with-additional-sensitive-props.minifi.properties
+++ 
b/encrypt-config/tests/resources/with-additional-sensitive-props.minifi.properties
@@ -102,6 +102,7 @@ nifi.c2.flow.id=
 nifi.c2.flow.url=
 
 # Publish metrics to external consumers
+# nifi.metrics.publisher.agent.identifier=
 # nifi.metrics.publisher.class=PrometheusMetricsPublisher
 # nifi.metrics.publisher.PrometheusMetricsPublisher.port=9936
 # 
nifi.metrics.publisher.metrics=QueueMetrics,RepositoryMetrics,GetFileMetrics,DeviceInfoNode,FlowInformation
diff --git a/extensions/prometheus/PrometheusMetricsPublisher.cpp 
b/extensions/prometheus/PrometheusMetricsPublisher.cpp
index 85f122120..56c866a4d 100644
--- a/extensions/prometheus/PrometheusMetricsPublisher.cpp
+++ b/extensions/prometheus/PrometheusMetricsPublisher.cpp
@@ -20,7 +20,9 @@
 
 #include "core/Resource.h"
 #include "utils/StringUtils.h"
+#include "utils/OsUtils.h"
 #include "PrometheusExposerWrapper.h"
+#include "utils/Id.h"
 
 namespace org::apache::nifi::minifi::extensions::prometheus {
 
@@ -35,6 +37,7 @@ void PrometheusMetricsPublisher::initialize(const 
std::shared_ptr<Configure>& co
   if (!exposer_) {
     exposer_ = std::make_unique<PrometheusExposerWrapper>(readPort());
   }
+  loadAgentIdentifier();
   loadMetricNodes(root);
 }
 
@@ -61,7 +64,7 @@ void 
PrometheusMetricsPublisher::loadMetricNodes(core::ProcessGroup* root) {
 
   for (const auto& metric_node : nodes) {
     logger_->log_debug("Registering metric node '%s'", metric_node->getName());
-    
gauge_collections_.push_back(std::make_shared<PublishedMetricGaugeCollection>(metric_node));
+    
gauge_collections_.push_back(std::make_shared<PublishedMetricGaugeCollection>(metric_node,
 agent_identifier_));
     exposer_->registerMetric(gauge_collections_.back());
   }
 }
@@ -82,6 +85,16 @@ std::vector<std::shared_ptr<state::response::ResponseNode>> 
PrometheusMetricsPub
   return nodes;
 }
 
+void PrometheusMetricsPublisher::loadAgentIdentifier() {
+  auto agent_identifier = 
configuration_->get(Configure::nifi_metrics_publisher_agent_identifier);
+  if (agent_identifier && !agent_identifier->empty()) {
+    agent_identifier_ = *agent_identifier;
+  } else {
+    auto hostname = utils::OsUtils::getHostName();
+    agent_identifier_ = hostname ? *hostname : "unknown-host-" + 
utils::IdGenerator::getIdGenerator()->generate().to_string();
+  }
+}
+
 REGISTER_RESOURCE(PrometheusMetricsPublisher, DescriptionOnly);
 
 }  // namespace org::apache::nifi::minifi::extensions::prometheus
diff --git a/extensions/prometheus/PrometheusMetricsPublisher.h 
b/extensions/prometheus/PrometheusMetricsPublisher.h
index b3ac09644..58451b077 100644
--- a/extensions/prometheus/PrometheusMetricsPublisher.h
+++ b/extensions/prometheus/PrometheusMetricsPublisher.h
@@ -44,12 +44,14 @@ class PrometheusMetricsPublisher : public 
core::CoreComponent, public state::Met
  private:
   uint32_t readPort();
   std::vector<std::shared_ptr<state::response::ResponseNode>> 
getMetricNodes(core::ProcessGroup* root);
+  void loadAgentIdentifier();
 
   std::mutex registered_metrics_mutex_;
   std::vector<std::shared_ptr<PublishedMetricGaugeCollection>> 
gauge_collections_;
   std::unique_ptr<MetricsExposer> exposer_;
   std::shared_ptr<Configure> configuration_;
   state::response::ResponseNodeLoader* response_node_loader_ = nullptr;
+  std::string agent_identifier_;
   std::shared_ptr<core::logging::Logger> 
logger_{core::logging::LoggerFactory<PrometheusMetricsPublisher>::getLogger()};
 };
 
diff --git a/extensions/prometheus/PublishedMetricGaugeCollection.cpp 
b/extensions/prometheus/PublishedMetricGaugeCollection.cpp
index e8974d386..81726749b 100644
--- a/extensions/prometheus/PublishedMetricGaugeCollection.cpp
+++ b/extensions/prometheus/PublishedMetricGaugeCollection.cpp
@@ -26,7 +26,9 @@
 
 namespace org::apache::nifi::minifi::extensions::prometheus {
 
-PublishedMetricGaugeCollection::PublishedMetricGaugeCollection(std::shared_ptr<state::PublishedMetricProvider>
 metric) : metric_{std::move(metric)} {
+PublishedMetricGaugeCollection::PublishedMetricGaugeCollection(std::shared_ptr<state::PublishedMetricProvider>
 metric, std::string agent_identifier)
+  : metric_{std::move(metric)},
+    agent_identifier_(std::move(agent_identifier)) {
 }
 
 std::vector<::prometheus::MetricFamily> 
PublishedMetricGaugeCollection::Collect() const {
@@ -35,6 +37,7 @@ std::vector<::prometheus::MetricFamily> 
PublishedMetricGaugeCollection::Collect(
     ::prometheus::ClientMetric client_metric;
     client_metric.label = ranges::views::transform(metric.labels, [](auto&& 
kvp) { return ::prometheus::ClientMetric::Label{kvp.first, kvp.second}; })
       | ranges::to<std::vector<::prometheus::ClientMetric::Label>>;
+    
client_metric.label.push_back(::prometheus::ClientMetric::Label{"agent_identifier",
 agent_identifier_});
     client_metric.gauge = ::prometheus::ClientMetric::Gauge{metric.value};
     collection.push_back({
       .name = "minifi_" + metric.name,
diff --git a/extensions/prometheus/PublishedMetricGaugeCollection.h 
b/extensions/prometheus/PublishedMetricGaugeCollection.h
index 8d8982a8f..0858e499f 100644
--- a/extensions/prometheus/PublishedMetricGaugeCollection.h
+++ b/extensions/prometheus/PublishedMetricGaugeCollection.h
@@ -18,6 +18,7 @@
 
 #include <memory>
 #include <vector>
+#include <string>
 
 #include "state/PublishedMetricProvider.h"
 #include "prometheus/collectable.h"
@@ -27,11 +28,12 @@ namespace org::apache::nifi::minifi::extensions::prometheus 
{
 
 class PublishedMetricGaugeCollection : public ::prometheus::Collectable {
  public:
-  explicit 
PublishedMetricGaugeCollection(std::shared_ptr<state::PublishedMetricProvider> 
metric);
+  explicit 
PublishedMetricGaugeCollection(std::shared_ptr<state::PublishedMetricProvider> 
metric, std::string agent_identifier);
   std::vector<::prometheus::MetricFamily> Collect() const override;
 
  private:
   std::shared_ptr<state::PublishedMetricProvider> metric_;
+  std::string agent_identifier_;
 };
 
 }  // namespace org::apache::nifi::minifi::extensions::prometheus
diff --git a/extensions/prometheus/tests/PrometheusMetricsPublisherTest.cpp 
b/extensions/prometheus/tests/PrometheusMetricsPublisherTest.cpp
index b10b779d0..98e8d6afb 100644
--- a/extensions/prometheus/tests/PrometheusMetricsPublisherTest.cpp
+++ b/extensions/prometheus/tests/PrometheusMetricsPublisherTest.cpp
@@ -24,7 +24,8 @@
 #include "MetricsExposer.h"
 #include "core/state/nodes/ResponseNodeLoader.h"
 #include "core/RepositoryFactory.h"
-#include "range/v3/algorithm/find.hpp"
+#include "range/v3/algorithm/find_if.hpp"
+#include "range/v3/algorithm/contains.hpp"
 
 namespace org::apache::nifi::minifi::extensions::prometheus::test {
 
@@ -90,6 +91,7 @@ 
TEST_CASE_METHOD(PrometheusPublisherTestFixtureWithRealExposer, "Test prometheus
 
 TEST_CASE_METHOD(PrometheusPublisherTestFixtureWithDummyExposer, "Test adding 
metrics to exposer", "[prometheusPublisherTest]") {
   configuration_->set(Configure::nifi_metrics_publisher_metrics, 
"QueueMetrics,RepositoryMetrics,DeviceInfoNode,FlowInformation,AgentInformation,InvalidMetrics,GetFileMetrics,GetTCPMetrics");
+  configuration_->set(Configure::nifi_metrics_publisher_agent_identifier, 
"AgentId-1");
   publisher_->initialize(configuration_, response_node_loader_, nullptr);
   auto stored_metrics = exposer_->getMetrics();
   std::vector<std::string> valid_metrics_without_flow = {"QueueMetrics", 
"RepositoryMetrics", "DeviceInfoNode", "FlowInformation", "AgentInformation"};
@@ -98,11 +100,12 @@ 
TEST_CASE_METHOD(PrometheusPublisherTestFixtureWithDummyExposer, "Test adding me
     auto collection = stored_metric->Collect();
     for (const auto& metric_family : collection) {
       for (const auto& prometheus_metric : metric_family.metric) {
-        for (const auto& label : prometheus_metric.label) {
-          if (label.name == "metric_class") {
-            REQUIRE(ranges::find(valid_metrics_without_flow, label.value) != 
ranges::end(valid_metrics_without_flow));
-          }
-        }
+        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");
       }
     }
   }
diff --git a/libminifi/include/properties/Configuration.h 
b/libminifi/include/properties/Configuration.h
index 906bdf0c2..7641aba4c 100644
--- a/libminifi/include/properties/Configuration.h
+++ b/libminifi/include/properties/Configuration.h
@@ -167,6 +167,7 @@ class Configuration : public Properties {
   static constexpr const char *nifi_asset_directory = "nifi.asset.directory";
 
   // Metrics publisher options
+  static constexpr const char *nifi_metrics_publisher_agent_identifier = 
"nifi.metrics.publisher.agent.identifier";
   static constexpr const char *nifi_metrics_publisher_class = 
"nifi.metrics.publisher.class";
   static constexpr const char 
*nifi_metrics_publisher_prometheus_metrics_publisher_port = 
"nifi.metrics.publisher.PrometheusMetricsPublisher.port";
   static constexpr const char *nifi_metrics_publisher_metrics = 
"nifi.metrics.publisher.metrics";
diff --git a/libminifi/include/utils/OsUtils.h 
b/libminifi/include/utils/OsUtils.h
index a9b6253d3..66c9ea85c 100644
--- a/libminifi/include/utils/OsUtils.h
+++ b/libminifi/include/utils/OsUtils.h
@@ -14,20 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef LIBMINIFI_INCLUDE_UTILS_OSUTILS_H_
-#define LIBMINIFI_INCLUDE_UTILS_OSUTILS_H_
+#pragma once
 
 #include <string>
+#include <optional>
 
 struct sockaddr;
 
-namespace org {
-namespace apache {
-namespace nifi {
-namespace minifi {
-namespace utils {
-namespace OsUtils {
-
+namespace org::apache::nifi::minifi::utils::OsUtils {
 
 /// Resolves a user ID to a username
 extern std::string userIdToUsername(const std::string &uid);
@@ -54,12 +48,6 @@ std::string getMachineArchitecture();
 extern std::string resolve_common_identifiers(const std::string &id);
 #endif
 
+std::optional<std::string> getHostName();
 
-} /* namespace OsUtils */
-} /* namespace utils */
-} /* namespace minifi */
-} /* namespace nifi */
-} /* namespace apache */
-} /* namespace org */
-
-#endif  // LIBMINIFI_INCLUDE_UTILS_OSUTILS_H_
+}  // namespace org::apache::nifi::minifi::utils::OsUtils
diff --git a/libminifi/src/Configuration.cpp b/libminifi/src/Configuration.cpp
index ccd8fcab9..5da28f49d 100644
--- a/libminifi/src/Configuration.cpp
+++ b/libminifi/src/Configuration.cpp
@@ -133,6 +133,7 @@ const std::vector<core::ConfigurationProperty> 
Configuration::CONFIGURATION_PROP
   core::ConfigurationProperty{Configuration::nifi_log_alert_buffer_limit},
   core::ConfigurationProperty{Configuration::nifi_log_alert_level},
   core::ConfigurationProperty{Configuration::nifi_asset_directory},
+  
core::ConfigurationProperty{Configuration::nifi_metrics_publisher_agent_identifier},
   core::ConfigurationProperty{Configuration::nifi_metrics_publisher_class},
   
core::ConfigurationProperty{Configuration::nifi_metrics_publisher_prometheus_metrics_publisher_port,
 gsl::make_not_null(core::StandardValidators::get().PORT_VALIDATOR.get())},
   core::ConfigurationProperty{Configuration::nifi_metrics_publisher_metrics}
diff --git a/libminifi/src/utils/OsUtils.cpp b/libminifi/src/utils/OsUtils.cpp
index cfac877d3..fd6789bc1 100644
--- a/libminifi/src/utils/OsUtils.cpp
+++ b/libminifi/src/utils/OsUtils.cpp
@@ -57,11 +57,7 @@
 #include <sys/sysctl.h>
 #endif
 
-namespace org {
-namespace apache {
-namespace nifi {
-namespace minifi {
-namespace utils {
+namespace org::apache::nifi::minifi::utils {
 
 #ifdef _WIN32
 /*
@@ -320,9 +316,13 @@ std::string OsUtils::getMachineArchitecture() {
   return "unknown";
 }
 
-}  // namespace utils
-}  // namespace minifi
-}  // namespace nifi
-}  // namespace apache
-}  // namespace org
+std::optional<std::string> OsUtils::getHostName() {
+  char hostname[1024];
+  hostname[1023] = '\0';
+  if (gethostname(hostname, 1023) != 0) {
+    return std::nullopt;
+  }
+  return {hostname};
+}
 
+}  // namespace org::apache::nifi::minifi::utils
diff --git a/libminifi/test/resources/encrypted.minifi.properties 
b/libminifi/test/resources/encrypted.minifi.properties
index 11c38e182..920034036 100644
--- a/libminifi/test/resources/encrypted.minifi.properties
+++ b/libminifi/test/resources/encrypted.minifi.properties
@@ -104,6 +104,7 @@ nifi.c2.flow.url=
 nifi.sensitive.props.additional.keys=c2.agent.identifier
 
 # Publish metrics to external consumers
+# nifi.metrics.publisher.agent.identifier=
 # nifi.metrics.publisher.class=PrometheusMetricsPublisher
 # nifi.metrics.publisher.PrometheusMetricsPublisher.port=9936
 # 
nifi.metrics.publisher.metrics=QueueMetrics,RepositoryMetrics,GetFileMetrics,DeviceInfoNode,FlowInformation

Reply via email to