http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/unit/LoggerTests.cpp ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/LoggerTests.cpp b/libminifi/test/unit/LoggerTests.cpp index 9139be2..5f87fe6 100644 --- a/libminifi/test/unit/LoggerTests.cpp +++ b/libminifi/test/unit/LoggerTests.cpp @@ -21,342 +21,71 @@ #include <memory> #include <ctime> #include "../TestBase.h" -#include "core/logging/LogAppenders.h" - -bool contains(std::string stringA, std::string ending) { - return (ending.length() > 0 && stringA.find(ending) != std::string::npos); -} TEST_CASE("Test log Levels", "[ttl1]") { - std::ostringstream oss; - - std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::OutputStreamAppender(oss, - 0)); - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - logger->updateLogger(std::move(outputLogger)); - logger->setLogLevel("trace"); - logger->log_info("hello world"); + LogTestController::getInstance().setTrace<logging::Logger>(); + std::shared_ptr<logging::Logger> logger = logging::LoggerFactory<logging::Logger>::getLogger(); + logger->log_info("hello %s", "world"); REQUIRE( - true == contains(oss.str(), "[minifi log -- org::apache::nifi::minifi::core::logging::OutputStreamAppender] [info] hello world")); - - std::unique_ptr<logging::BaseLogger> nullAppender = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::NullAppender()); - - logger->updateLogger(std::move(nullAppender)); + true + == LogTestController::getInstance().contains( + "[org::apache::nifi::minifi::core::logging::Logger] [info] hello world")); + LogTestController::getInstance().reset(); } TEST_CASE("Test log Levels debug", "[ttl2]") { - std::ostringstream oss; - - std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::OutputStreamAppender(oss, - 0)); - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - logger->updateLogger(std::move(outputLogger)); - logger->setLogLevel("trace"); - logger->log_debug("hello world"); + LogTestController::getInstance().setTrace<logging::Logger>(); + std::shared_ptr<logging::Logger> logger = logging::LoggerFactory<logging::Logger>::getLogger(); + logger->log_debug("hello %s", "world"); REQUIRE( - true == contains(oss.str(), "[minifi log -- org::apache::nifi::minifi::core::logging::OutputStreamAppender] [debug] hello world")); - - std::unique_ptr<logging::BaseLogger> nullAppender = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::NullAppender()); - - logger->updateLogger(std::move(nullAppender)); + true + == LogTestController::getInstance().contains( + "[org::apache::nifi::minifi::core::logging::Logger] [debug] hello world")); + LogTestController::getInstance().reset(); } TEST_CASE("Test log Levels trace", "[ttl3]") { - std::ostringstream oss; - - std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::OutputStreamAppender(oss, - 0)); - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - logger->updateLogger(std::move(outputLogger)); - logger->setLogLevel("trace"); - - logger->log_trace("hello world"); + LogTestController::getInstance().setTrace<logging::Logger>(); + std::shared_ptr<logging::Logger> logger = logging::LoggerFactory<logging::Logger>::getLogger(); + logger->log_trace("hello %s", "world"); REQUIRE( - true == contains(oss.str(), "[minifi log -- org::apache::nifi::minifi::core::logging::OutputStreamAppender] [trace] hello world")); - - std::unique_ptr<logging::BaseLogger> nullAppender = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::NullAppender()); - - logger->updateLogger(std::move(nullAppender)); + true + == LogTestController::getInstance().contains( + "[org::apache::nifi::minifi::core::logging::Logger] [trace] hello world")); + LogTestController::getInstance().reset(); } TEST_CASE("Test log Levels error", "[ttl4]") { - std::ostringstream oss; - - std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::OutputStreamAppender(oss, - 0)); - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - logger->updateLogger(std::move(outputLogger)); - logger->setLogLevel("trace"); - - logger->log_error("hello world"); + LogTestController::getInstance().setTrace<logging::Logger>(); + std::shared_ptr<logging::Logger> logger = logging::LoggerFactory<logging::Logger>::getLogger(); + logger->log_error("hello %s", "world"); REQUIRE( - true == contains(oss.str(), "[minifi log -- org::apache::nifi::minifi::core::logging::OutputStreamAppender] [error] hello world")); - - std::unique_ptr<logging::BaseLogger> nullAppender = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::NullAppender()); - - logger->updateLogger(std::move(nullAppender)); + true + == LogTestController::getInstance().contains( + "[org::apache::nifi::minifi::core::logging::Logger] [error] hello world")); + LogTestController::getInstance().reset(); } TEST_CASE("Test log Levels change", "[ttl5]") { - std::ostringstream oss; - - std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::OutputStreamAppender(oss, - 0)); - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - logger->updateLogger(std::move(outputLogger)); - logger->setLogLevel("trace"); - - logger->log_error("hello world"); - - REQUIRE( - true == contains(oss.str(), "[minifi log -- org::apache::nifi::minifi::core::logging::OutputStreamAppender] [error] hello world")); - oss.str(""); - oss.clear(); - REQUIRE(0 == oss.str().length()); - logger->setLogLevel("off"); - - logger->log_error("hello world"); - - REQUIRE(0 == oss.str().length()); - - std::unique_ptr<logging::BaseLogger> nullAppender = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::NullAppender()); - - logger->updateLogger(std::move(nullAppender)); -} - -TEST_CASE("Test log LevelsConfigured", "[ttl6]") { - std::ostringstream oss; - - std::shared_ptr<minifi::Configure> config = - std::make_shared<minifi::Configure>(); - - config->set(logging::BaseLogger::nifi_log_appender, "OutputStreamAppender"); - config->set( - org::apache::nifi::minifi::core::logging::OutputStreamAppender::nifi_log_output_stream_error_stderr, - "true"); - - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - - auto oldrdbuf = std::cerr.rdbuf(); - std::cerr.rdbuf(oss.rdbuf()); - - std::unique_ptr<logging::BaseLogger> newLogger = - logging::LogInstance::getConfiguredLogger(config); - - logger->updateLogger(std::move(newLogger)); - - logger->setLogLevel("trace"); - - // capture stderr - logger->log_error("hello world"); - - REQUIRE( - true == contains(oss.str(), "[minifi log -- org::apache::nifi::minifi::core::logging::OutputStreamAppender] [error] hello world")); - - std::cerr.rdbuf(oldrdbuf); - - config->set(logging::BaseLogger::nifi_log_appender, "nullappender"); - - newLogger = logging::LogInstance::getConfiguredLogger(config); - - logger->updateLogger(std::move(newLogger)); - - oss.str(""); - oss.clear(); - REQUIRE(0 == oss.str().length()); - - // should have nothing from the null appender - logger->log_info("hello world"); - logger->log_debug("hello world"); - logger->log_trace("hello world"); - - REQUIRE(0 == oss.str().length()); -} - -TEST_CASE("Test log Levels With std::string", "[ttl1]") { - std::ostringstream oss; - - std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::OutputStreamAppender(oss, - 0)); - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - logger->updateLogger(std::move(outputLogger)); - logger->setLogLevel("trace"); - std::string world = "world"; - logger->log_error("hello %s", world); - - REQUIRE( - true == contains(oss.str(), "[minifi log -- org::apache::nifi::minifi::core::logging::OutputStreamAppender] [error] hello world")); - oss.str(""); - oss.clear(); - REQUIRE(0 == oss.str().length()); - logger->setLogLevel("off"); - - logger->log_error("hello world"); - - REQUIRE(0 == oss.str().length()); - - std::unique_ptr<logging::BaseLogger> nullAppender = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::NullAppender()); - - logger->updateLogger(std::move(nullAppender)); -} - -TEST_CASE("Test log Levels debug With std::string ", "[ttl2]") { - std::ostringstream oss; - - std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::OutputStreamAppender(oss, - 0)); - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - logger->updateLogger(std::move(outputLogger)); - logger->setLogLevel("trace"); - std::string world = "world"; - logger->log_debug("hello %s", world); - - REQUIRE( - true == contains(oss.str(), "[minifi log -- org::apache::nifi::minifi::core::logging::OutputStreamAppender] [debug] hello world")); - - std::unique_ptr<logging::BaseLogger> nullAppender = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::NullAppender()); - - logger->updateLogger(std::move(nullAppender)); -} - -TEST_CASE("Test log Levels trace With std::string", "[ttl3]") { - std::ostringstream oss; - - std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::OutputStreamAppender(oss, - 0)); - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - logger->updateLogger(std::move(outputLogger)); - logger->setLogLevel("trace"); - std::string world = "world"; - logger->log_trace("hello %s", world); - - REQUIRE( - true == contains(oss.str(), "[minifi log -- org::apache::nifi::minifi::core::logging::OutputStreamAppender] [trace] hello world")); - - std::unique_ptr<logging::BaseLogger> nullAppender = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::NullAppender()); - - logger->updateLogger(std::move(nullAppender)); -} - -TEST_CASE("Test log Levels error With std::string ", "[ttl4]") { - std::ostringstream oss; - - std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::OutputStreamAppender(oss, - 0)); - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - logger->updateLogger(std::move(outputLogger)); - logger->setLogLevel("trace"); - - std::string world = "world"; - logger->log_error("hello %s", world); - - REQUIRE( - true == contains(oss.str(), "[minifi log -- org::apache::nifi::minifi::core::logging::OutputStreamAppender] [error] hello world")); - - std::unique_ptr<logging::BaseLogger> nullAppender = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::NullAppender()); - - logger->updateLogger(std::move(nullAppender)); -} - -TEST_CASE("Test log Levels change With std::string ", "[ttl5]") { - std::ostringstream oss; - - std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::OutputStreamAppender(oss, - 0)); - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - logger->updateLogger(std::move(outputLogger)); - logger->setLogLevel("trace"); - - std::string world = "world"; - logger->log_error("hello %s", world); - - REQUIRE( - true == contains(oss.str(), "[minifi log -- org::apache::nifi::minifi::core::logging::OutputStreamAppender] [error] hello world")); - oss.str(""); - oss.clear(); - REQUIRE(0 == oss.str().length()); - logger->setLogLevel("off"); - - logger->log_error("hello %s", world); - - REQUIRE(0 == oss.str().length()); - - std::unique_ptr<logging::BaseLogger> nullAppender = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::NullAppender()); - - logger->updateLogger(std::move(nullAppender)); -} - -TEST_CASE("Test log Levels change With std::string maybe ", "[ttl5]") { - std::ostringstream oss; - - std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::OutputStreamAppender(oss, - 0)); - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - logger->updateLogger(std::move(outputLogger)); - logger->setLogLevel("trace"); - + LogTestController::getInstance().setTrace<logging::Logger>(); + std::shared_ptr<logging::Logger> logger = logging::LoggerFactory<logging::Logger>::getLogger(); logger->log_error("hello %s", "world"); REQUIRE( - true == contains(oss.str(), "[minifi log -- org::apache::nifi::minifi::core::logging::OutputStreamAppender] [error] hello world")); - oss.str(""); - oss.clear(); - REQUIRE(0 == oss.str().length()); - logger->setLogLevel("off"); - + true + == LogTestController::getInstance().contains( + "[org::apache::nifi::minifi::core::logging::Logger] [error] hello world")); + LogTestController::getInstance().reset(); + LogTestController::getInstance().setOff<logging::Logger>(); logger->log_error("hello %s", "world"); - REQUIRE(0 == oss.str().length()); - - std::unique_ptr<logging::BaseLogger> nullAppender = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::NullAppender()); - - logger->updateLogger(std::move(nullAppender)); + REQUIRE( + false + == LogTestController::getInstance().contains( + "[org::apache::nifi::minifi::core::logging::Logger] [error] hello world")); + LogTestController::getInstance().reset(); }
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/unit/ProcessorTests.cpp ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/ProcessorTests.cpp b/libminifi/test/unit/ProcessorTests.cpp index 82f9cae..491ca8f 100644 --- a/libminifi/test/unit/ProcessorTests.cpp +++ b/libminifi/test/unit/ProcessorTests.cpp @@ -25,8 +25,6 @@ #include <fstream> #include "../unit/ProvenanceTestHelper.h" #include "../TestBase.h" -#include "core/logging/LogAppenders.h" -#include "core/logging/BaseLogger.h" #include "processors/ListenHTTP.h" #include "processors/LogAttribute.h" #include "processors/GetFile.h" @@ -39,6 +37,7 @@ #include "core/reporting/SiteToSiteProvenanceReportingTask.h" TEST_CASE("Test Creation of GetFile", "[getfileCreate]") { + TestController testController; std::shared_ptr<core::Processor> processor = std::make_shared< org::apache::nifi::minifi::processors::GetFile>("processorname"); REQUIRE(processor->getName() == "processorname"); @@ -47,8 +46,6 @@ TEST_CASE("Test Creation of GetFile", "[getfileCreate]") { TEST_CASE("Test Find file", "[getfileCreate2]") { TestController testController; - testController.enableDebug(); - std::shared_ptr<core::Processor> processor = std::make_shared< org::apache::nifi::minifi::processors::GetFile>("getfileCreate2"); @@ -187,8 +184,6 @@ TEST_CASE("Test Find file", "[getfileCreate2]") { TEST_CASE("Test GetFileLikeIt'sThreaded", "[getfileCreate3]") { TestController testController; - testController.enableDebug(); - std::shared_ptr<core::Processor> processor = std::make_shared< org::apache::nifi::minifi::processors::GetFile>("getfileCreate2"); @@ -275,17 +270,8 @@ TEST_CASE("Test GetFileLikeIt'sThreaded", "[getfileCreate3]") { } TEST_CASE("LogAttributeTest", "[getfileCreate3]") { - std::ostringstream oss; - std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::OutputStreamAppender(oss, - 0)); - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - logger->updateLogger(std::move(outputLogger)); - TestController testController; - - testController.enableDebug(); + LogTestController::getInstance().setDebug<minifi::processors::LogAttribute>(); std::shared_ptr<core::Repository> repo = std::make_shared<TestRepository>(); @@ -376,8 +362,6 @@ TEST_CASE("LogAttributeTest", "[getfileCreate3]") { records = reporter->getEvents(); session.commit(); - oss.str(""); - oss.clear(); logAttribute->incrementActiveTasks(); logAttribute->setScheduledState(core::ScheduledState::RUNNING); @@ -385,18 +369,10 @@ TEST_CASE("LogAttributeTest", "[getfileCreate3]") { records = reporter->getEvents(); - std::string log_attribute_output = oss.str(); - REQUIRE( - log_attribute_output.find("key:absolute.path value:" + ss.str()) - != std::string::npos); - REQUIRE(log_attribute_output.find("Size:8 Offset:0") != std::string::npos); - REQUIRE( - log_attribute_output.find("key:path value:" + std::string(dir)) - != std::string::npos); - - outputLogger = std::unique_ptr<logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::NullAppender()); - logger->updateLogger(std::move(outputLogger)); + REQUIRE(true == LogTestController::getInstance().contains("key:absolute.path value:" + ss.str())); + REQUIRE(true == LogTestController::getInstance().contains("Size:8 Offset:0")); + REQUIRE(true == LogTestController::getInstance().contains("key:path value:" + std::string(dir))); + LogTestController::getInstance().reset(); } int fileSize(const char *add) { http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/unit/RepoTests.cpp ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/RepoTests.cpp b/libminifi/test/unit/RepoTests.cpp index 9d22030..34b1f35 100644 --- a/libminifi/test/unit/RepoTests.cpp +++ b/libminifi/test/unit/RepoTests.cpp @@ -43,8 +43,6 @@ TEST_CASE("Test Repo Empty Value Attribute", "[TestFFR1]") { REQUIRE(true == record.Serialize()); repository->stop(); - - testController.setNullAppender(); } TEST_CASE("Test Repo Empty Key Attribute ", "[TestFFR2]") { @@ -66,8 +64,6 @@ TEST_CASE("Test Repo Empty Key Attribute ", "[TestFFR2]") { REQUIRE(true == record.Serialize()); repository->stop(); - - testController.setNullAppender(); } TEST_CASE("Test Repo Key Attribute Verify ", "[TestFFR3]") { http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/unit/SerializationTests.cpp ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/SerializationTests.cpp b/libminifi/test/unit/SerializationTests.cpp index 1946a92..a66376d 100644 --- a/libminifi/test/unit/SerializationTests.cpp +++ b/libminifi/test/unit/SerializationTests.cpp @@ -20,8 +20,7 @@ #include "Site2SitePeer.h" #include "Site2SiteClientProtocol.h" #include <uuid/uuid.h> -#include "core/logging/LogAppenders.h" -#include "core/logging/BaseLogger.h" +#include "SiteToSiteHelper.h" #include <algorithm> #include <string> #include <memory> http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/unit/Site2SiteTests.cpp ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/Site2SiteTests.cpp b/libminifi/test/unit/Site2SiteTests.cpp index 4ccf012..18878ad 100644 --- a/libminifi/test/unit/Site2SiteTests.cpp +++ b/libminifi/test/unit/Site2SiteTests.cpp @@ -25,8 +25,6 @@ #include "io/BaseStream.h" #include "Site2SitePeer.h" #include "Site2SiteClientProtocol.h" -#include "core/logging/LogAppenders.h" -#include "core/logging/BaseLogger.h" #include <algorithm> #include "../TestBase.h" #include "../unit/SiteToSiteHelper.h" @@ -100,15 +98,6 @@ void sunny_path_bootstrap(SiteToSiteResponder *collector) { } TEST_CASE("TestSiteToSiteVerifySend", "[S2S3]") { - std::ostringstream oss; - - std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr< - logging::BaseLogger>( - new org::apache::nifi::minifi::core::logging::OutputStreamAppender( - std::cout, std::make_shared<minifi::Configure>())); - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - logger->updateLogger(std::move(outputLogger)); - logger->setLogLevel("trace"); SiteToSiteResponder *collector = new SiteToSiteResponder(); sunny_path_bootstrap(collector); http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/unit/StringUtilsTests.cpp ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/StringUtilsTests.cpp b/libminifi/test/unit/StringUtilsTests.cpp new file mode 100644 index 0000000..7c78c98 --- /dev/null +++ b/libminifi/test/unit/StringUtilsTests.cpp @@ -0,0 +1,46 @@ +/** + * + * 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. + */ + +#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file +#include <string> +#include <vector> + +#include "../TestBase.h" +#include "core/Core.h" +#include "utils/StringUtils.h" + +TEST_CASE("TestStringUtils::split", "[test split no delimiter]") { + std::vector<std::string> expected = {"hello"}; + REQUIRE(expected == org::apache::nifi::minifi::utils::StringUtils::split("hello", ",")); +} + +TEST_CASE("TestStringUtils::split2", "[test split single delimiter]") { + std::vector<std::string> expected = {"hello", "world"}; + REQUIRE(expected == org::apache::nifi::minifi::utils::StringUtils::split("hello world", " ")); +} + +TEST_CASE("TestStringUtils::split3", "[test split multiple delimiter]") { + std::vector<std::string> expected = {"hello", "world", "I'm", "a", "unit", "test"}; + REQUIRE(expected == org::apache::nifi::minifi::utils::StringUtils::split("hello world I'm a unit test", " ")); +} + +TEST_CASE("TestStringUtils::split4", "[test split classname]") { + std::vector<std::string> expected = {"org", "apache", "nifi", "minifi", "utils", "StringUtils"}; + REQUIRE(expected == org::apache::nifi::minifi::utils::StringUtils::split( + org::apache::nifi::minifi::core::getClassName<org::apache::nifi::minifi::utils::StringUtils>(), "::")); +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/unit/YamlConfigurationTests.cpp ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/YamlConfigurationTests.cpp b/libminifi/test/unit/YamlConfigurationTests.cpp index a7ed5df..76ddcac 100644 --- a/libminifi/test/unit/YamlConfigurationTests.cpp +++ b/libminifi/test/unit/YamlConfigurationTests.cpp @@ -25,6 +25,8 @@ #include "../TestBase.h" TEST_CASE("Test YAML Config Processing", "[YamlConfiguration]") { + TestController test_controller; + std::shared_ptr<core::Repository> testProvRepo = core::createRepository( "provenancerepository", true); std::shared_ptr<core::Repository> testFlowFileRepo = core::createRepository( http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/main/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index f7f16e7..93f5396 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -23,7 +23,7 @@ IF(POLICY CMP0048) CMAKE_POLICY(SET CMP0048 OLD) ENDIF(POLICY CMP0048) -include_directories(../include ../libminifi/include ../libminifi/include/core/yaml ../libminifi/include/core ../thirdparty/concurrentqueue ../thirdparty/yaml-cpp-yaml-cpp-0.5.3/include ../thirdparty/civetweb-1.9.1/include ../thirdparty/jsoncpp/include ../thirdparty/leveldb-1.18/include ../thirdparty/) +include_directories(../libminifi/include ../libminifi/include/core/yaml ../libminifi/include/core ../thirdparty/spdlog-0.13.0/include ../thirdparty/concurrentqueue ../thirdparty/yaml-cpp-yaml-cpp-0.5.3/include ../thirdparty/civetweb-1.9.1/include ../thirdparty/jsoncpp/include ../thirdparty/leveldb-1.18/include ../thirdparty/) find_package(Boost REQUIRED) include_directories(${Boost_INCLUDE_DIRS}) http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/main/MiNiFiMain.cpp ---------------------------------------------------------------------- diff --git a/main/MiNiFiMain.cpp b/main/MiNiFiMain.cpp index 5944ff2..297313d 100644 --- a/main/MiNiFiMain.cpp +++ b/main/MiNiFiMain.cpp @@ -30,13 +30,13 @@ #include "core/Core.h" -#include "core/logging/BaseLogger.h" -#include "core/logging/LogAppenders.h" #include "spdlog/spdlog.h" #include "core/FlowConfiguration.h" #include "core/ConfigurationFactory.h" #include "core/RepositoryFactory.h" #include "core/logging/Logger.h" +#include "core/logging/LoggerConfiguration.h" +#include "properties/Properties.h" #include "properties/Configure.h" #include "FlowController.h" @@ -48,6 +48,8 @@ #define DEFAULT_NIFI_CONFIG_YML "./conf/config.yml" //! Default nifi properties file path #define DEFAULT_NIFI_PROPERTIES_FILE "./conf/minifi.properties" + +#define DEFAULT_LOG_PROPERTIES_FILE "./conf/minifi-log.properties" //! Define home environment variable #define MINIFI_HOME_ENV_KEY "MINIFI_HOME" @@ -79,9 +81,7 @@ void sigHandler(int signal) { } int main(int argc, char **argv) { - std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger(); - - logger->setLogLevel(logging::info); + std::shared_ptr<logging::Logger> logger = logging::LoggerConfiguration::getConfiguration().getLogger("main"); uint16_t stop_wait_time = STOP_WAIT_TIME_MS; @@ -100,9 +100,9 @@ int main(int argc, char **argv) { std::string minifiHome; if (const char* env_p = std::getenv(MINIFI_HOME_ENV_KEY)) { minifiHome = env_p; + logger->log_info("MINIFI_HOME=%s", minifiHome); } else { - logger->log_info( - "MINIFI_HOME was not found, determining based on executable path."); + logger->log_info("MINIFI_HOME was not found, determining based on executable path."); char *path = NULL; char full_path[PATH_MAX]; path = realpath(argv[0], full_path); @@ -119,6 +119,14 @@ int main(int argc, char **argv) { return -1; } + std::shared_ptr<logging::LoggerProperties> log_properties = std::make_shared<logging::LoggerProperties>(); + log_properties->setHome(minifiHome); + log_properties->loadConfigureFile(DEFAULT_LOG_PROPERTIES_FILE); + logging::LoggerConfiguration::getConfiguration().initialize(log_properties); + + // Make a record of minifi home in the configured log file. + logger->log_info("MINIFI_HOME=%s", minifiHome); + std::shared_ptr<minifi::Configure> configure = std::make_shared<minifi::Configure>(); configure->setHome(minifiHome); configure->loadConfigureFile(DEFAULT_NIFI_PROPERTIES_FILE); @@ -142,18 +150,6 @@ int main(int argc, char **argv) { STOP_WAIT_TIME_MS); } - std::string log_level; - if (configure->get(minifi::Configure::nifi_log_level, - log_level)) { - logger->setLogLevel(log_level); - } - - // set the log configuration. - std::unique_ptr<logging::BaseLogger> configured_logger = - logging::LogInstance::getConfiguredLogger(configure); - - logger->updateLogger(std::move(configured_logger)); - configure->get(minifi::Configure::nifi_provenance_repository_class_name, prov_repo_class); // Create repos for flow record and provenance http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/.gitignore ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/.gitignore b/thirdparty/spdlog-0.13.0/.gitignore new file mode 100644 index 0000000..b51a05b --- /dev/null +++ b/thirdparty/spdlog-0.13.0/.gitignore @@ -0,0 +1,64 @@ +# Auto generated files +*.slo +*.lo +*.o +*.obj +*.suo +*.tlog +*.ilk +*.log +*.pdb +*.idb +*.iobj +*.ipdb +*.opensdf +*.sdf + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# Codelite +.codelite + +# .orig files +*.orig + +# example files +example/* +!example/example.cpp +!example/bench.cpp +!example/utils.h +!example/Makefile* +!example/example.sln +!example/example.vcxproj +!example/CMakeLists.txt +!example/multisink.cpp +!example/jni + +# generated files +generated + +# Cmake +CMakeCache.txt +CMakeFiles +CMakeScripts +Makefile +cmake_install.cmake +install_manifest.txt +/tests/tests.VC.VC.opendb +/tests/tests.VC.db +/tests/tests +/tests/logs/file_helper_test.txt http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/CMakeLists.txt b/thirdparty/spdlog-0.13.0/CMakeLists.txt new file mode 100644 index 0000000..61c45b5 --- /dev/null +++ b/thirdparty/spdlog-0.13.0/CMakeLists.txt @@ -0,0 +1,87 @@ +# +# Copyright(c) 2015 Ruslan Baratov. +# Distributed under the MIT License (http://opensource.org/licenses/MIT) +# + +cmake_minimum_required(VERSION 3.1) +project(spdlog VERSION 1.0.0) +include(CTest) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + set(CMAKE_CXX_FLAGS "-Wall ${CMAKE_CXX_FLAGS}") +endif() + +add_library(spdlog INTERFACE) + +option(SPDLOG_BUILD_EXAMPLES "Build examples" OFF) +option(SPDLOG_BUILD_TESTING "Build spdlog tests" ON) + +target_include_directories( + spdlog + INTERFACE + "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>" + "$<INSTALL_INTERFACE:include>" +) + +set(HEADER_BASE "${CMAKE_CURRENT_SOURCE_DIR}/include") + +if(SPDLOG_BUILD_EXAMPLES) + add_subdirectory(example) +endif() + +if(SPDLOG_BUILD_TESTING) + add_subdirectory(tests) +endif() + +### Install ### +# * https://github.com/forexample/package-example +set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated") + +set(config_install_dir "lib/cmake/${PROJECT_NAME}") +set(include_install_dir "include") +set(pkgconfig_install_dir "lib/pkgconfig") + +set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake") +set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake") +set(pkg_config "${generated_dir}/${PROJECT_NAME}.pc") +set(targets_export_name "${PROJECT_NAME}Targets") +set(namespace "${PROJECT_NAME}::") + +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + "${version_config}" COMPATIBILITY SameMajorVersion +) + +# Note: use 'targets_export_name' +configure_file("cmake/Config.cmake.in" "${project_config}" @ONLY) +configure_file("cmake/spdlog.pc.in" "${pkg_config}" @ONLY) + +install( + TARGETS spdlog + EXPORT "${targets_export_name}" + INCLUDES DESTINATION "${include_install_dir}" +) + +install(DIRECTORY "include/spdlog" DESTINATION "${include_install_dir}") + +install( + FILES "${project_config}" "${version_config}" + DESTINATION "${config_install_dir}" +) + +install( + FILES "${pkg_config}" + DESTINATION "${pkgconfig_install_dir}" +) + +install( + EXPORT "${targets_export_name}" + NAMESPACE "${namespace}" + DESTINATION "${config_install_dir}" +) + +file(GLOB_RECURSE spdlog_include_SRCS "${HEADER_BASE}/*.h") +add_custom_target(spdlog_headers_for_ide SOURCES ${spdlog_include_SRCS}) http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/INSTALL ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/INSTALL b/thirdparty/spdlog-0.13.0/INSTALL new file mode 100644 index 0000000..664509d --- /dev/null +++ b/thirdparty/spdlog-0.13.0/INSTALL @@ -0,0 +1,13 @@ +spdlog is header only library. +Just copy the files to your build tree and use a C++11 compiler + +Tested on: +gcc 4.8.1 and above +clang 3.5 +Visual Studio 2013 + +gcc 4.8 flags: --std==c++11 -pthread -O3 -flto -Wl,--no-as-needed +gcc 4.9 flags: --std=c++11 -pthread -O3 -flto + + +see the makefile in the example folder http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/LICENSE ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/LICENSE b/thirdparty/spdlog-0.13.0/LICENSE new file mode 100644 index 0000000..4b43e06 --- /dev/null +++ b/thirdparty/spdlog-0.13.0/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2016 Gabi Melman. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/README.md ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/README.md b/thirdparty/spdlog-0.13.0/README.md new file mode 100644 index 0000000..f5e5fe3 --- /dev/null +++ b/thirdparty/spdlog-0.13.0/README.md @@ -0,0 +1,218 @@ +# spdlog + +Very fast, header only, C++ logging library. [](https://travis-ci.org/gabime/spdlog) [](https://ci.appveyor.com/project/gabime/spdlog) + + +## Install +#### Just copy the headers: + +* Copy the source [folder](https://github.com/gabime/spdlog/tree/master/include/spdlog) to your build tree and use a C++11 compiler. + +#### Or use your favourite package manager: + +* Ubuntu: `apt-get install libspdlog-dev` +* Homebrew: `brew install spdlog` +* FreeBSD: `cd /usr/ports/devel/spdlog/ && make install clean` +* Fedora: `yum install spdlog` +* Arch Linux: `pacman -S spdlog-git` +* vcpkg: `vcpkg install spdlog` + + +## Platforms + * Linux, FreeBSD, Solaris + * Windows (vc 2013+, cygwin/mingw) + * Mac OSX (clang 3.5+) + * Android + +## Features +* Very fast - performance is the primary goal (see [benchmarks](#benchmarks) below). +* Headers only, just copy and use. +* Feature rich [call style](#usage-example) using the excellent [fmt](https://github.com/fmtlib/fmt) library. +* Extremely fast asynchronous mode (optional) - using lockfree queues and other tricks to reach millions of calls/sec. +* [Custom](https://github.com/gabime/spdlog/wiki/3.-Custom-formatting) formatting. +* Multi/Single threaded loggers. +* Various log targets: + * Rotating log files. + * Daily log files. + * Console logging (colors supported). + * syslog. + * Windows debugger (```OutputDebugString(..)```) + * Easily extendable with custom log targets (just implement a single function in the [sink](include/spdlog/sinks/sink.h) interface). +* Severity based filtering - threshold levels can be modified in runtime as well as in compile time. + + + +## Benchmarks + +Below are some [benchmarks](bench) comparing popular log libraries under Ubuntu 64 bit, Intel i7-4770 CPU @ 3.40GHz + +#### Synchronous mode +Time needed to log 1,000,000 lines in synchronous mode (in seconds, the best of 3 runs): + +|threads|boost log 1.54|glog |easylogging |spdlog| +|-------|:-------:|:-----:|----------:|------:| +|1| 4.169s |1.066s |0.975s |0.302s| +|10| 6.180s |3.032s |2.857s |0.968s| +|100| 5.981s |1.139s |4.512s |0.497s| + + +#### Asynchronous mode +Time needed to log 1,000,000 lines in asynchronous mode, i.e. the time it takes to put them in the async queue (in seconds, the best of 3 runs): + +|threads|g2log <sup>async logger</sup> |spdlog <sup>async mode</sup>| +|:-------|:-----:|-------------------------:| +|1| 1.850s |0.216s | +|10| 0.943s |0.173s| +|100| 0.959s |0.202s| + + + + +## Usage Example +```c++ + +#include "spdlog/spdlog.h" + +#include <iostream> +#include <memory> + +void async_example(); +void syslog_example(); +void user_defined_example(); +void err_handler_example(); + +namespace spd = spdlog; +int main(int, char*[]) +{ + try + { + // Console logger with color + auto console = spd::stdout_color_mt("console"); + console->info("Welcome to spdlog!"); + console->error("Some error message with arg{}..", 1); + + // Formatting examples + console->warn("Easy padding in numbers like {:08d}", 12); + console->critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42); + console->info("Support for floats {:03.2f}", 1.23456); + console->info("Positional args are {1} {0}..", "too", "supported"); + console->info("{:<30}", "left aligned"); + + + spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function"); + + // Create basic file logger (not rotated) + auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic.txt"); + my_logger->info("Some log message"); + + // Create a file rotating logger with 5mb size max and 3 rotated files + auto rotating_logger = spd::rotating_logger_mt("some_logger_name", "logs/mylogfile", 1048576 * 5, 3); + for (int i = 0; i < 10; ++i) + rotating_logger->info("{} * {} equals {:>10}", i, i, i*i); + + // Create a daily logger - a new file is created every day on 2:30am + auto daily_logger = spd::daily_logger_mt("daily_logger", "logs/daily", 2, 30); + // trigger flush if the log severity is error or higher + daily_logger->flush_on(spd::level::err); + daily_logger->info(123.44); + + // Customize msg format for all messages + spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***"); + rotating_logger->info("This is another message with custom format"); + + + // Runtime log levels + spd::set_level(spd::level::info); //Set global log level to info + console->debug("This message shold not be displayed!"); + console->set_level(spd::level::debug); // Set specific logger's log level + console->debug("This message shold be displayed.."); + + // Compile time log levels + // define SPDLOG_DEBUG_ON or SPDLOG_TRACE_ON + SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23); + SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23); + + // Asynchronous logging is very fast.. + // Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous.. + async_example(); + + // syslog example. linux/osx only + syslog_example(); + + // android example. compile with NDK + android_example(); + + // Log user-defined types example + user_defined_example(); + + // Change default log error handler + err_handler_example(); + + // Apply a function on all registered loggers + spd::apply_all([&](std::shared_ptr<spdlog::logger> l) + { + l->info("End of example."); + }); + + // Release and close all loggers + spdlog::drop_all(); + } + // Exceptions will only be thrown upon failed logger or sink construction (not during logging) + catch (const spd::spdlog_ex& ex) + { + std::cout << "Log init failed: " << ex.what() << std::endl; + return 1; + } +} + +void async_example() +{ + size_t q_size = 4096; //queue size must be power of 2 + spdlog::set_async_mode(q_size); + auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt"); + for (int i = 0; i < 100; ++i) + async_file->info("Async message #{}", i); +} + +//syslog example +void syslog_example() +{ +#ifdef SPDLOG_ENABLE_SYSLOG + std::string ident = "spdlog-example"; + auto syslog_logger = spd::syslog_logger("syslog", ident, LOG_PID); + syslog_logger->warn("This is warning that will end up in syslog.."); +#endif +} + +// user defined types logging by implementing operator<< +struct my_type +{ + int i; + template<typename OStream> + friend OStream& operator<<(OStream& os, const my_type &c) + { + return os << "[my_type i="<<c.i << "]"; + } +}; + +#include <spdlog/fmt/ostr.h> // must be included +void user_defined_example() +{ + spd::get("console")->info("user defined type: {}", my_type { 14 }); +} + +// +//custom error handler +// +void err_handler_example() +{ + spdlog::set_error_handler([](const std::string& msg) { + std::cerr << "my err handler: " << msg << std::endl; + }); + // (or logger->set_error_handler(..) to set for specific logger) +} + +``` + +## Documentation +Documentation can be found in the [wiki](https://github.com/gabime/spdlog/wiki/1.-QuickStart) pages. http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/astyle.sh ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/astyle.sh b/thirdparty/spdlog-0.13.0/astyle.sh new file mode 100755 index 0000000..a7a9051 --- /dev/null +++ b/thirdparty/spdlog-0.13.0/astyle.sh @@ -0,0 +1,5 @@ +#!/bin/bash +find . -name "*\.h" -o -name "*\.cpp"|xargs dos2unix +find . -name "*\.h" -o -name "*\.cpp"|xargs astyle -n -c -A1 + + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/cmake/Config.cmake.in ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/cmake/Config.cmake.in b/thirdparty/spdlog-0.13.0/cmake/Config.cmake.in new file mode 100644 index 0000000..ba0b36f --- /dev/null +++ b/thirdparty/spdlog-0.13.0/cmake/Config.cmake.in @@ -0,0 +1,24 @@ +# *************************************************************************/ +# * Copyright (c) 2015 Ruslan Baratov. */ +# * */ +# * Permission is hereby granted, free of charge, to any person obtaining */ +# * a copy of this software and associated documentation files (the */ +# * "Software"), to deal in the Software without restriction, including */ +# * without limitation the rights to use, copy, modify, merge, publish, */ +# * distribute, sublicense, and/or sell copies of the Software, and to */ +# * permit persons to whom the Software is furnished to do so, subject to */ +# * the following conditions: */ +# * */ +# * The above copyright notice and this permission notice shall be */ +# * included in all copies or substantial portions of the Software. */ +# * */ +# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +# * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +# * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +# * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +# * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +# * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +# * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +# *************************************************************************/ + +include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]") http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/cmake/spdlog.pc.in ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/cmake/spdlog.pc.in b/thirdparty/spdlog-0.13.0/cmake/spdlog.pc.in new file mode 100644 index 0000000..262248a --- /dev/null +++ b/thirdparty/spdlog-0.13.0/cmake/spdlog.pc.in @@ -0,0 +1,6 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +includedir=${prefix}/include + +Name: @PROJECT_NAME@ +Description: Super fast C++ logging library. +Version: @PROJECT_VERSION@ http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/async_logger.h ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/async_logger.h b/thirdparty/spdlog-0.13.0/include/spdlog/async_logger.h new file mode 100644 index 0000000..76d70a3 --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/async_logger.h @@ -0,0 +1,82 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +// Very fast asynchronous logger (millions of logs per second on an average desktop) +// Uses pre allocated lockfree queue for maximum throughput even under large number of threads. +// Creates a single back thread to pop messages from the queue and log them. +// +// Upon each log write the logger: +// 1. Checks if its log level is enough to log the message +// 2. Push a new copy of the message to a queue (or block the caller until space is available in the queue) +// 3. will throw spdlog_ex upon log exceptions +// Upon destruction, logs all remaining messages in the queue before destructing.. + +#include <spdlog/common.h> +#include <spdlog/logger.h> + +#include <chrono> +#include <functional> +#include <string> +#include <memory> + +namespace spdlog +{ + +namespace details +{ +class async_log_helper; +} + +class async_logger :public logger +{ +public: + template<class It> + async_logger(const std::string& name, + const It& begin, + const It& end, + size_t queue_size, + const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, + const std::function<void()>& worker_warmup_cb = nullptr, + const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), + const std::function<void()>& worker_teardown_cb = nullptr); + + async_logger(const std::string& logger_name, + sinks_init_list sinks, + size_t queue_size, + const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, + const std::function<void()>& worker_warmup_cb = nullptr, + const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), + const std::function<void()>& worker_teardown_cb = nullptr); + + async_logger(const std::string& logger_name, + sink_ptr single_sink, + size_t queue_size, + const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, + const std::function<void()>& worker_warmup_cb = nullptr, + const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), + const std::function<void()>& worker_teardown_cb = nullptr); + + //Wait for the queue to be empty, and flush synchronously + //Warning: this can potentialy last forever as we wait it to complete + void flush() override; + + // Error handler + virtual void set_error_handler(log_err_handler) override; + virtual log_err_handler error_handler() override; + +protected: + void _sink_it(details::log_msg& msg) override; + void _set_formatter(spdlog::formatter_ptr msg_formatter) override; + void _set_pattern(const std::string& pattern) override; + +private: + std::unique_ptr<details::async_log_helper> _async_log_helper; +}; +} + + +#include <spdlog/details/async_logger_impl.h> http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/common.h ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/common.h b/thirdparty/spdlog-0.13.0/include/spdlog/common.h new file mode 100644 index 0000000..a0a227e --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/common.h @@ -0,0 +1,143 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#include <string> +#include <initializer_list> +#include <chrono> +#include <memory> +#include <atomic> +#include <exception> +#include<functional> + +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) +#include <codecvt> +#include <locale> +#endif + +#include <spdlog/details/null_mutex.h> + +//visual studio upto 2013 does not support noexcept nor constexpr +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define SPDLOG_NOEXCEPT throw() +#define SPDLOG_CONSTEXPR +#else +#define SPDLOG_NOEXCEPT noexcept +#define SPDLOG_CONSTEXPR constexpr +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define SPDLOG_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +#define SPDLOG_DEPRECATED __declspec(deprecated) +#else +#define SPDLOG_DEPRECATED +#endif + + +#include <spdlog/fmt/fmt.h> + +namespace spdlog +{ + +class formatter; + +namespace sinks +{ +class sink; +} + +using log_clock = std::chrono::system_clock; +using sink_ptr = std::shared_ptr < sinks::sink >; +using sinks_init_list = std::initializer_list < sink_ptr >; +using formatter_ptr = std::shared_ptr<spdlog::formatter>; +#if defined(SPDLOG_NO_ATOMIC_LEVELS) +using level_t = details::null_atomic_int; +#else +using level_t = std::atomic<int>; +#endif + +using log_err_handler = std::function<void(const std::string &err_msg)>; + +//Log level enum +namespace level +{ +typedef enum +{ + trace = 0, + debug = 1, + info = 2, + warn = 3, + err = 4, + critical = 5, + off = 6 +} level_enum; + +static const char* level_names[] { "trace", "debug", "info", "warning", "error", "critical", "off" }; + +static const char* short_level_names[] { "T", "D", "I", "W", "E", "C", "O" }; + +inline const char* to_str(spdlog::level::level_enum l) +{ + return level_names[l]; +} + +inline const char* to_short_str(spdlog::level::level_enum l) +{ + return short_level_names[l]; +} +} //level + + +// +// Async overflow policy - block by default. +// +enum class async_overflow_policy +{ + block_retry, // Block / yield / sleep until message can be enqueued + discard_log_msg // Discard the message it enqueue fails +}; + + +// +// Log exception +// +namespace details +{ +namespace os +{ +std::string errno_str(int err_num); +} +} +class spdlog_ex: public std::exception +{ +public: + spdlog_ex(const std::string& msg):_msg(msg) + {} + spdlog_ex(const std::string& msg, int last_errno) + { + _msg = msg + ": " + details::os::errno_str(last_errno); + } + const char* what() const SPDLOG_NOEXCEPT override + { + return _msg.c_str(); + } +private: + std::string _msg; + +}; + +// +// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined) +// +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) +using filename_t = std::wstring; +#else +using filename_t = std::string; +#endif + + +} //spdlog http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/details/async_log_helper.h ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/details/async_log_helper.h b/thirdparty/spdlog-0.13.0/include/spdlog/details/async_log_helper.h new file mode 100644 index 0000000..92a0f4c --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/details/async_log_helper.h @@ -0,0 +1,391 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +// async log helper : +// Process logs asynchronously using a back thread. +// +// If the internal queue of log messages reaches its max size, +// then the client call will block until there is more room. +// +// If the back thread throws during logging, a spdlog::spdlog_ex exception +// will be thrown in client's thread when tries to log the next message + +#pragma once + +#include <spdlog/common.h> +#include <spdlog/sinks/sink.h> +#include <spdlog/details/mpmc_bounded_q.h> +#include <spdlog/details/log_msg.h> +#include <spdlog/details/os.h> +#include <spdlog/formatter.h> + +#include <chrono> +#include <exception> +#include <functional> +#include <memory> +#include <string> +#include <thread> +#include <utility> +#include <vector> + +namespace spdlog +{ +namespace details +{ + +class async_log_helper +{ + // Async msg to move to/from the queue + // Movable only. should never be copied + enum class async_msg_type + { + log, + flush, + terminate + }; + struct async_msg + { + std::string logger_name; + level::level_enum level; + log_clock::time_point time; + size_t thread_id; + std::string txt; + async_msg_type msg_type; + + async_msg() = default; + ~async_msg() = default; + + +async_msg(async_msg&& other) SPDLOG_NOEXCEPT: + logger_name(std::move(other.logger_name)), + level(std::move(other.level)), + time(std::move(other.time)), + txt(std::move(other.txt)), + msg_type(std::move(other.msg_type)) + {} + + async_msg(async_msg_type m_type):msg_type(m_type) + {} + + async_msg& operator=(async_msg&& other) SPDLOG_NOEXCEPT + { + logger_name = std::move(other.logger_name); + level = other.level; + time = std::move(other.time); + thread_id = other.thread_id; + txt = std::move(other.txt); + msg_type = other.msg_type; + return *this; + } + + // never copy or assign. should only be moved.. + async_msg(const async_msg&) = delete; + async_msg& operator=(const async_msg& other) = delete; + + // construct from log_msg + async_msg(const details::log_msg& m): + level(m.level), + time(m.time), + thread_id(m.thread_id), + txt(m.raw.data(), m.raw.size()), + msg_type(async_msg_type::log) + { +#ifndef SPDLOG_NO_NAME + logger_name = *m.logger_name; +#endif + } + + + // copy into log_msg + void fill_log_msg(log_msg &msg) + { + msg.logger_name = &logger_name; + msg.level = level; + msg.time = time; + msg.thread_id = thread_id; + msg.raw << txt; + } + }; + +public: + + using item_type = async_msg; + using q_type = details::mpmc_bounded_queue<item_type>; + + using clock = std::chrono::steady_clock; + + + async_log_helper(formatter_ptr formatter, + const std::vector<sink_ptr>& sinks, + size_t queue_size, + const log_err_handler err_handler, + const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, + const std::function<void()>& worker_warmup_cb = nullptr, + const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), + const std::function<void()>& worker_teardown_cb = nullptr); + + void log(const details::log_msg& msg); + + // stop logging and join the back thread + ~async_log_helper(); + + void set_formatter(formatter_ptr); + + void flush(bool wait_for_q); + + void set_error_handler(spdlog::log_err_handler err_handler); + +private: + formatter_ptr _formatter; + std::vector<std::shared_ptr<sinks::sink>> _sinks; + + // queue of messages to log + q_type _q; + + log_err_handler _err_handler; + + bool _flush_requested; + + bool _terminate_requested; + + + // overflow policy + const async_overflow_policy _overflow_policy; + + // worker thread warmup callback - one can set thread priority, affinity, etc + const std::function<void()> _worker_warmup_cb; + + // auto periodic sink flush parameter + const std::chrono::milliseconds _flush_interval_ms; + + // worker thread teardown callback + const std::function<void()> _worker_teardown_cb; + + // worker thread + std::thread _worker_thread; + + void push_msg(async_msg&& new_msg); + + // worker thread main loop + void worker_loop(); + + // pop next message from the queue and process it. will set the last_pop to the pop time + // return false if termination of the queue is required + bool process_next_msg(log_clock::time_point& last_pop, log_clock::time_point& last_flush); + + void handle_flush_interval(log_clock::time_point& now, log_clock::time_point& last_flush); + + // sleep,yield or return immediatly using the time passed since last message as a hint + static void sleep_or_yield(const spdlog::log_clock::time_point& now, const log_clock::time_point& last_op_time); + + // wait until the queue is empty + void wait_empty_q(); + +}; +} +} + +/////////////////////////////////////////////////////////////////////////////// +// async_sink class implementation +/////////////////////////////////////////////////////////////////////////////// +inline spdlog::details::async_log_helper::async_log_helper( + formatter_ptr formatter, + const std::vector<sink_ptr>& sinks, + size_t queue_size, + log_err_handler err_handler, + const async_overflow_policy overflow_policy, + const std::function<void()>& worker_warmup_cb, + const std::chrono::milliseconds& flush_interval_ms, + const std::function<void()>& worker_teardown_cb): + _formatter(formatter), + _sinks(sinks), + _q(queue_size), + _err_handler(err_handler), + _flush_requested(false), + _terminate_requested(false), + _overflow_policy(overflow_policy), + _worker_warmup_cb(worker_warmup_cb), + _flush_interval_ms(flush_interval_ms), + _worker_teardown_cb(worker_teardown_cb), + _worker_thread(&async_log_helper::worker_loop, this) +{} + +// Send to the worker thread termination message(level=off) +// and wait for it to finish gracefully +inline spdlog::details::async_log_helper::~async_log_helper() +{ + try + { + push_msg(async_msg(async_msg_type::terminate)); + _worker_thread.join(); + } + catch (...) // don't crash in destructor + { + } +} + + +//Try to push and block until succeeded (if the policy is not to discard when the queue is full) +inline void spdlog::details::async_log_helper::log(const details::log_msg& msg) +{ + push_msg(async_msg(msg)); +} + +inline void spdlog::details::async_log_helper::push_msg(details::async_log_helper::async_msg&& new_msg) +{ + if (!_q.enqueue(std::move(new_msg)) && _overflow_policy != async_overflow_policy::discard_log_msg) + { + auto last_op_time = details::os::now(); + auto now = last_op_time; + do + { + now = details::os::now(); + sleep_or_yield(now, last_op_time); + } + while (!_q.enqueue(std::move(new_msg))); + } +} + +// optionally wait for the queue be empty and request flush from the sinks +inline void spdlog::details::async_log_helper::flush(bool wait_for_q) +{ + push_msg(async_msg(async_msg_type::flush)); + if (wait_for_q) + wait_empty_q(); //return only make after the above flush message was processed +} + +inline void spdlog::details::async_log_helper::worker_loop() +{ + if (_worker_warmup_cb) _worker_warmup_cb(); + auto last_pop = details::os::now(); + auto last_flush = last_pop; + auto active = true; + while (active) + { + try + { + active = process_next_msg(last_pop, last_flush); + } + catch (const std::exception &ex) + { + _err_handler(ex.what()); + } + catch (...) + { + _err_handler("Unknown exception"); + } + } + if (_worker_teardown_cb) _worker_teardown_cb(); + + +} + +// process next message in the queue +// return true if this thread should still be active (while no terminate msg was received) +inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_point& last_pop, log_clock::time_point& last_flush) +{ + async_msg incoming_async_msg; + + if (_q.dequeue(incoming_async_msg)) + { + last_pop = details::os::now(); + switch (incoming_async_msg.msg_type) + { + case async_msg_type::flush: + _flush_requested = true; + break; + + case async_msg_type::terminate: + _flush_requested = true; + _terminate_requested = true; + break; + + default: + log_msg incoming_log_msg; + incoming_async_msg.fill_log_msg(incoming_log_msg); + _formatter->format(incoming_log_msg); + for (auto &s : _sinks) + { + if (s->should_log(incoming_log_msg.level)) + { + s->log(incoming_log_msg); + } + } + } + return true; + } + + // Handle empty queue.. + // This is the only place where the queue can terminate or flush to avoid losing messages already in the queue + else + { + auto now = details::os::now(); + handle_flush_interval(now, last_flush); + sleep_or_yield(now, last_pop); + return !_terminate_requested; + } +} + +// flush all sinks if _flush_interval_ms has expired +inline void spdlog::details::async_log_helper::handle_flush_interval(log_clock::time_point& now, log_clock::time_point& last_flush) +{ + auto should_flush = _flush_requested || (_flush_interval_ms != std::chrono::milliseconds::zero() && now - last_flush >= _flush_interval_ms); + if (should_flush) + { + for (auto &s : _sinks) + s->flush(); + now = last_flush = details::os::now(); + _flush_requested = false; + } +} + +inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter) +{ + _formatter = msg_formatter; +} + + +// spin, yield or sleep. use the time passed since last message as a hint +inline void spdlog::details::async_log_helper::sleep_or_yield(const spdlog::log_clock::time_point& now, const spdlog::log_clock::time_point& last_op_time) +{ + using namespace std::this_thread; + using std::chrono::milliseconds; + using std::chrono::microseconds; + + auto time_since_op = now - last_op_time; + + // spin upto 50 micros + if (time_since_op <= microseconds(50)) + return; + + // yield upto 150 micros + if (time_since_op <= microseconds(100)) + return std::this_thread::yield(); + + // sleep for 20 ms upto 200 ms + if (time_since_op <= milliseconds(200)) + return sleep_for(milliseconds(20)); + + // sleep for 200 ms + return sleep_for(milliseconds(200)); +} + +// wait for the queue to be empty +inline void spdlog::details::async_log_helper::wait_empty_q() +{ + auto last_op = details::os::now(); + while (_q.approx_size() > 0) + { + sleep_or_yield(details::os::now(), last_op); + } +} + +inline void spdlog::details::async_log_helper::set_error_handler(spdlog::log_err_handler err_handler) +{ + _err_handler = err_handler; +} + + + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/details/async_logger_impl.h ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/details/async_logger_impl.h b/thirdparty/spdlog-0.13.0/include/spdlog/details/async_logger_impl.h new file mode 100644 index 0000000..487c628 --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/details/async_logger_impl.h @@ -0,0 +1,102 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +// Async Logger implementation +// Use an async_sink (queue per logger) to perform the logging in a worker thread + +#include <spdlog/details/async_log_helper.h> +#include <spdlog/async_logger.h> + +#include <string> +#include <functional> +#include <chrono> +#include <memory> + +template<class It> +inline spdlog::async_logger::async_logger(const std::string& logger_name, + const It& begin, + const It& end, + size_t queue_size, + const async_overflow_policy overflow_policy, + const std::function<void()>& worker_warmup_cb, + const std::chrono::milliseconds& flush_interval_ms, + const std::function<void()>& worker_teardown_cb) : + logger(logger_name, begin, end), + _async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, _err_handler, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb)) +{ +} + +inline spdlog::async_logger::async_logger(const std::string& logger_name, + sinks_init_list sinks_list, + size_t queue_size, + const async_overflow_policy overflow_policy, + const std::function<void()>& worker_warmup_cb, + const std::chrono::milliseconds& flush_interval_ms, + const std::function<void()>& worker_teardown_cb) : + async_logger(logger_name, sinks_list.begin(), sinks_list.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {} + +inline spdlog::async_logger::async_logger(const std::string& logger_name, + sink_ptr single_sink, + size_t queue_size, + const async_overflow_policy overflow_policy, + const std::function<void()>& worker_warmup_cb, + const std::chrono::milliseconds& flush_interval_ms, + const std::function<void()>& worker_teardown_cb) : + async_logger(logger_name, +{ + single_sink +}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {} + + +inline void spdlog::async_logger::flush() +{ + _async_log_helper->flush(true); +} + +// Error handler +inline void spdlog::async_logger::set_error_handler(spdlog::log_err_handler err_handler) +{ + _err_handler = err_handler; + _async_log_helper->set_error_handler(err_handler); + +} +inline spdlog::log_err_handler spdlog::async_logger::error_handler() +{ + return _err_handler; +} + + +inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter) +{ + _formatter = msg_formatter; + _async_log_helper->set_formatter(_formatter); +} + +inline void spdlog::async_logger::_set_pattern(const std::string& pattern) +{ + _formatter = std::make_shared<pattern_formatter>(pattern); + _async_log_helper->set_formatter(_formatter); +} + + +inline void spdlog::async_logger::_sink_it(details::log_msg& msg) +{ + try + { + _async_log_helper->log(msg); + if (_should_flush_on(msg)) + _async_log_helper->flush(false); // do async flush + } + catch (const std::exception &ex) + { + _err_handler(ex.what()); + } + catch (...) + { + _err_handler("Unknown exception"); + } +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/details/file_helper.h ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/details/file_helper.h b/thirdparty/spdlog-0.13.0/include/spdlog/details/file_helper.h new file mode 100644 index 0000000..074d9b8 --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/details/file_helper.h @@ -0,0 +1,118 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +// Helper class for file sink +// When failing to open a file, retry several times(5) with small delay between the tries(10 ms) +// Can be set to auto flush on every line +// Throw spdlog_ex exception on errors + +#include <spdlog/details/os.h> +#include <spdlog/details/log_msg.h> + +#include <chrono> +#include <cstdio> +#include <string> +#include <thread> +#include <cerrno> + +namespace spdlog +{ +namespace details +{ + +class file_helper +{ + +public: + const int open_tries = 5; + const int open_interval = 10; + + explicit file_helper() : + _fd(nullptr) + {} + + file_helper(const file_helper&) = delete; + file_helper& operator=(const file_helper&) = delete; + + ~file_helper() + { + close(); + } + + + void open(const filename_t& fname, bool truncate = false) + { + + close(); + auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab"); + _filename = fname; + for (int tries = 0; tries < open_tries; ++tries) + { + if (!os::fopen_s(&_fd, fname, mode)) + return; + + std::this_thread::sleep_for(std::chrono::milliseconds(open_interval)); + } + + throw spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno); + } + + void reopen(bool truncate) + { + if (_filename.empty()) + throw spdlog_ex("Failed re opening file - was not opened before"); + open(_filename, truncate); + + } + + void flush() + { + std::fflush(_fd); + } + + void close() + { + if (_fd) + { + std::fclose(_fd); + _fd = nullptr; + } + } + + void write(const log_msg& msg) + { + + size_t msg_size = msg.formatted.size(); + auto data = msg.formatted.data(); + if (std::fwrite(data, 1, msg_size, _fd) != msg_size) + throw spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno); + } + + size_t size() + { + if (!_fd) + throw spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename)); + return os::filesize(_fd); + } + + const filename_t& filename() const + { + return _filename; + } + + static bool file_exists(const filename_t& name) + { + + return os::file_exists(name); + } + +private: + FILE* _fd; + filename_t _filename; +}; +} +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/details/log_msg.h ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/details/log_msg.h b/thirdparty/spdlog-0.13.0/include/spdlog/details/log_msg.h new file mode 100644 index 0000000..ecdc73d --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/details/log_msg.h @@ -0,0 +1,46 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#include <spdlog/common.h> +#include <spdlog/details/os.h> + + +#include <string> +#include <utility> + +namespace spdlog +{ +namespace details +{ +struct log_msg +{ + log_msg() = default; + log_msg(const std::string *loggers_name, level::level_enum lvl) : logger_name(loggers_name), level(lvl) + { +#ifndef SPDLOG_NO_DATETIME + time = os::now(); +#endif + +#ifndef SPDLOG_NO_THREAD_ID + thread_id = os::thread_id(); +#endif + } + + log_msg(const log_msg& other) = delete; + log_msg& operator=(log_msg&& other) = delete; + log_msg(log_msg&& other) = delete; + + + const std::string *logger_name; + level::level_enum level; + log_clock::time_point time; + size_t thread_id; + fmt::MemoryWriter raw; + fmt::MemoryWriter formatted; +}; +} +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/details/logger_impl.h ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/details/logger_impl.h b/thirdparty/spdlog-0.13.0/include/spdlog/details/logger_impl.h new file mode 100644 index 0000000..5bb85f6 --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/details/logger_impl.h @@ -0,0 +1,296 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#include <spdlog/logger.h> +#include <spdlog/sinks/stdout_sinks.h> + +#include <memory> +#include <string> + + +// create logger with given name, sinks and the default pattern formatter +// all other ctors will call this one +template<class It> +inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end): + _name(logger_name), + _sinks(begin, end), + _formatter(std::make_shared<pattern_formatter>("%+")) +{ + _level = level::info; + _flush_level = level::off; + _last_err_time = 0; + _err_handler = [this](const std::string &msg) + { + this->_default_err_handler(msg); + }; +} + +// ctor with sinks as init list +inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list): + logger(logger_name, sinks_list.begin(), sinks_list.end()) +{} + + +// ctor with single sink +inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink): + logger(logger_name, +{ + single_sink +}) +{} + + +inline spdlog::logger::~logger() = default; + + +inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter) +{ + _set_formatter(msg_formatter); +} + +inline void spdlog::logger::set_pattern(const std::string& pattern) +{ + _set_pattern(pattern); +} + + +template <typename... Args> +inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Args&... args) +{ + if (!should_log(lvl)) return; + + try + { + details::log_msg log_msg(&_name, lvl); + log_msg.raw.write(fmt, args...); + _sink_it(log_msg); + } + catch (const std::exception &ex) + { + _err_handler(ex.what()); + } + catch (...) + { + _err_handler("Unknown exception"); + } +} + +template <typename... Args> +inline void spdlog::logger::log(level::level_enum lvl, const char* msg) +{ + if (!should_log(lvl)) return; + try + { + details::log_msg log_msg(&_name, lvl); + log_msg.raw << msg; + _sink_it(log_msg); + } + catch (const std::exception &ex) + { + _err_handler(ex.what()); + } + catch (...) + { + _err_handler("Unknown exception"); + } + +} + +template<typename T> +inline void spdlog::logger::log(level::level_enum lvl, const T& msg) +{ + if (!should_log(lvl)) return; + try + { + details::log_msg log_msg(&_name, lvl); + log_msg.raw << msg; + _sink_it(log_msg); + } + catch (const std::exception &ex) + { + _err_handler(ex.what()); + } + catch (...) + { + _err_handler("Unknown exception"); + } +} + + +template <typename Arg1, typename... Args> +inline void spdlog::logger::trace(const char* fmt, const Arg1 &arg1, const Args&... args) +{ + log(level::trace, fmt, arg1, args...); +} + +template <typename Arg1, typename... Args> +inline void spdlog::logger::debug(const char* fmt, const Arg1 &arg1, const Args&... args) +{ + log(level::debug, fmt, arg1, args...); +} + +template <typename Arg1, typename... Args> +inline void spdlog::logger::info(const char* fmt, const Arg1 &arg1, const Args&... args) +{ + log(level::info, fmt, arg1, args...); +} + +template <typename Arg1, typename... Args> +inline void spdlog::logger::warn(const char* fmt, const Arg1 &arg1, const Args&... args) +{ + log(level::warn, fmt, arg1, args...); +} + +template <typename Arg1, typename... Args> +inline void spdlog::logger::error(const char* fmt, const Arg1 &arg1, const Args&... args) +{ + log(level::err, fmt, arg1, args...); +} + +template <typename Arg1, typename... Args> +inline void spdlog::logger::critical(const char* fmt, const Arg1 &arg1, const Args&... args) +{ + log(level::critical, fmt, arg1, args...); +} + +template<typename T> +inline void spdlog::logger::trace(const T& msg) +{ + log(level::trace, msg); +} + +template<typename T> +inline void spdlog::logger::debug(const T& msg) +{ + log(level::debug, msg); +} + + +template<typename T> +inline void spdlog::logger::info(const T& msg) +{ + log(level::info, msg); +} + + +template<typename T> +inline void spdlog::logger::warn(const T& msg) +{ + log(level::warn, msg); +} + +template<typename T> +inline void spdlog::logger::error(const T& msg) +{ + log(level::err, msg); +} + +template<typename T> +inline void spdlog::logger::critical(const T& msg) +{ + log(level::critical, msg); +} + + + + +// +// name and level +// +inline const std::string& spdlog::logger::name() const +{ + return _name; +} + +inline void spdlog::logger::set_level(spdlog::level::level_enum log_level) +{ + _level.store(log_level); +} + +inline void spdlog::logger::set_error_handler(spdlog::log_err_handler err_handler) +{ + _err_handler = err_handler; +} + +inline spdlog::log_err_handler spdlog::logger::error_handler() +{ + return _err_handler; +} + + +inline void spdlog::logger::flush_on(level::level_enum log_level) +{ + _flush_level.store(log_level); +} + +inline spdlog::level::level_enum spdlog::logger::level() const +{ + return static_cast<spdlog::level::level_enum>(_level.load(std::memory_order_relaxed)); +} + +inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const +{ + return msg_level >= _level.load(std::memory_order_relaxed); +} + +// +// protected virtual called at end of each user log call (if enabled) by the line_logger +// +inline void spdlog::logger::_sink_it(details::log_msg& msg) +{ + _formatter->format(msg); + for (auto &sink : _sinks) + { + if( sink->should_log( msg.level)) + { + sink->log(msg); + } + } + + if(_should_flush_on(msg)) + flush(); +} + +inline void spdlog::logger::_set_pattern(const std::string& pattern) +{ + _formatter = std::make_shared<pattern_formatter>(pattern); +} +inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter) +{ + _formatter = msg_formatter; +} + +inline void spdlog::logger::flush() +{ + for (auto& sink : _sinks) + sink->flush(); +} + +inline void spdlog::logger::_default_err_handler(const std::string &msg) +{ + auto now = time(nullptr); + if (now - _last_err_time < 60) + return; + auto tm_time = details::os::localtime(now); + char date_buf[100]; + std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); + details::log_msg err_msg; + err_msg.formatted.write("[*** LOG ERROR ***] [{}] [{}] [{}]{}", name(), msg, date_buf, details::os::eol); + sinks::stderr_sink_mt::instance()->log(err_msg); + _last_err_time = now; +} + +inline bool spdlog::logger::_should_flush_on(const details::log_msg &msg) +{ + const auto flush_level = _flush_level.load(std::memory_order_relaxed); + return (msg.level >= flush_level) && (msg.level != level::off); +} + +inline const std::vector<spdlog::sink_ptr>& spdlog::logger::sinks() const +{ + return _sinks; +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/details/mpmc_bounded_q.h ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/details/mpmc_bounded_q.h b/thirdparty/spdlog-0.13.0/include/spdlog/details/mpmc_bounded_q.h new file mode 100644 index 0000000..3a46e8e --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/details/mpmc_bounded_q.h @@ -0,0 +1,172 @@ +/* +A modified version of Bounded MPMC queue by Dmitry Vyukov. + +Original code from: +http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue + +licensed by Dmitry Vyukov under the terms below: + +Simplified BSD license + +Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list +of conditions and the following disclaimer in the documentation and/or other materials +provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the authors and +should not be interpreted as representing official policies, either expressed or implied, of Dmitry Vyukov. +*/ + +/* +The code in its current form adds the license below: + +Copyright(c) 2015 Gabi Melman. +Distributed under the MIT License (http://opensource.org/licenses/MIT) + +*/ + +#pragma once + +#include <spdlog/common.h> + +#include <atomic> +#include <utility> + +namespace spdlog +{ +namespace details +{ + +template<typename T> +class mpmc_bounded_queue +{ +public: + + using item_type = T; + mpmc_bounded_queue(size_t buffer_size) + :max_size_(buffer_size), + buffer_(new cell_t [buffer_size]), + buffer_mask_(buffer_size - 1) + { + //queue size must be power of two + if(!((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0))) + throw spdlog_ex("async logger queue size must be power of two"); + + for (size_t i = 0; i != buffer_size; i += 1) + buffer_[i].sequence_.store(i, std::memory_order_relaxed); + enqueue_pos_.store(0, std::memory_order_relaxed); + dequeue_pos_.store(0, std::memory_order_relaxed); + } + + ~mpmc_bounded_queue() + { + delete [] buffer_; + } + + + bool enqueue(T&& data) + { + cell_t* cell; + size_t pos = enqueue_pos_.load(std::memory_order_relaxed); + for (;;) + { + cell = &buffer_[pos & buffer_mask_]; + size_t seq = cell->sequence_.load(std::memory_order_acquire); + intptr_t dif = (intptr_t)seq - (intptr_t)pos; + if (dif == 0) + { + if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed)) + break; + } + else if (dif < 0) + { + return false; + } + else + { + pos = enqueue_pos_.load(std::memory_order_relaxed); + } + } + cell->data_ = std::move(data); + cell->sequence_.store(pos + 1, std::memory_order_release); + return true; + } + + bool dequeue(T& data) + { + cell_t* cell; + size_t pos = dequeue_pos_.load(std::memory_order_relaxed); + for (;;) + { + cell = &buffer_[pos & buffer_mask_]; + size_t seq = + cell->sequence_.load(std::memory_order_acquire); + intptr_t dif = (intptr_t)seq - (intptr_t)(pos + 1); + if (dif == 0) + { + if (dequeue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed)) + break; + } + else if (dif < 0) + return false; + else + pos = dequeue_pos_.load(std::memory_order_relaxed); + } + data = std::move(cell->data_); + cell->sequence_.store(pos + buffer_mask_ + 1, std::memory_order_release); + return true; + } + + size_t approx_size() + { + size_t first_pos = dequeue_pos_.load(std::memory_order_relaxed); + size_t last_pos = enqueue_pos_.load(std::memory_order_relaxed); + if (last_pos <= first_pos) + return 0; + auto size = last_pos - first_pos; + return size < max_size_ ? size : max_size_; + } + +private: + struct cell_t + { + std::atomic<size_t> sequence_; + T data_; + }; + + size_t const max_size_; + + static size_t const cacheline_size = 64; + typedef char cacheline_pad_t [cacheline_size]; + + cacheline_pad_t pad0_; + cell_t* const buffer_; + size_t const buffer_mask_; + cacheline_pad_t pad1_; + std::atomic<size_t> enqueue_pos_; + cacheline_pad_t pad2_; + std::atomic<size_t> dequeue_pos_; + cacheline_pad_t pad3_; + + mpmc_bounded_queue(mpmc_bounded_queue const&) = delete; + void operator= (mpmc_bounded_queue const&) = delete; +}; + +} // ns details +} // ns spdlog
