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

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

commit 2f26cb92f5331a8facbfd7354d5dfca148895b74
Author: Gabor Gyimesi <[email protected]>
AuthorDate: Thu Feb 26 15:53:20 2026 +0100

    MINIFICPP-2723 Add log and properties.d dir property files to debug bundle
    
    Signed-off-by: Ferenc Gerlits <[email protected]>
    
    Closes #2124
---
 libminifi/include/properties/Configure.h           |  3 +++
 libminifi/include/properties/Properties.h          |  3 ++-
 libminifi/src/Configure.cpp                        | 14 ++++++++++++++
 libminifi/src/FlowController.cpp                   | 17 +++++++++++++++++
 libminifi/test/integration/C2DebugBundleTest.cpp   | 22 ++++++++++++++++++----
 .../test/libtest/integration/IntegrationBase.cpp   |  3 ++-
 .../test/libtest/integration/IntegrationBase.h     |  9 ++++++++-
 .../include/minifi-cpp/properties/Configure.h      |  3 +++
 .../include/minifi-cpp/properties/Properties.h     |  1 +
 9 files changed, 68 insertions(+), 7 deletions(-)

diff --git a/libminifi/include/properties/Configure.h 
b/libminifi/include/properties/Configure.h
index d869ad7da..7f35c8324 100644
--- a/libminifi/include/properties/Configure.h
+++ b/libminifi/include/properties/Configure.h
@@ -49,6 +49,9 @@ class ConfigureImpl : public ConfigurationImpl, public 
virtual core::AgentIdenti
   std::string getAgentIdentifier() const override;
   void setFallbackAgentIdentifier(const std::string& id) override;
 
+  std::optional<std::filesystem::path> logPropertiesFilePath() const override;
+  std::optional<std::filesystem::path> extraLogPropertiesFilesDirName() const 
override;
+
   using Configuration::set;
   void set(const std::string& key, const std::string& value, 
PropertyChangeLifetime lifetime) override;
   bool commitChanges() override;
