You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2021/05/06 14:46:57 UTC

[celix] branch feature/cxx_rsa_update updated: Refactors cxx rsa, improves configured discovery tests and add C++ LogHelper class

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

pnoltes pushed a commit to branch feature/cxx_rsa_update
in repository https://gitbox.apache.org/repos/asf/celix.git


The following commit(s) were added to refs/heads/feature/cxx_rsa_update by this push:
     new 20ad07b  Refactors cxx rsa, improves configured discovery tests and add C++ LogHelper class
20ad07b is described below

commit 20ad07b281e7ac972b7d7dc06816b3cf427407e7
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Thu May 6 16:45:11 2021 +0200

    Refactors cxx rsa, improves configured discovery tests and add C++ LogHelper class
---
 bundles/cxx_remote_services/admin/CMakeLists.txt   |   2 +-
 .../admin/gtest/src/RemoteServiceAdminTestSuite.cc |   5 +-
 .../admin/include/RemoteServiceAdmin.h             |   9 +-
 .../admin/src/RemoteServiceAdmin.cc                |  29 ++---
 .../discovery_configured/CMakeLists.txt            |   1 +
 .../gtest/src/RsaConfiguredDiscoveryTestSuite.cc   |  34 +++++-
 .../celix/rsa/IConfiguredDiscoveryManager.h        |  37 ++++++-
 .../src/ConfiguredDiscoveryManager.cc              | 122 +++++++++++++--------
 .../src/ConfiguredDiscoveryManager.h               |  18 ++-
 .../src/ConfiguredDiscoveryManagerActivator.cc     |   3 +-
 bundles/logging/log_helper/CMakeLists.txt          |   2 +-
 .../log_helper/gtest/src/LogHelperTestSuite.cc     |  44 +++++---
 .../logging/log_helper/include/celix/LogHelper.h   | 118 ++++++++++++++++++++
 .../logging/log_helper/include/celix_log_helper.h  |  26 +++--
 .../{include_v2 => include_v1}/log_helper.h        |   0
 15 files changed, 332 insertions(+), 118 deletions(-)

diff --git a/bundles/cxx_remote_services/admin/CMakeLists.txt b/bundles/cxx_remote_services/admin/CMakeLists.txt
index 38bae70..4aee864 100644
--- a/bundles/cxx_remote_services/admin/CMakeLists.txt
+++ b/bundles/cxx_remote_services/admin/CMakeLists.txt
@@ -28,7 +28,7 @@ target_include_directories(RemoteServiceAdmin PRIVATE include)
 target_link_libraries(RemoteServiceAdmin PRIVATE
         Celix::rsa_spi
         Celix::framework
-        Celix::log_service_api
+        Celix::log_helper
 )
 
 install_celix_bundle(RemoteServiceAdmin EXPORT celix COMPONENT rsa)