diff --git a/libminifi/include/properties/Properties.h 
b/libminifi/include/properties/Properties.h
index 4f94f6401..f4880a557 100644
--- a/libminifi/include/properties/Properties.h
+++ b/libminifi/include/properties/Properties.h
@@ -124,8 +124,9 @@ class PropertiesImpl : public virtual Properties {
 
   std::map<std::string, std::string> getProperties() const override;
 
+  std::filesystem::path extraPropertiesFilesDirName() const override;
+
  private:
-  std::filesystem::path extraPropertiesFilesDirName() const;
   void setPropertiesFromFile(const std::filesystem::path& properties_file, 
std::string_view prefix);
 
   std::map<std::string, PropertyValue> properties_;
diff --git a/libminifi/src/Configure.cpp b/libminifi/src/Configure.cpp
index a0ad4f91d..35280d56c 100644
--- a/libminifi/src/Configure.cpp
+++ b/libminifi/src/Configure.cpp
@@ -110,6 +110,20 @@ void ConfigureImpl::setFallbackAgentIdentifier(const 
std::string& id) {
   fallback_identifier_ = id;
 }
 
+std::optional<std::filesystem::path> ConfigureImpl::logPropertiesFilePath() 
const {
+  if (logger_properties_) {
+    return logger_properties_->getFilePath();
+  }
+  return std::nullopt;
+}
+
+std::optional<std::filesystem::path> 
ConfigureImpl::extraLogPropertiesFilesDirName() const {
+  if (logger_properties_) {
+    return logger_properties_->extraPropertiesFilesDirName();
+  }
+  return std::nullopt;
+}
+
 void ConfigureImpl::set(const std::string& key, const std::string& value, 
PropertyChangeLifetime lifetime) {
   const std::string_view log_prefix = "nifi.log.";
   if (utils::string::startsWith(key, log_prefix)) {
diff --git a/libminifi/src/FlowController.cpp b/libminifi/src/FlowController.cpp
index 16a43ec13..a0ab0f90c 100644
--- a/libminifi/src/FlowController.cpp
+++ b/libminifi/src/FlowController.cpp
@@ -482,12 +482,29 @@ std::map<std::string, std::unique_ptr<io::InputStream>> 
FlowController::getDebug
     std::string index_str = i == logs.size() - 1 ? "" : "." + 
std::to_string(logs.size() - 1 - i);
     debug_info["minifi.log" + index_str + ".gz"] = std::move(logs[i]);
   }
+
   if (auto opt_flow_path = flow_configuration_->getConfigurationPath()) {
     if (utils::file::exists(opt_flow_path.value())) {
       debug_info["config.yml"] = 
std::make_unique<io::FileStream>(opt_flow_path.value(), 0, false);
     }
   }
+
+  const auto addDirectoryContents = [this, &debug_info](const 
std::filesystem::path& dir) {
+    if (!utils::file::exists(dir)) { return; }
+    for (const auto& [parent, file] : utils::file::list_dir_all(dir, logger_, 
false)) {
+      debug_info[parent.filename().string() + "/" + file.string()] = 
std::make_unique<io::FileStream>(dir / file, 0, false);
+    }
+  };
+
   debug_info["minifi.properties"] = 
std::make_unique<io::FileStream>(configuration_->getFilePath(), 0, false);
+  addDirectoryContents(configuration_->extraPropertiesFilesDirName());
+
+  if (auto log_properties_path = configuration_->logPropertiesFilePath()) {
+    debug_info["minifi-log.properties"] = 
std::make_unique<io::FileStream>(*log_properties_path, 0, false);
+  }
+  if (auto log_properties_dir = 
configuration_->extraLogPropertiesFilesDirName()) {
+    addDirectoryContents(*log_properties_dir);
+  }
 
   return debug_info;
 }
diff --git a/libminifi/test/integration/C2DebugBundleTest.cpp 
b/libminifi/test/integration/C2DebugBundleTest.cpp
index 6a5ab86b3..f68f8d7a3 100644
--- a/libminifi/test/integration/C2DebugBundleTest.cpp
+++ b/libminifi/test/integration/C2DebugBundleTest.cpp
@@ -138,6 +138,9 @@ class C2HeartbeatHandler : public ServerAwareHandler {
 };
 
 static std::string properties_file = "some.dummy.content = here\n";
+static std::string c2_properties_file = "c2.dummy.content = content\n";
+static std::string log_properties_file = "log.dummy.content = log\n";
+static std::string extra_log_properties_file = "extra.log.dummy.content = 
extra\n";
 static std::string flow_config_file = empty_flow;
 
 TEST_CASE("C2DebugBundleTest", "[c2test]") {
@@ -149,7 +152,12 @@ TEST_CASE("C2DebugBundleTest", "[c2test]") {
 
   std::filesystem::path home_dir = controller.createTempDirectory();
   minifi::utils::file::PathUtils::create_dir(home_dir / "conf");
+  minifi::utils::file::PathUtils::create_dir(home_dir / "conf" / 
"minifi.properties.d");
+  minifi::utils::file::PathUtils::create_dir(home_dir / "conf" / 
"minifi-log.properties.d");
   std::ofstream{home_dir / "conf" / "minifi.properties", std::ios::binary} << 
properties_file;
+  std::ofstream{home_dir / "conf" / "minifi.properties.d" / 
"90_c2.properties", std::ios::binary} << c2_properties_file;
+  std::ofstream{home_dir / "conf" / "minifi-log.properties", std::ios::binary} 
<< log_properties_file;
+  std::ofstream{home_dir / "conf" / "minifi-log.properties.d" / 
"99_c2.properties", std::ios::binary} << extra_log_properties_file;
   std::ofstream{home_dir / "conf" / "config.yml", std::ios::binary} << 
flow_config_file;
 
   VerifyDebugInfo harness(home_dir / "conf" / "config.yml", [&]() -> bool {
@@ -174,8 +182,11 @@ TEST_CASE("C2DebugBundleTest", "[c2test]") {
               file_content.length());
       archive_content[info->filename] = std::move(file_content);
     }
-    REQUIRE(archive_content["minifi.properties"] == properties_file);
-    REQUIRE(archive_content["config.yml"] == flow_config_file);
+    CHECK(archive_content["minifi.properties"] == properties_file);
+    CHECK(archive_content["minifi.properties.d/90_c2.properties"] == 
c2_properties_file);
+    CHECK(archive_content["minifi-log.properties"] == log_properties_file);
+    CHECK(archive_content["minifi-log.properties.d/99_c2.properties"] == 
extra_log_properties_file);
+    CHECK(archive_content["config.yml"] == flow_config_file);
     auto log_gz = archive_content["minifi.log.gz"];
     auto log_stream = std::make_shared<minifi::io::BufferStream>();
     {
@@ -185,11 +196,12 @@ TEST_CASE("C2DebugBundleTest", "[c2test]") {
     std::string log_text;
     log_text.resize(log_stream->size());
     log_stream->read(as_writable_bytes(std::span(log_text)));
-    REQUIRE(log_text.find("Tis but a scratch") != std::string::npos);
-    REQUIRE(archive_content["manifest.json"].find("minifi-archive-extensions") 
!= std::string::npos);
+    CHECK(log_text.find("Tis but a scratch") != std::string::npos);
+    CHECK(archive_content["manifest.json"].find("minifi-archive-extensions") 
!= std::string::npos);
     return true;
   });
 
+  harness.getLoggerProperties()->loadConfigureFile(home_dir / "conf" / 
"minifi-log.properties");
   harness.getConfiguration()->loadConfigureFile(home_dir / "conf" / 
"minifi.properties");
   harness.setUrl("http://localhost:0/heartbeat";, &heartbeat_handler);
   harness.setUrl("http://localhost:0/acknowledge";, &ack_handler);
@@ -213,6 +225,7 @@ TEST_CASE("Test that the debug bundle operation works when 
config.yml does not e
   std::filesystem::path home_dir = controller.createTempDirectory();
   minifi::utils::file::PathUtils::create_dir(home_dir / "conf");
   std::ofstream{home_dir / "conf" / "minifi.properties", std::ios::binary} << 
properties_file;
+  std::ofstream{home_dir / "conf" / "minifi-log.properties", std::ios::binary} 
<< log_properties_file;
 
   VerifyDebugInfo harness(home_dir / "conf" / "config.yml", [&]() -> bool {
     if (!ack_handler.isAcknowledged("79")) {
@@ -224,6 +237,7 @@ TEST_CASE("Test that the debug bundle operation works when 
config.yml does not e
   });
 
   harness.getConfiguration()->loadConfigureFile(home_dir / "conf" / 
"minifi.properties");
+  harness.getLoggerProperties()->loadConfigureFile(home_dir / "conf" / 
"minifi-log.properties");
   harness.setUrl("http://localhost:0/heartbeat";, &heartbeat_handler);
   harness.setUrl("http://localhost:0/acknowledge";, &ack_handler);
   harness.setUrl("http://localhost:0/debug_bundle";, &bundle_handler);
diff --git a/libminifi/test/libtest/integration/IntegrationBase.cpp 
b/libminifi/test/libtest/integration/IntegrationBase.cpp
index cb29d5a02..8a767546a 100644
--- a/libminifi/test/libtest/integration/IntegrationBase.cpp
+++ b/libminifi/test/libtest/integration/IntegrationBase.cpp
@@ -31,7 +31,8 @@
 namespace org::apache::nifi::minifi::test {
 
 IntegrationBase::IntegrationBase(const std::optional<std::filesystem::path>& 
test_file_location, const std::optional<std::filesystem::path>& home_path, 
std::chrono::milliseconds waitTime)
-    : configuration(std::make_shared<minifi::ConfigureImpl>()),
+    : 
logger_properties_(std::make_shared<core::logging::LoggerProperties>(std::filesystem::temp_directory_path())),
+      configuration(std::make_shared<minifi::ConfigureImpl>(std::nullopt, 
logger_properties_)),
       wait_time_(waitTime),
       home_path_(home_path) {
   flow_config_path_.config_path = test_file_location;
diff --git a/libminifi/test/libtest/integration/IntegrationBase.h 
b/libminifi/test/libtest/integration/IntegrationBase.h
index df7a29688..9f406d57a 100644
--- a/libminifi/test/libtest/integration/IntegrationBase.h
+++ b/libminifi/test/libtest/integration/IntegrationBase.h
@@ -50,7 +50,8 @@ class IntegrationBase {
       std::chrono::milliseconds waitTime = 
std::chrono::milliseconds(DEFAULT_WAITTIME_MSECS));
   IntegrationBase(const IntegrationBase&) = delete;
   IntegrationBase(IntegrationBase&& other) noexcept
-      : configuration{std::move(other.configuration)},
+      : logger_properties_{std::move(other.logger_properties_)},
+        configuration{std::move(other.configuration)},
         flowController_{std::move(other.flowController_)},
         wait_time_{other.wait_time_},
         port{std::move(other.port)},
@@ -64,6 +65,7 @@ class IntegrationBase {
   IntegrationBase& operator=(const IntegrationBase&) = delete;
   IntegrationBase& operator=(IntegrationBase&& other) noexcept {
     if (&other == this) return *this;
+    logger_properties_ = std::move(other.logger_properties_);
     configuration = std::move(other.configuration);
     flowController_ = std::move(other.flowController_);
     wait_time_ = other.wait_time_;
@@ -94,6 +96,10 @@ class IntegrationBase {
     return configuration;
   }
 
+  const std::shared_ptr<core::logging::LoggerProperties>& 
getLoggerProperties() const {
+    return logger_properties_;
+  }
+
   void setConfiguration(std::shared_ptr<minifi::Configure> configuration) {
     this->configuration = std::move(configuration);
   }
@@ -124,6 +130,7 @@ class IntegrationBase {
   }
 
   void configureSecurity();
+  std::shared_ptr<core::logging::LoggerProperties> logger_properties_;
   std::shared_ptr<minifi::Configure> configuration;
   std::unique_ptr<minifi::utils::file::AssetManager> asset_manager_;
   std::unique_ptr<core::BulletinStore> bulletin_store_;
diff --git a/minifi-api/include/minifi-cpp/properties/Configure.h 
b/minifi-api/include/minifi-cpp/properties/Configure.h
index 12427cf8e..5402e5a18 100644
--- a/minifi-api/include/minifi-cpp/properties/Configure.h
+++ b/minifi-api/include/minifi-cpp/properties/Configure.h
@@ -41,6 +41,9 @@ class Configure : public virtual Configuration, public 
virtual core::AgentIdenti
 
   virtual void setFallbackAgentIdentifier(const std::string& id) = 0;
 
+  virtual std::optional<std::filesystem::path> logPropertiesFilePath() const = 
0;
+  virtual std::optional<std::filesystem::path> 
extraLogPropertiesFilesDirName() const = 0;
+
   using Configuration::set;
   void set(const std::string& key, const std::string& value, 
PropertyChangeLifetime lifetime) override = 0;
   bool commitChanges() override = 0;
diff --git a/minifi-api/include/minifi-cpp/properties/Properties.h 
b/minifi-api/include/minifi-cpp/properties/Properties.h
index a9573a09a..a40d540fd 100644
--- a/minifi-api/include/minifi-cpp/properties/Properties.h
+++ b/minifi-api/include/minifi-cpp/properties/Properties.h
@@ -60,6 +60,7 @@ class Properties {
   virtual utils::ChecksumCalculator& getChecksumCalculator() = 0;
   virtual std::filesystem::path getFilePath() const = 0;
   virtual std::map<std::string, std::string> getProperties() const = 0;
+  virtual std::filesystem::path extraPropertiesFilesDirName() const = 0;
 
   static std::shared_ptr<Properties> create();
 };

Reply via email to