diff --git a/bundles/cxx_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc b/bundles/cxx_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc
index c9d5c4e..3ffdd18 100644
--- a/bundles/cxx_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc
+++ b/bundles/cxx_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc
@@ -28,7 +28,10 @@
 class RemoteServiceAdminTestSuite : public ::testing::Test {
 public:
     RemoteServiceAdminTestSuite() {
-        fw = celix::createFramework();
+        celix::Properties config{
+                {"CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL", "trace"}
+        };
+        fw = celix::createFramework(config);
         ctx = fw->getFrameworkBundleContext();
     }
 
diff --git a/bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h b/bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h
index 2d6b866..454ff90 100644
--- a/bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h
+++ b/bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h
@@ -20,7 +20,7 @@
 #include "celix/rsa/EndpointDescription.h"
 #include <celix_api.h>
 #include <mutex>
-#include "celix_log_service.h"
+#include "celix/LogHelper.h"
 
 #if defined(__has_include) && __has_include(<version>)
 #include <version>
@@ -37,6 +37,8 @@ namespace celix::rsa {
 
     class RemoteServiceAdmin {
     public:
+        explicit RemoteServiceAdmin(celix::LogHelper logHelper);
+
         // Imported endpoint add/remove functions
         void addEndpoint(const std::shared_ptr<celix::rsa::EndpointDescription>& endpoint);
         void removeEndpoint(const std::shared_ptr<celix::rsa::EndpointDescription>& endpoint);
@@ -52,14 +54,11 @@ namespace celix::rsa {
         // Add/remove services, used to track all services registered with celix and check if remote = true.
         void addService(const std::shared_ptr<void>& svc, const std::shared_ptr<const celix::Properties>& properties);
         void removeService(const std::shared_ptr<void>& svc, const std::shared_ptr<const celix::Properties>& properties);
-
-        // Set logging service
-        void setLogger(const std::shared_ptr<celix_log_service>& logService);
     private:
         void createExportServices();
         void createImportServices();
 
-        std::shared_ptr<celix_log_service> _logService{};
+        celix::LogHelper _logHelper;
         std::mutex _m{}; // protects below
 
 #if __cpp_lib_memory_resource
diff --git a/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc b/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc
index 4bdcc49..e71c50c 100644
--- a/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc
+++ b/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc
@@ -23,21 +23,15 @@
 #include "celix/rsa/IExportServiceFactory.h"
 
 #define L_DEBUG(...) \
-    if (_logService) {                                                  \
-        _logService->debug(_logService->handle, __VA_ARGS__);           \
-    }
+        _logHelper.debug(__VA_ARGS__);
 #define L_INFO(...) \
-    if (_logService) {                                                  \
-        _logService->info(_logService->handle, __VA_ARGS__);            \
-    }
+        _logHelper.info(__VA_ARGS__);
 #define L_WARN(...) \
-    if (_logService) {                                                  \
-        _logService->warning(_logService->handle, __VA_ARGS__);         \
-    }
+        _logHelper.warning(__VA_ARGS__);
 #define L_ERROR(...) \
-    if (_logService) {                                                  \
-        _logService->error(_logService->handle, __VA_ARGS__);           \
-    }
+        _logHelper.error(__VA_ARGS__);
+
+celix::rsa::RemoteServiceAdmin::RemoteServiceAdmin(celix::LogHelper logHelper) : _logHelper{std::move(logHelper)} {}
 
 void celix::rsa::RemoteServiceAdmin::addEndpoint(const std::shared_ptr<celix::rsa::EndpointDescription>& endpoint) {
     assert(endpoint);
@@ -223,14 +217,10 @@ void celix::rsa::RemoteServiceAdmin::createExportServices() {
     }
 }
 
-void celix::rsa::RemoteServiceAdmin::setLogger(const std::shared_ptr<celix_log_service>& logService) {
-    _logService = logService;
-}
-
 class AdminActivator {
 public:
     explicit AdminActivator(const std::shared_ptr<celix::BundleContext>& ctx) {
-        auto admin = std::make_shared<celix::rsa::RemoteServiceAdmin>();
+        auto admin = std::make_shared<celix::rsa::RemoteServiceAdmin>(celix::LogHelper{ctx, celix::typeName<celix::rsa::RemoteServiceAdmin>()});
 
         auto& cmp = ctx->getDependencyManager()->createComponent(admin);
         cmp.createServiceDependency<celix::rsa::EndpointDescription>()
@@ -245,11 +235,6 @@ public:
                 .setRequired(false)
                 .setStrategy(celix::dm::DependencyUpdateStrategy::locking)
                 .setCallbacks(&celix::rsa::RemoteServiceAdmin::addExportedServiceFactory, &celix::rsa::RemoteServiceAdmin::removeExportedServiceFactory);
-        cmp.createServiceDependency<celix_log_service>(CELIX_LOG_SERVICE_NAME)
-                .setRequired(false)
-                .setFilter(std::string{"("}.append(CELIX_LOG_SERVICE_PROPERTY_NAME).append("=celix::rsa::RemoteServiceAdmin)"))
-                .setStrategy(celix::dm::DependencyUpdateStrategy::suspend)
-                .setCallbacks(&celix::rsa::RemoteServiceAdmin::setLogger);
         cmp.build();
 
         //note adding void service dependencies is not supported for the dependency manager, using a service tracker instead.
diff --git a/bundles/cxx_remote_services/discovery_configured/CMakeLists.txt b/bundles/cxx_remote_services/discovery_configured/CMakeLists.txt
index 5301efb..cccd2a1 100644
--- a/bundles/cxx_remote_services/discovery_configured/CMakeLists.txt
+++ b/bundles/cxx_remote_services/discovery_configured/CMakeLists.txt
@@ -36,6 +36,7 @@ target_link_libraries(RsaConfiguredDiscovery PRIVATE
         RsaConfiguredDiscovery_api
         Celix::framework
         Celix::rsa_spi
+        Celix::log_helper
 )
 target_include_directories(RsaConfiguredDiscovery PRIVATE src)
 install_celix_bundle(RsaConfiguredDiscovery EXPORT celix COMPONENT rsa)
diff --git a/bundles/cxx_remote_services/discovery_configured/gtest/src/RsaConfiguredDiscoveryTestSuite.cc b/bundles/cxx_remote_services/discovery_configured/gtest/src/RsaConfiguredDiscoveryTestSuite.cc
index cd67aef..1f413f1 100644
--- a/bundles/cxx_remote_services/discovery_configured/gtest/src/RsaConfiguredDiscoveryTestSuite.cc
+++ b/bundles/cxx_remote_services/discovery_configured/gtest/src/RsaConfiguredDiscoveryTestSuite.cc
@@ -26,8 +26,10 @@
 class RsaConfiguredDiscoveryTestSuite : public ::testing::Test {
 public:
     RsaConfiguredDiscoveryTestSuite() {
-        celix::Properties config{};
-        config[celix::rsa::CONFIGURED_DISCOVERY_DISCOVERY_FILES] = std::string{RSA_CONFIGURED_DISCOVERY_DISCOVERY_FILE}.append("  ,  garbage_path, garbage_path2  ");
+        celix::Properties config{
+                {celix::rsa::CONFIGURED_DISCOVERY_DISCOVERY_FILES, std::string{RSA_CONFIGURED_DISCOVERY_DISCOVERY_FILE}.append("  ,  garbage_path, garbage_path2  ")},
+                {"CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL", "trace"}
+        };
         fw = celix::createFramework(config);
         ctx = fw->getFrameworkBundleContext();
     }
@@ -52,7 +54,7 @@ TEST_F(RsaConfiguredDiscoveryTestSuite, discoverConfiguredEndpoints) {
     auto count = ctx->useServices<celix::rsa::EndpointDescription>()
             .addUseCallback([](auto& endpoint) {
                 EXPECT_NE(endpoint.getId(), "");
-                //TODO EXPECT_NE(endpoint.getConfigurationTypes(), "");
+                EXPECT_NE(endpoint.getConfigurationTypes(), "");
                 EXPECT_NE(endpoint.getInterface(), "");
                 EXPECT_NE(endpoint.getFrameworkUUID(), "");
                 EXPECT_NE(endpoint.getProperties().get("endpoint.scope"), ""); //note async specific
@@ -63,4 +65,28 @@ TEST_F(RsaConfiguredDiscoveryTestSuite, discoverConfiguredEndpoints) {
     EXPECT_EQ(count, 2);
 }
 
-//TODO test add/remove of adding configured discovery file
\ No newline at end of file
+TEST_F(RsaConfiguredDiscoveryTestSuite, removeConfiguredEndpointFile) {
+    //When I install a configured discovery bundle with also a configured discovery file and will find
+    //2 EndpointDescriptions.
+    //If I then remove the configured discovery file using the IConfiguredDiscoveryManager service I will find
+    //0 EndpointDescriptions.
+
+    auto bndId = ctx->installBundle(RSA_CONFIGURED_DISCOVERY_BUNDLE_LOCATION);
+    EXPECT_GE(bndId, 0);
+
+    auto count = ctx->useServices<celix::rsa::EndpointDescription>().build();
+    EXPECT_EQ(count, 2);
+
+    count = ctx->useService<celix::rsa::IConfiguredDiscoveryManager>()
+                .addUseCallback([](auto& svc) {
+                    auto files = svc.getConfiguredDiscoveryFiles();
+                    EXPECT_EQ(files.size(), 1);
+                    svc.removeConfiguredDiscoveryFile(RSA_CONFIGURED_DISCOVERY_DISCOVERY_FILE);
+                })
+                .build();
+    EXPECT_EQ(count, 1);
+
+
+    count = ctx->useServices<celix::rsa::EndpointDescription>().build();
+    EXPECT_EQ(count, 0);
+}
diff --git a/bundles/cxx_remote_services/discovery_configured/include/celix/rsa/IConfiguredDiscoveryManager.h b/bundles/cxx_remote_services/discovery_configured/include/celix/rsa/IConfiguredDiscoveryManager.h
index 4e7967a..56b3649 100644
--- a/bundles/cxx_remote_services/discovery_configured/include/celix/rsa/IConfiguredDiscoveryManager.h
+++ b/bundles/cxx_remote_services/discovery_configured/include/celix/rsa/IConfiguredDiscoveryManager.h
@@ -18,23 +18,56 @@
  */
 #pragma once
 
+#include <vector>
+#include <string>
+
 namespace celix::rsa {
     /**
-     * @brief Config property for the ',' seperated paths for  configured endpoints files.
+     * @brief Config property for the configured endpoints files.
+     *
+     * Configured files will be read by the configured discovery manager during startup and the file will not
+     * be monitored for updates.
+     * Should be a string and can contain multiple entries ',' separated.
      */
     constexpr const char *const CONFIGURED_DISCOVERY_DISCOVERY_FILES = "CELIX_RSA_CONFIGURED_DISCOVERY_DISCOVERY_FILES";
 
     /**
      * @brief The IConfiguredDiscoveryManager interface.
      *
-     * TODO document the expect json format.
+     * Expected configured endpoint json format:
+     *      {
+     *          "endpoints": [
+     *              {
+     *                  "endpoint.id": "id-01",
+     *                  "service.imported": true,
+     *                  "service.imported.configs": ["pubsub"],
+     *                  "service.exported.interfaces": "IHardcodedService",
+     *                  "endpoint.objectClass": "TestComponentName",
+     *                  "endpoint.anykey" : "anyval"
+     *              }
+     *          ]
+     *      }
      */
     class IConfiguredDiscoveryManager {
     public:
         virtual ~IConfiguredDiscoveryManager() noexcept = default;
 
+        /**
+         * @brief Adds a configured discovery file to the discovery manager.
+         * @param path Path to a discovery file
+         * @throws celix::rsa::RemoteException if the path is incorrect or if the file format is invalid.
+         */
         virtual void addConfiguredDiscoveryFile(const std::string& path) = 0;
 
+        /**
+         * @brief Removes a configured discovery file to the discovery manager.
+         * @param path Path to a discovery file
+         */
         virtual void removeConfiguredDiscoveryFile(const std::string& path) = 0;
+
+        /**
+         * @brief List the (valid) configured discovery files known to this configured discovery manager.
+         */
+        virtual std::vector<std::string> getConfiguredDiscoveryFiles() const = 0;
     };
 }
diff --git a/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.cc b/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.cc
index 53d4d9e..4bd3cc5 100644
--- a/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.cc
+++ b/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.cc
@@ -21,11 +21,19 @@
 
 #include <fstream>
 #include <filesystem>
-
-#include <celix_bundle_context.h>
-
 #include <rapidjson/writer.h>
 
+#define L_TRACE(...) \
+        logHelper.trace(__VA_ARGS__);
+#define L_DEBUG(...) \
+        logHelper.debug(__VA_ARGS__);
+#define L_INFO(...) \
+        logHelper.info(__VA_ARGS__);
+#define L_WARN(...) \
+        logHelper.warning(__VA_ARGS__);
+#define L_ERROR(...) \
+        logHelper.error(__VA_ARGS__);
+
 static constexpr const char* ENDPOINT_ARRAY = "endpoints";
 
 static std::optional<std::string> readFile(const std::string& path) {
@@ -33,7 +41,7 @@ static std::optional<std::string> readFile(const std::string& path) {
     std::string contents;
     std::ifstream file(path);
     if(!file) {
-        return {};
+        throw celix::rsa::RemoteServicesException{"Cannot open file"};
     }
     file.seekg(0, std::ios::end);
     contents.resize(file.tellg());
@@ -52,83 +60,101 @@ static rapidjson::Document parseJSONFile(std::string& contents)  {
 
 celix::rsa::ConfiguredDiscoveryManager::ConfiguredDiscoveryManager(std::shared_ptr<celix::BundleContext> _ctx) :
         ctx{std::move(_ctx)},
-        configuredDiscoveryFiles{ctx->getConfigProperty(celix::rsa::CONFIGURED_DISCOVERY_DISCOVERY_FILES, "")} {
+        configuredDiscoveryFiles{ctx->getConfigProperty(celix::rsa::CONFIGURED_DISCOVERY_DISCOVERY_FILES, "")},
+        logHelper{ctx, celix::typeName<ConfiguredDiscoveryManager>()}{
     readConfiguredDiscoveryFiles();
 }
 
 void celix::rsa::ConfiguredDiscoveryManager::readConfiguredDiscoveryFiles() {
-    //TODO split configuredDiscoveryFiles
     if (!configuredDiscoveryFiles.empty()) {
-        for (auto path : celix::split(configuredDiscoveryFiles)) {
-            addConfiguredDiscoveryFile(path);
+        for (const auto& path : celix::split(configuredDiscoveryFiles)) {
+            try {
+                addConfiguredDiscoveryFile(path);
+            } catch (celix::rsa::RemoteServicesException& e) {
+                L_ERROR("Error adding disc file %s: %s", path.c_str(), e.what());
+            }
         }
     }
 }
 
-//static std::vector<std::string> parseJSONStringArray(const rapidjson::Value& jsonArray) {
-//    std::vector<std::string> resultVec{};
-//    if (jsonArray.IsArray()) {
-//        resultVec.reserve(jsonArray.Size());
-//        for (auto& element : jsonArray.GetArray()) {
-//            if (element.IsString()) {
-//                resultVec.emplace_back(element.GetString());
-//            }
-//        }
-//    }
-//    return resultVec;
-//}
-
 celix::Properties celix::rsa::ConfiguredDiscoveryManager::convertToEndpointProperties(const rapidjson::Value &endpointJSON) {
     celix::Properties result{};
     result.set(celix::rsa::ENDPOINT_FRAMEWORK_UUID, ctx->getFramework()->getUUID());
     for (auto it = endpointJSON.MemberBegin(); it != endpointJSON.MemberEnd(); ++it) {
-        if (it->value.GetType() == rapidjson::Type::kStringType) {
+        if (it->value.IsString()) {
             if (celix_utils_stringEquals(it->name.GetString(), "endpoint.objectClass")) { //TODO improve
                 result.set(celix::SERVICE_NAME, it->value.GetString());
             } else {
                 result.set(it->name.GetString(), it->value.GetString());
             }
-        } else if (it->value.GetType() == rapidjson::Type::kTrueType || it->value.GetType() == rapidjson::Type::kFalseType) {
+        } else if (it->value.IsBool()) {
             result.set(it->name.GetString(), it->value.GetBool());
+        } else if (it->value.IsArray()) {
+            std::string strArray{};
+            for (const auto& entry : it->value.GetArray()) {
+                if (entry.IsString()) {
+                    strArray.append(entry.GetString());
+                    strArray.append(",");
+                } else {
+                    L_WARN("Cannot parse endpoint member %s. Cannot parse array where the elements are not strings", it->name.GetString());
+                    continue;
+                }
+            }
+            result.set(it->name.GetString(), strArray.substr(0, strArray.size() -1 /*remote last ","*/));
         } else {
-            std::cout << "TODO member " << it->name.GetString() << std::endl;
+            L_WARN("Cannot parse endpoint member %s. Type is %i", it->name.GetString(), (int)it->value.GetType());
         }
     }
     return result;
 }
 
 void celix::rsa::ConfiguredDiscoveryManager::addConfiguredDiscoveryFile(const std::string& path) {
-    std::vector<std::shared_ptr<celix::ServiceRegistration>> newEndpoints{};
-    auto contents = readFile(path);
-    if (contents) {
-        auto parsedJson = parseJSONFile(contents.value());
-        if (parsedJson.IsObject()) {
-            if (parsedJson.HasMember(ENDPOINT_ARRAY) && parsedJson[ENDPOINT_ARRAY].IsArray()) {
-
-                for (auto& jsonEndpoint : parsedJson[ENDPOINT_ARRAY].GetArray()) {
-                    try {
-                        auto endpointProperties = convertToEndpointProperties(jsonEndpoint);
-                        auto endpointDescription = std::make_shared<EndpointDescription>(std::move(endpointProperties));
-
-                        //TODO log service
-                        std::cout << endpointDescription->toString() << std::endl;
-
-                        auto reg = ctx->registerService<celix::rsa::EndpointDescription>(std::move(endpointDescription))
-                                .build();
-                        newEndpoints.emplace_back(std::move(reg));
-                    } catch (celix::rsa::RemoteServicesException& exp) {
-                        //TODO log service
-                        std::cerr << exp.what() << std::endl;
+    try {
+        std::vector<std::shared_ptr<celix::ServiceRegistration>> newEndpoints{};
+        auto contents = readFile(path);
+        if (contents) {
+            auto parsedJson = parseJSONFile(contents.value());
+            if (parsedJson.IsObject()) {
+                if (parsedJson.HasMember(ENDPOINT_ARRAY) && parsedJson[ENDPOINT_ARRAY].IsArray()) {
+
+                    for (auto &jsonEndpoint : parsedJson[ENDPOINT_ARRAY].GetArray()) {
+                        try {
+                            auto endpointProperties = convertToEndpointProperties(jsonEndpoint);
+                            auto endpointDescription = std::make_shared<EndpointDescription>(
+                                    std::move(endpointProperties));
+                            L_TRACE("Created endpoint description from %s: %s", path.c_str(), endpointDescription->toString().c_str())
+
+                            auto reg = ctx->registerService<celix::rsa::EndpointDescription>(
+                                            std::move(endpointDescription))
+                                    .build();
+                            newEndpoints.emplace_back(std::move(reg));
+                        } catch (celix::rsa::RemoteServicesException& e) {
+                            L_ERROR("Error creating EndpointDescription from endpoints entry in JSON from path %s: %s", path.c_str(), e.what());
+                        }
                     }
                 }
             }
+            std::lock_guard lock{mutex};
+            endpointRegistrations.emplace(path, std::move(newEndpoints));
         }
-        std::lock_guard<std::mutex> lock{mutex};
-        endpointRegistrations.emplace(path, std::move(newEndpoints));
+    } catch (std::exception& e) {
+        throw celix::rsa::RemoteServicesException{std::string{"Error adding configured discovery file: "} + e.what()};
+    } catch (...) {
+        throw celix::rsa::RemoteServicesException{"Error adding configured discovery file."};
     }
 }
 
 void celix::rsa::ConfiguredDiscoveryManager::removeConfiguredDiscoveryFile(const std::string& path) {
-    std::lock_guard<std::mutex> lock{mutex};
+    std::lock_guard lock{mutex};
     endpointRegistrations.erase(path);
 }
+
+std::vector<std::string> celix::rsa::ConfiguredDiscoveryManager::getConfiguredDiscoveryFiles() const {
+    std::vector<std::string> result{};
+    std::lock_guard lock{mutex};
+    for (const auto& pair : endpointRegistrations) {
+        result.emplace_back(pair.first);
+    }
+    return result;
+}
+
diff --git a/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.h b/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.h
index 7797471..3bd23c0 100644
--- a/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.h
+++ b/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.h
@@ -18,19 +18,20 @@
  */
 #pragma once
 
-#include "celix/rsa/IEndpointAnnouncer.h"
 
 #include <memory>
 #include <vector>
 #include <string>
 
-#include "celix/rsa/EndpointDescription.h"
-#include "celix/rsa/IConfiguredDiscoveryManager.h"
-#include "celix_api.h"
-
 #include <rapidjson/document.h>
 #include <rapidjson/stringbuffer.h>
 
+#include "celix/rsa/IEndpointAnnouncer.h"
+#include "celix/BundleContext.h"
+#include "celix/LogHelper.h"
+#include "celix/rsa/EndpointDescription.h"
+#include "celix/rsa/IConfiguredDiscoveryManager.h"
+
 /** Path for configured endpoints file. */
 
 namespace celix::rsa {
@@ -48,6 +49,8 @@ public:
      */
     explicit ConfiguredDiscoveryManager(std::shared_ptr<celix::BundleContext> ctx);
 
+    ~ConfiguredDiscoveryManager() noexcept override = default;
+
     void announceEndpoint(std::unique_ptr<EndpointDescription> /*endpoint*/) override {/*nop*/}
 
     void revokeEndpoint(std::unique_ptr<EndpointDescription> /*endpoint*/) override {/*nop*/}
@@ -55,14 +58,17 @@ public:
     void addConfiguredDiscoveryFile(const std::string& path) override;
 
     void removeConfiguredDiscoveryFile(const std::string& path) override;
+
+    std::vector<std::string> getConfiguredDiscoveryFiles() const override;
 private:
     celix::Properties convertToEndpointProperties(const rapidjson::Value &endpointJSON);
     void readConfiguredDiscoveryFiles();
 
     const std::shared_ptr<celix::BundleContext> ctx;
     const std::string configuredDiscoveryFiles;
+    celix::LogHelper logHelper;
 
-    std::mutex mutex{}; //protects below
+    mutable std::mutex mutex{}; //protects below
     std::unordered_map<std::string, std::vector<std::shared_ptr<celix::ServiceRegistration>>> endpointRegistrations{}; //key = configured discovery file path
 };
 
diff --git a/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManagerActivator.cc b/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManagerActivator.cc
index ab61c8b..f24be8d 100644
--- a/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManagerActivator.cc
+++ b/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManagerActivator.cc
@@ -18,7 +18,7 @@
  */
 
 #include "celix/BundleActivator.h"
-#include <ConfiguredDiscoveryManager.h>
+#include "ConfiguredDiscoveryManager.h"
 
 class ConfiguredDiscoveryManagerActivator {
 public:
@@ -26,6 +26,7 @@ public:
         auto &cmp = ctx->getDependencyManager()->createComponent(
                 std::make_unique<celix::rsa::ConfiguredDiscoveryManager>(ctx));
         cmp.addInterface<celix::rsa::IEndpointAnnouncer>();
+        cmp.addInterface<celix::rsa::IConfiguredDiscoveryManager>();
         cmp.build();
     }
 };
diff --git a/bundles/logging/log_helper/CMakeLists.txt b/bundles/logging/log_helper/CMakeLists.txt
index 59b67c8..65d89a9 100644
--- a/bundles/logging/log_helper/CMakeLists.txt
+++ b/bundles/logging/log_helper/CMakeLists.txt
@@ -33,7 +33,7 @@ install(DIRECTORY include/ DESTINATION include/celix/log_helper COMPONENT loggin
 
 if (CELIX_INSTALL_DEPRECATED_API)
 	target_include_directories(log_helper PUBLIC
-		$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include_v2>
+		$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include_v1>
 		$<INSTALL_INTERFACE:include/celix/log_helper>
 	)
 	install(DIRECTORY include_v2/ DESTINATION include/celix/log_helper)
diff --git a/bundles/logging/log_helper/gtest/src/LogHelperTestSuite.cc b/bundles/logging/log_helper/gtest/src/LogHelperTestSuite.cc
index 98623a4..1ba728c 100644
--- a/bundles/logging/log_helper/gtest/src/LogHelperTestSuite.cc
+++ b/bundles/logging/log_helper/gtest/src/LogHelperTestSuite.cc
@@ -20,33 +20,31 @@
 #include <gtest/gtest.h>
 #include <atomic>
 
+#include "celix/FrameworkFactory.h"
+#include "celix/BundleContext.h"
 #include "celix_log_service.h"
 #include "celix_log_constants.h"
-#include "celix_api.h"
 #include "celix_log_helper.h"
+#include "celix/LogHelper.h"
 
 class LogHelperTestSuite : public ::testing::Test {
 public:
     LogHelperTestSuite() {
-        auto* properties = celix_properties_create();
-        celix_properties_set(properties, "org.osgi.framework.storage", ".cacheLogHelperTestSuite");
-        celix_properties_set(properties, CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL_CONFIG_NAME, "debug");
-
-
-        auto* fwPtr = celix_frameworkFactory_createFramework(properties);
-        auto* ctxPtr = celix_framework_getFrameworkContext(fwPtr);
-        fw = std::shared_ptr<celix_framework_t>{fwPtr, [](celix_framework_t* f) {celix_frameworkFactory_destroyFramework(f);}};
-        ctx = std::shared_ptr<celix_bundle_context_t>{ctxPtr, [](celix_bundle_context_t*){/*nop*/}};
+        celix::Properties properties{};
+        properties.set("org.osgi.framework.storage", ".cacheLogHelperTestSuite");
+        properties.set(CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL_CONFIG_NAME, "debug");
+        fw = celix::createFramework(properties);
+        ctx = fw->getFrameworkBundleContext();
     }
 
-    std::shared_ptr<celix_framework_t> fw{nullptr};
-    std::shared_ptr<celix_bundle_context_t> ctx{nullptr};
+    std::shared_ptr<celix::Framework> fw{};
+    std::shared_ptr<celix::BundleContext> ctx{};
 };
 
 
 
 TEST_F(LogHelperTestSuite, LogToStdOut) {
-    auto *helper = celix_logHelper_create(ctx.get(), "test::Log");
+    auto *helper = celix_logHelper_create(ctx->getCBundleContext(), "test::Log");
     EXPECT_EQ(0, celix_logHelper_logCount(helper));
 
     celix_logHelper_trace(helper, "testing %i", 0); //not not active
@@ -61,7 +59,7 @@ TEST_F(LogHelperTestSuite, LogToStdOut) {
 }
 
 TEST_F(LogHelperTestSuite, LogToLogSvc) {
-    auto *helper = celix_logHelper_create(ctx.get(), "test::Log");
+    auto *helper = celix_logHelper_create(ctx->getCBundleContext(), "test::Log");
     EXPECT_EQ(0, celix_logHelper_logCount(helper));
 
     std::atomic<size_t> logCount{0};
@@ -81,7 +79,7 @@ TEST_F(LogHelperTestSuite, LogToLogSvc) {
     opts.serviceVersion = CELIX_LOG_SERVICE_VERSION;
     opts.properties = props;
     opts.svc = (void*)&logSvc;
-    long svcId = celix_bundleContext_registerServiceWithOptions(ctx.get(), &opts);
+    long svcId = celix_bundleContext_registerServiceWithOptions(ctx->getCBundleContext(), &opts);
 
     EXPECT_EQ(0, celix_logHelper_logCount(helper));
     EXPECT_EQ(0, logCount.load());
@@ -96,6 +94,20 @@ TEST_F(LogHelperTestSuite, LogToLogSvc) {
     EXPECT_EQ(6, celix_logHelper_logCount(helper));
     EXPECT_EQ(6, logCount.load());
 
-    celix_bundleContext_unregisterService(ctx.get(), svcId);
+    celix_bundleContext_unregisterService(ctx->getCBundleContext(), svcId);
     celix_logHelper_destroy(helper);
+}
+
+TEST_F(LogHelperTestSuite, CxxLogHelper) {
+    celix::LogHelper helper{ctx, "test name"};
+
+    EXPECT_EQ(0, helper.count());
+
+    helper.trace("testing %i", 0); //not not active
+    helper.debug("testing %i", 1); //not not active
+    helper.info("testing %i", 2); //not not active
+    helper.warning("testing %i", 3); //not not active
+    helper.error("testing %i", 4); //not not active
+    helper.fatal("testing %i", 5); //not not active
+    EXPECT_EQ(5, helper.count());
 }
\ No newline at end of file
diff --git a/bundles/logging/log_helper/include/celix/LogHelper.h b/bundles/logging/log_helper/include/celix/LogHelper.h
new file mode 100644
index 0000000..f4fd4b3
--- /dev/null
+++ b/bundles/logging/log_helper/include/celix/LogHelper.h
@@ -0,0 +1,118 @@
+/**
+ *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.
+ */
+
+#pragma once
+
+#include "celix_log_helper.h"
+
+namespace celix {
+
+    class LogHelper {
+    public:
+        LogHelper(const std::shared_ptr<celix::BundleContext>& ctx, const std::string& logName) : logHelper(createHelper(ctx, logName)) {}
+
+        /**
+         * @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_TRACE level, printf style
+         */
+        void trace(const char *format, ...) {
+            va_list args;
+            va_start(args, format);
+            vlog(CELIX_LOG_LEVEL_TRACE, format, args);
+            va_end(args);
+        }
+        
+        /**
+         * @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_DEBUG level, printf style
+         */
+        void debug(const char *format, ...) {
+            va_list args;
+            va_start(args, format);
+            vlog(CELIX_LOG_LEVEL_DEBUG, format, args);
+            va_end(args);
+        }
+        
+        /**
+         * @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_INFO level, printf style
+         */
+        void info(const char *format, ...) {
+            va_list args;
+            va_start(args, format);
+            vlog(CELIX_LOG_LEVEL_INFO, format, args);
+            va_end(args);
+        }
+        
+        /**
+         * @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_WARNING level, printf style
+         */
+        void warning(const char *format, ...) {
+            va_list args;
+            va_start(args, format);
+            vlog(CELIX_LOG_LEVEL_WARNING, format, args);
+            va_end(args);
+        }
+        
+        /**
+         * @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_ERROR level, printf style
+         */
+        void error(const char *format, ...) {
+            va_list args;
+            va_start(args, format);
+            vlog(CELIX_LOG_LEVEL_ERROR, format, args);
+            va_end(args);
+        }
+        
+        /**
+         * @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_FATAL level, printf style
+         */
+        void fatal(const char *format, ...) {
+            va_list args;
+            va_start(args, format);
+            vlog(CELIX_LOG_LEVEL_FATAL, format, args);
+            va_end(args);
+        }
+
+        /**
+         * @brief Logs a message to the log_helper using a format string and a va_list argument (vprintf style).
+         *
+         * Silently ignores log level CELIX_LOG_LEVEL_DISABLED.
+         */
+        void vlog(celix_log_level_e level, const char *format, va_list formatArgs) {
+            celix_logHelper_vlog(logHelper.get(), level, format, formatArgs);
+        }
+
+        /**
+         * @brief nr of times a helper log function has been called.
+         */
+        std::size_t count() const {
+            return celix_logHelper_logCount(logHelper.get());
+        }
+
+    private:
+        std::shared_ptr<celix_log_helper> createHelper(const std::shared_ptr<celix::BundleContext>& ctx, const std::string& logName) {
+            return std::shared_ptr<celix_log_helper>{
+                celix_logHelper_create(ctx->getCBundleContext(), logName.c_str()),
+                [](celix_log_helper* lh) {celix_logHelper_destroy(lh);}
+            };
+        }
+
+        const std::shared_ptr<celix_log_helper> logHelper;
+    };
+
+
+}
diff --git a/bundles/logging/log_helper/include/celix_log_helper.h b/bundles/logging/log_helper/include/celix_log_helper.h
index d40d5e4..bd17059 100644
--- a/bundles/logging/log_helper/include/celix_log_helper.h
+++ b/bundles/logging/log_helper/include/celix_log_helper.h
@@ -36,43 +36,45 @@ celix_log_helper_t* celix_logHelper_create(celix_bundle_context_t* ctx, const ch
 void celix_logHelper_destroy(celix_log_helper_t* logHelper);
 
 /**
- * Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_TRACE level, printf style
+ * @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_TRACE level, printf style
  */
 void celix_logHelper_trace(celix_log_helper_t* logHelper, const char *format, ...);
 
 /**
- * Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_DEBUG level, printf style
+ * @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_DEBUG level, printf style
  */
 void celix_logHelper_debug(celix_log_helper_t* logHelper, const char *format, ...);
 
 /**
- * Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_INFO level, printf style
+ * @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_INFO level, printf style
  */
 void celix_logHelper_info(celix_log_helper_t* logHelper, const char *format, ...);
 
 /**
- * Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_WARNING level, printf style
+ * @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_WARNING level, printf style
  */
 void celix_logHelper_warning(celix_log_helper_t* logHelper, const char *format, ...);
 
 /**
- * Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_ERROR level, printf style
+ * @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_ERROR level, printf style
  */
 void celix_logHelper_error(celix_log_helper_t* logHelper, const char *format, ...);
 
 /**
- * Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_FATAL level, printf style
+ * @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_FATAL level, printf style
  */
 void celix_logHelper_fatal(celix_log_helper_t* logHelper, const char *format, ...);
 
 /**
- * Logs a message using the provided celix log level to the log_helper, printf style.
+ * @brief Logs a message using the provided celix log level to the log_helper, printf style.
+ *
  * Silently ignores log level CELIX_LOG_LEVEL_DISABLED.
  */
 void celix_logHelper_log(celix_log_helper_t* logHelper, celix_log_level_e level, const char *format, ...);
 
 /**
- * Logs a detailed message using the provided celix log level to the log_helper, printf style.
+ * @brief Logs a detailed message using the provided celix log level to the log_helper, printf style.
+ *
  * Silently ignores log level CELIX_LOG_LEVEL_DISABLED.
  *
  * The file, function and line arguments are expected to be called with the values:
@@ -84,13 +86,15 @@ void celix_logHelper_log(celix_log_helper_t* logHelper, celix_log_level_e level,
 void celix_logHelper_logDetails(celix_log_helper_t* logHelper, celix_log_level_e level, const char* file, const char* function, int line, const char *format, ...);
 
 /**
- * Logs a message to the log_helper using a format string and a va_list argument (vprintf style).
+ * @brief Logs a message to the log_helper using a format string and a va_list argument (vprintf style).
+ *
  * Silently ignores log level CELIX_LOG_LEVEL_DISABLED.
  */
 void celix_logHelper_vlog(celix_log_helper_t* logHelper, celix_log_level_e level, const char *format, va_list formatArgs);
 
 /**
- * Logs a detailed message to log_helper using a format string and a va_list argument (vprintf style).
+ * @brief Logs a detailed message to log_helper using a format string and a va_list argument (vprintf style).
+ *
  * Silently ignores log level CELIX_LOG_LEVEL_DISABLED.
  *
  * The file, function and line arguments are expected to be called with the values:
@@ -102,7 +106,7 @@ void celix_logHelper_vlog(celix_log_helper_t* logHelper, celix_log_level_e level
 void celix_logHelper_vlogDetails(celix_log_helper_t* logHelper, celix_log_level_e level, const char* file, const char* function, int line, const char *format, va_list formatArgs);
 
 /**
- * Returns the nr of time a helper log function has been called.
+ * @brief nr of times a helper log function has been called.
  */
 size_t celix_logHelper_logCount(celix_log_helper_t* logHelper);
 
diff --git a/bundles/logging/log_helper/include_v2/log_helper.h b/bundles/logging/log_helper/include_v1/log_helper.h
similarity index 100%
rename from bundles/logging/log_helper/include_v2/log_helper.h
rename to bundles/logging/log_helper/include_v1/log_helper.h