MINIFI-83: Allow appenders to be specified and auto configured. This PR will modify logging so that we can have configurable appenders and have them be modified via custom configuration for that appender. Eventually these can be modified real time.
This closes #57. Signed-off-by: Aldrin Piri <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/repo Commit: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/commit/f38859e4 Tree: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/tree/f38859e4 Diff: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/diff/f38859e4 Branch: refs/heads/master Commit: f38859e432d437fc7a869016fc40f8dadfe89e72 Parents: 3facf2c Author: Marc Parisi <[email protected]> Authored: Fri Feb 24 10:06:19 2017 -0500 Committer: Aldrin Piri <[email protected]> Committed: Mon Feb 27 14:40:12 2017 -0500 ---------------------------------------------------------------------- libminifi/include/AppendHostInfo.h | 2 +- libminifi/include/BaseLogger.h | 207 +++++++++++++++ libminifi/include/Configure.h | 4 +- libminifi/include/Connection.h | 4 +- libminifi/include/ExecuteProcess.h | 2 +- libminifi/include/FlowControlProtocol.h | 4 +- libminifi/include/FlowController.h | 5 +- libminifi/include/FlowFileRecord.h | 2 +- libminifi/include/GetFile.h | 2 +- libminifi/include/ListenHTTP.h | 6 +- libminifi/include/ListenSyslog.h | 2 +- libminifi/include/LogAppenders.h | 298 ++++++++++++++++++++++ libminifi/include/LogAttribute.h | 2 +- libminifi/include/Logger.h | 223 ++++++++-------- libminifi/include/ProcessContext.h | 2 +- libminifi/include/ProcessGroup.h | 4 +- libminifi/include/ProcessSession.h | 4 +- libminifi/include/Processor.h | 2 +- libminifi/include/Property.h | 1 - libminifi/include/Provenance.h | 6 +- libminifi/include/PutFile.h | 4 +- libminifi/include/RealTimeDataCollector.h | 2 +- libminifi/include/RemoteProcessorGroupPort.h | 31 +-- libminifi/include/ResourceClaim.h | 2 +- libminifi/include/SchedulingAgent.h | 3 +- libminifi/include/Site2SiteClientProtocol.h | 4 +- libminifi/include/Site2SitePeer.h | 3 +- libminifi/include/TailFile.h | 2 +- libminifi/include/ThreadedSchedulingAgent.h | 2 +- libminifi/include/io/ClientSocket.h | 2 +- libminifi/include/io/TLSSocket.h | 2 +- libminifi/src/BaseLogger.cpp | 153 +++++++++++ libminifi/src/Configure.cpp | 2 +- libminifi/src/FlowFileRecord.cpp | 3 +- libminifi/src/LogAppenders.cpp | 25 ++ libminifi/src/Logger.cpp | 5 +- libminifi/src/Provenance.cpp | 3 +- libminifi/src/io/TLSSocket.cpp | 16 +- libminifi/test/TestBase.h | 2 +- libminifi/test/unit/CRCTests.cpp | 81 ++++++ libminifi/test/unit/CRCTests.h | 78 ------ libminifi/test/unit/LoggerTests.cpp | 143 +++++++++++ libminifi/test/unit/ProcessorTests.cpp | 150 +++++++++++ libminifi/test/unit/ProcessorTests.h | 154 ----------- libminifi/test/unit/PropertyTests.cpp | 103 ++++++++ libminifi/test/unit/PropertyTests.h | 106 -------- libminifi/test/unit/ProvenanceTests.cpp | 96 +++++++ libminifi/test/unit/ProvenanceTests.h | 96 ------- libminifi/test/unit/SerializationTests.cpp | 83 ++++++ libminifi/test/unit/SerializationTests.h | 88 ------- libminifi/test/unit/SocketTests.cpp | 186 ++++++++++++++ libminifi/test/unit/SocketTests.h | 190 -------------- libminifi/test/unit/Tests.cpp | 14 +- libminifi/test/unit/TimeUtilsTest.h | 30 --- main/MiNiFiMain.cpp | 119 ++++----- 55 files changed, 1773 insertions(+), 992 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/AppendHostInfo.h ---------------------------------------------------------------------- diff --git a/libminifi/include/AppendHostInfo.h b/libminifi/include/AppendHostInfo.h index 5d62aae..8d9dd8f 100644 --- a/libminifi/include/AppendHostInfo.h +++ b/libminifi/include/AppendHostInfo.h @@ -61,7 +61,7 @@ protected: private: //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; }; #endif http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/BaseLogger.h ---------------------------------------------------------------------- diff --git a/libminifi/include/BaseLogger.h b/libminifi/include/BaseLogger.h new file mode 100644 index 0000000..e9d2a02 --- /dev/null +++ b/libminifi/include/BaseLogger.h @@ -0,0 +1,207 @@ +/** + * + * 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. + */ +#ifndef LIBMINIFI_INCLUDE_BASELOGGER_H_ +#define LIBMINIFI_INCLUDE_BASELOGGER_H_ + +#include <string> +#include <memory> +#include "spdlog/spdlog.h" +#include <iostream> +//! 5M default log file size +#define DEFAULT_LOG_FILE_SIZE (5*1024*1024) +//! 3 log files rotation +#define DEFAULT_LOG_FILE_NUMBER 3 +#define LOG_NAME "minifi log" +#define LOG_FILE_NAME "minifi-app.log" + +/** + * Log level enumeration. + */ +typedef enum { + trace = 0, debug = 1, info = 2, warn = 3, err = 4, critical = 5, off = 6 +} LOG_LEVEL_E; + +#define LOG_BUFFER_SIZE 1024 +#define FILL_BUFFER char buffer[LOG_BUFFER_SIZE]; \ + va_list args; \ + va_start(args, format); \ + std::vsnprintf(buffer, LOG_BUFFER_SIZE,format, args); \ + va_end(args); + +/** + * Base class that represents a logger configuration. + */ +class BaseLogger { + +public: + static const char *nifi_log_level; + static const char *nifi_log_appender; + + /** + * Base Constructor + */ + BaseLogger() { + setLogLevel("info"); + logger_ = nullptr; + stderr_ = nullptr; + } + + /** + * Logger configuration constructorthat will set the base log level. + * @param config incoming configuration. + */ + BaseLogger(std::string log_level, std::shared_ptr<spdlog::logger> logger) : logger_(logger) { + setLogLevel(log_level); + + } + + virtual ~BaseLogger() { + + } + + /** + * Move constructor that will atomically swap configuration + * shared pointers. + */ + BaseLogger(const BaseLogger &&other) : + configured_level_(other.configured_level_.load()) { + // must atomically exchange the pointers + logger_ = std::move(other.logger_); + set_error_logger(other.stderr_); + + } + + /** + * Returns the log level for this instance. + */ + virtual LOG_LEVEL_E getLogLevel() const { + return configured_level_; + } + + /** + * @brief Log error message + * @param format format string ('man printf' for syntax) + * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match + */ + virtual void log_error(const char * const format, ...); + /** + * @brief Log warn message + * @param format format string ('man printf' for syntax) + * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match + */ + virtual void log_warn(const char * const format, ...); + /** + * @brief Log info message + * @param format format string ('man printf' for syntax) + * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match + */ + virtual void log_info(const char * const format, ...); + /** + * @brief Log debug message + * @param format format string ('man printf' for syntax) + * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match + */ + virtual void log_debug(const char * const format, ...); + /** + * @brief Log trace message + * @param format format string ('man printf' for syntax) + * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match + */ + virtual void log_trace(const char * const format, ...); + + /** + * @brief Log error message + * @param format format string ('man printf' for syntax) + * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match + */ + virtual void log_str(LOG_LEVEL_E level,const std::string &buffer); + + /** + * Sets the log level for this instance based on the string + * @param level desired log leve. + * @param defaultLevel default level if we cannot match level. + */ + virtual void setLogLevel(const std::string &level, + LOG_LEVEL_E defaultLevel = info); + + /** + * Sets the log level atomic and sets it + * within logger if it can + * @param level desired log level. + */ + virtual void setLogLevel(LOG_LEVEL_E level) { + configured_level_ = level; + setLogLevel(); + } + + bool shouldLog(LOG_LEVEL_E level) + { + return level >= configured_level_.load(std::memory_order_relaxed); + } + + /** + * Move operator overload + */ + BaseLogger &operator=(const BaseLogger &&other) { + configured_level_ = (other.configured_level_.load()); + // must atomically exchange the pointers + logger_ = std::move(other.logger_); + set_error_logger(other.stderr_); + return *this; + } + +protected: + + + + /** + * Logger configuration constructorthat will set the base log level. + * @param config incoming configuration. + */ + BaseLogger(std::string log_level) : logger_(nullptr) { + setLogLevel(log_level); + } + + + void setLogger(std::shared_ptr<spdlog::logger> logger) { + logger_ = logger; + } + + /** + * Since a thread may be using stderr and it can be null, + * we must atomically exchange the shared pointers. + * @param other other shared pointer. can be null ptr + */ + void set_error_logger(std::shared_ptr<spdlog::logger> other); + + /** + * Sets the log level on the spdlogger if it is not null. + */ + void setLogLevel() { + if (logger_ != nullptr) + logger_->set_level( + (spdlog::level::level_enum) configured_level_.load()); + + } + + std::atomic<LOG_LEVEL_E> configured_level_; + std::shared_ptr<spdlog::logger> logger_; + std::shared_ptr<spdlog::logger> stderr_; +}; + +#endif /* LIBMINIFI_INCLUDE_BASELOGGER_H_ */ http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Configure.h ---------------------------------------------------------------------- diff --git a/libminifi/include/Configure.h b/libminifi/include/Configure.h index a60a6d5..9bb7a0e 100644 --- a/libminifi/include/Configure.h +++ b/libminifi/include/Configure.h @@ -27,6 +27,7 @@ #include <errno.h> #include <iostream> #include <fstream> + #include "Logger.h" class Configure { @@ -45,7 +46,6 @@ public: static const char *nifi_administrative_yield_duration; static const char *nifi_bored_yield_duration; static const char *nifi_graceful_shutdown_seconds; - static const char *nifi_log_level; static const char *nifi_server_name; static const char *nifi_server_port; static const char *nifi_server_report_interval; @@ -101,7 +101,7 @@ private: //! Mutex for protection std::mutex _mtx; //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; //! Home location for this executable std::string _minifiHome; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Connection.h ---------------------------------------------------------------------- diff --git a/libminifi/include/Connection.h b/libminifi/include/Connection.h index d372b77..0868560 100644 --- a/libminifi/include/Connection.h +++ b/libminifi/include/Connection.h @@ -29,8 +29,8 @@ #include <algorithm> #include "FlowFileRecord.h" -#include "Relationship.h" #include "Logger.h" +#include "Relationship.h" //! Forwarder declaration class Processor; @@ -190,7 +190,7 @@ private: //! Queue for the Flow File std::queue<FlowFileRecord *> _queue; //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; // Prevent default copy constructor and assignment operation // Only support pass by reference or pointer Connection(const Connection &parent); http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ExecuteProcess.h ---------------------------------------------------------------------- diff --git a/libminifi/include/ExecuteProcess.h b/libminifi/include/ExecuteProcess.h index 83cf23c..3ddd815 100644 --- a/libminifi/include/ExecuteProcess.h +++ b/libminifi/include/ExecuteProcess.h @@ -94,7 +94,7 @@ protected: private: //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; //! Property std::string _command; std::string _commandArgument; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/FlowControlProtocol.h ---------------------------------------------------------------------- diff --git a/libminifi/include/FlowControlProtocol.h b/libminifi/include/FlowControlProtocol.h index b3b0686..ffc454a 100644 --- a/libminifi/include/FlowControlProtocol.h +++ b/libminifi/include/FlowControlProtocol.h @@ -32,8 +32,8 @@ #include <errno.h> #include <chrono> #include <thread> -#include "Logger.h" #include "Configure.h" +#include "Logger.h" #include "Property.h" //! Forwarder declaration @@ -304,7 +304,7 @@ private: //! Mutex for protection std::mutex _mtx; //! Logger - Logger *logger_ = NULL; + std::shared_ptr<Logger> logger_; //! Configure Configure *configure_ = NULL; //! NiFi server Name http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/FlowController.h ---------------------------------------------------------------------- diff --git a/libminifi/include/FlowController.h b/libminifi/include/FlowController.h index 56dba03..d60f022 100644 --- a/libminifi/include/FlowController.h +++ b/libminifi/include/FlowController.h @@ -219,7 +219,7 @@ protected: private: //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; }; @@ -281,9 +281,8 @@ private: //! Mutex for protection std::mutex _mtx; //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; Configure *configure_; - //! Process Processor Node YAML void parseProcessorNodeYaml(YAML::Node processorNode, ProcessGroup *parent); //! Process Port YAML http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/FlowFileRecord.h ---------------------------------------------------------------------- diff --git a/libminifi/include/FlowFileRecord.h b/libminifi/include/FlowFileRecord.h index 6626572..a3b87ee 100644 --- a/libminifi/include/FlowFileRecord.h +++ b/libminifi/include/FlowFileRecord.h @@ -216,7 +216,7 @@ private: //! Orginal connection queue that this flow file was dequeued from Connection *_orginalConnection; //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; //! Snapshot flow record for session rollback bool _snapshot; // Prevent default copy constructor and assignment operation http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/GetFile.h ---------------------------------------------------------------------- diff --git a/libminifi/include/GetFile.h b/libminifi/include/GetFile.h index 0d74110..8f8068c 100644 --- a/libminifi/include/GetFile.h +++ b/libminifi/include/GetFile.h @@ -82,7 +82,7 @@ protected: private: //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; //! Queue for store directory list std::queue<std::string> _dirList; //! Get Listing size http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ListenHTTP.h ---------------------------------------------------------------------- diff --git a/libminifi/include/ListenHTTP.h b/libminifi/include/ListenHTTP.h index 57fd967..5a467f2 100644 --- a/libminifi/include/ListenHTTP.h +++ b/libminifi/include/ListenHTTP.h @@ -80,7 +80,7 @@ public: //! Send HTTP 500 error response to client void sendErrorResponse(struct mg_connection *conn); //! Logger - Logger *_logger; + std::shared_ptr<Logger> _logger; std::regex _authDNRegex; std::regex _headersAsAttributesRegex; @@ -97,7 +97,7 @@ public: private: //! Logger - Logger *_logger; + std::shared_ptr<Logger> _logger; struct mg_connection *_conn; const struct mg_request_info *_reqInfo; @@ -107,7 +107,7 @@ protected: private: //! Logger - Logger *_logger; + std::shared_ptr<Logger> _logger; std::unique_ptr<CivetServer> _server; std::unique_ptr<Handler> _handler; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ListenSyslog.h ---------------------------------------------------------------------- diff --git a/libminifi/include/ListenSyslog.h b/libminifi/include/ListenSyslog.h index 309a3ad..339dbc1 100644 --- a/libminifi/include/ListenSyslog.h +++ b/libminifi/include/ListenSyslog.h @@ -130,7 +130,7 @@ protected: private: //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; //! Run function for the thread static void run(ListenSyslog *process); //! Run Thread http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/LogAppenders.h ---------------------------------------------------------------------- diff --git a/libminifi/include/LogAppenders.h b/libminifi/include/LogAppenders.h new file mode 100644 index 0000000..ef28bb8 --- /dev/null +++ b/libminifi/include/LogAppenders.h @@ -0,0 +1,298 @@ +/** + * + * 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. + */ +#ifndef LIBMINIFI_INCLUDE_LOGAPPENDERS_H_ +#define LIBMINIFI_INCLUDE_LOGAPPENDERS_H_ + +#include "BaseLogger.h" +#include "spdlog/sinks/null_sink.h" +#include "spdlog/sinks/ostream_sink.h" +#include <cxxabi.h> +#include "Configure.h" + +template<typename T> +static std::string getUniqueName() { + std::string name = LOG_NAME; + name += " -- "; + name += abi::__cxa_demangle(typeid(T).name(), 0, 0, 0); + spdlog::drop(name); + return name; +} + +/** + * Null appender sets a null sink, thereby performing no logging. + */ +class NullAppender: public BaseLogger { +public: + /** + * Base constructor that creates the null sink. + */ + explicit NullAppender() : + ::BaseLogger("off") { + auto null_sink = std::make_shared<spdlog::sinks::null_sink_st>(); + std::string unique_name = getUniqueName<NullAppender>(); + logger_ = std::make_shared<spdlog::logger>(unique_name, null_sink); + configured_level_ = off; + setLogLevel(); + } + + /** + * Move constructor for the null appender. + */ + explicit NullAppender(const NullAppender &&other) : + ::BaseLogger(std::move(other)) { + + } + +}; + +/** + * Basic output stream configuration that uses a supplied ostream + * + * Design : extends LoggerConfiguration using the logger and log level + * encapsulated within the base configuration class. + */ +class OutputStreamAppender: public BaseLogger { + +public: + + static const char *nifi_log_output_stream_error_stderr; + + /** + * Output stream move constructor. + */ + explicit OutputStreamAppender(const OutputStreamAppender &&other) : + ::BaseLogger(std::move(other)) { + + } + + /** + * Base constructor. Creates a ostream sink. + * @param stream incoming stream reference. + * @param config configuration. + */ + explicit OutputStreamAppender(Configure *config) : + ::BaseLogger("info") { + auto ostream_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>( + std::cout); + + std::string unique_name = getUniqueName<OutputStreamAppender>(); + logger_ = std::make_shared<spdlog::logger>(unique_name, ostream_sink); + + std::string use_std_err; + + if (NULL != config + && config->get(nifi_log_output_stream_error_stderr, + use_std_err)) { + + std::transform(use_std_err.begin(), use_std_err.end(), + use_std_err.begin(), ::tolower); + + if (use_std_err == "true") { + std::string err_unique_name = + getUniqueName<OutputStreamAppender>(); + auto error_ostream_sink = std::make_shared< + spdlog::sinks::ostream_sink_mt>(std::cerr); + stderr_ = std::make_shared<spdlog::logger>(err_unique_name, + error_ostream_sink); + } + } else { + stderr_ = nullptr; + } + + std::string log_level; + if (NULL != config + && config->get(BaseLogger::nifi_log_level, log_level)) { + setLogLevel(log_level); + } else{ + setLogLevel("info"); + } + + } + + /** + * Base constructor. Creates a ostream sink. + * @param stream incoming stream reference. + * @param config configuration. + */ + OutputStreamAppender(std::ostream &stream, Configure *config) : + ::BaseLogger("info") { + auto ostream_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>( + stream); + std::string unique_name = getUniqueName<OutputStreamAppender>(); + logger_ = std::make_shared<spdlog::logger>(unique_name, ostream_sink); + + stderr_ = nullptr; + + std::string log_level; + if (NULL != config + && config->get(BaseLogger::nifi_log_level, log_level)) { + setLogLevel(log_level); + } else { + setLogLevel("info"); + } + + } + +protected: + +}; + +/** + * Rolling configuration + * Design : extends LoggerConfiguration using the logger and log level + * encapsulated within the base configuration class. + */ +class RollingAppender: public BaseLogger { +public: + static const char *nifi_log_rolling_apender_file; + static const char *nifi_log_rolling_appender_max_files; + static const char *nifi_log_rolling_appender_max_file_size; + + /** + * RollingAppenderConfiguration move constructor. + */ + explicit RollingAppender(const RollingAppender&& other) : + ::BaseLogger(std::move(other)), max_files_( + std::move(other.max_files_)), file_name_( + std::move(other.file_name_)), max_file_size_( + std::move(other.max_file_size_)) { + } + /** + * Base Constructor. + * @param config pointer to the configuration for this instance. + */ + explicit RollingAppender(Configure * config = 0) : + ::BaseLogger("info") { + std::string file_name = ""; + if (NULL != config + && config->get(nifi_log_rolling_apender_file, file_name)) { + file_name_ = file_name; + } else{ + file_name_ = LOG_FILE_NAME; + } + + std::string max_files = ""; + if (NULL != config + && config->get(nifi_log_rolling_appender_max_files, + max_files)) { + try { + max_files_ = std::stoi(max_files); + } catch (const std::invalid_argument &ia) { + max_files_ = DEFAULT_LOG_FILE_NUMBER; + } catch (const std::out_of_range &oor) { + max_files_ = DEFAULT_LOG_FILE_NUMBER; + } + } else { + max_files_ = DEFAULT_LOG_FILE_NUMBER; + } + + std::string max_file_size = ""; + if (NULL != config + && config->get(nifi_log_rolling_appender_max_file_size, + max_file_size)) { + try { + max_file_size_ = std::stoi(max_file_size); + } catch (const std::invalid_argument &ia) { + max_file_size_ = DEFAULT_LOG_FILE_SIZE; + } catch (const std::out_of_range &oor) { + max_file_size_ = DEFAULT_LOG_FILE_SIZE; + } + } else { + max_file_size_ = DEFAULT_LOG_FILE_SIZE; + } + + std::string unique_name = getUniqueName<OutputStreamAppender>(); + logger_ = spdlog::rotating_logger_mt(unique_name, file_name_, + max_file_size_, max_files_); + + std::string log_level; + if (NULL != config + && config->get(BaseLogger::nifi_log_level, log_level)) { + setLogLevel(log_level); + } + } + + /** + * To maintain current functionality we will flush on write. + */ + void log_str(LOG_LEVEL_E level, const std::string &buffer) { + ::BaseLogger::log_str(level, buffer); + logger_->flush(); + } + +protected: + + /** + * file name. + */ + std::string file_name_; + /** + * maximum number of files to keep in the rotation. + */ + size_t max_files_; + /** + * Maximum file size per rotated file. + */ + size_t max_file_size_; + +}; + +class LogInstance { +public: + /** + * Returns a logger configuration based on + * the configuration within this instance. + * @param config configuration for this instance. + */ + static std::unique_ptr<BaseLogger> getConfiguredLogger(Configure *config) { + std::string appender = ""; + + if (config->get(BaseLogger::nifi_log_appender, appender)) { + std::transform(appender.begin(), appender.end(), appender.begin(), + ::tolower); + + if ("nullappender" == appender || "null appender" == appender + || "null" == appender) { + + return std::move( + std::unique_ptr<BaseLogger>(new NullAppender())); + + } else if ("rollingappender" == appender + || "rolling appender" == appender + || "rolling" == appender) { + + return std::move( + std::unique_ptr<BaseLogger>( + new RollingAppender(config))); + + } else if ("outputstream" == appender + || "outputstreamappender" == appender + || "outputstream appender" == appender) { + + return std::move( + std::unique_ptr<BaseLogger>( + new OutputStreamAppender(config))); + + } + } + return nullptr; + + } +}; + +#endif /* LIBMINIFI_INCLUDE_LOGAPPENDERS_H_ */ http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/LogAttribute.h ---------------------------------------------------------------------- diff --git a/libminifi/include/LogAttribute.h b/libminifi/include/LogAttribute.h index 2478c7a..429a594 100644 --- a/libminifi/include/LogAttribute.h +++ b/libminifi/include/LogAttribute.h @@ -122,7 +122,7 @@ protected: private: //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; }; #endif http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Logger.h ---------------------------------------------------------------------- diff --git a/libminifi/include/Logger.h b/libminifi/include/Logger.h index 91d0e72..81d4446 100644 --- a/libminifi/include/Logger.h +++ b/libminifi/include/Logger.h @@ -22,166 +22,179 @@ #define __LOGGER_H__ #include <string> +#include <atomic> +#include <memory> +#include <utility> #include <algorithm> #include <cstdio> -#include "spdlog/spdlog.h" +#include <iostream> -using spdlog::stdout_logger_mt; -using spdlog::rotating_logger_mt; -using spdlog::logger; - -#define LOG_BUFFER_SIZE 1024 -#define FILL_BUFFER char buffer[LOG_BUFFER_SIZE]; \ - va_list args; \ - va_start(args, format); \ - std::vsnprintf(buffer, LOG_BUFFER_SIZE,format, args); \ - va_end(args); - -//! 5M default log file size -#define DEFAULT_LOG_FILE_SIZE (5*1024*1024) -//! 3 log files rotation -#define DEFAULT_LOG_FILE_NUMBER 3 -#define LOG_NAME "minifi log" -#define LOG_FILE_NAME "minifi-app.log" - -typedef enum -{ - trace = 0, - debug = 1, - info = 2, - notice = 3, - warn = 4, - err = 5, - critical = 6, - alert = 7, - emerg = 8, - off = 9 -} LOG_LEVEL_E; - -//! Logger Class -class Logger { +#include "BaseLogger.h" +#include "spdlog/spdlog.h" +/** + * Logger class + * Design: Extends BaseLogger, leaving this class to be the facade to the underlying + * logging mechanism. Is a facade to BaseLogger's underlying log stream. This allows + * the underlying implementation to be replaced real time. + */ +class Logger: public BaseLogger { +protected: + struct singleton; public: - //! Get the singleton logger instance - static Logger * getLogger() { - if (!logger_) - logger_ = new Logger(); - return logger_; + /** + * Returns a shared pointer to the logger instance. + * Note that while there is no synchronization this is expected + * to be called and initialized first + * @returns shared pointer to the base logger. + */ + static std::shared_ptr<Logger> getLogger() { + + if (singleton_logger_ == nullptr) + singleton_logger_ = std::make_shared<Logger>(singleton { 0 }); + return singleton_logger_; + } + + /** + * Returns the log level for this instance. + */ + LOG_LEVEL_E getLogLevel() const { + return current_logger_.load()->getLogLevel(); } + + /** + * Sets the log level atomic and sets it + * within logger if it can + * @param level desired log level. + */ void setLogLevel(LOG_LEVEL_E level) { - if (spdlog_ == NULL) - return; - spdlog_->set_level((spdlog::level::level_enum) level); + current_logger_.load()->setLogLevel(level); } - void setLogLevel(const std::string &level,LOG_LEVEL_E defaultLevel = info ) - { - std::string logLevel = ""; - std::transform(level.begin(), level.end(), logLevel.end(), ::tolower); - - if (logLevel == "trace") { - setLogLevel(trace); - } else if (logLevel == "debug") { - setLogLevel(debug); - } else if (logLevel == "info") { - setLogLevel(info); - } else if (logLevel == "notice") { - setLogLevel(notice); - } else if (logLevel == "warn") { - setLogLevel(warn); - } else if (logLevel == "error") { - setLogLevel(err); - } else if (logLevel == "critical") { - setLogLevel(critical); - } else if (logLevel == "alert") { - setLogLevel(alert); - } else if (logLevel == "emerg") { - setLogLevel(emerg); - } else if (logLevel == "off") { - setLogLevel(off); - } else { - setLogLevel(defaultLevel); - } + /** + * Sets the log level for this instance based on the string + * @param level desired log leve. + * @param defaultLevel default level if we cannot match level. + */ + void setLogLevel(const std::string &level, + LOG_LEVEL_E defaultLevel = info) { + current_logger_.load()->setLogLevel(level, info); } - //! Destructor - ~Logger() {} + + void updateLogger(std::unique_ptr<BaseLogger> logger) { + + if (logger == nullptr ) + return; + current_logger_.store(logger.release()); + } + /** * @brief Log error message * @param format format string ('man printf' for syntax) * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match */ - void log_error(const char *const format, ...) { - if(spdlog_ == NULL || !spdlog_->should_log(spdlog::level::level_enum::err)) + void log_error(const char * const format, ...) { + if (!current_logger_.load()->shouldLog(err)) return; FILL_BUFFER - spdlog_->error(buffer); + current_logger_.load()->log_str(err, buffer); } /** * @brief Log warn message * @param format format string ('man printf' for syntax) * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match */ - void log_warn(const char *const format, ...) { - if(spdlog_ == NULL || !spdlog_->should_log(spdlog::level::level_enum::warn)) + void log_warn(const char * const format, ...) { + if (!current_logger_.load()->shouldLog(warn)) return; FILL_BUFFER - spdlog_->warn(buffer); + current_logger_.load()->log_str(warn, buffer); } /** * @brief Log info message * @param format format string ('man printf' for syntax) * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match */ - void log_info(const char *const format, ...) { - if(spdlog_ == NULL || !spdlog_->should_log(spdlog::level::level_enum::info)) + void log_info(const char * const format, ...) { + if (!current_logger_.load()->shouldLog(info)) return; FILL_BUFFER - spdlog_->info(buffer); + current_logger_.load()->log_str(info, buffer); } /** * @brief Log debug message * @param format format string ('man printf' for syntax) * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match */ - void log_debug(const char *const format, ...) { - if(spdlog_ == NULL || !spdlog_->should_log(spdlog::level::level_enum::debug)) + void log_debug(const char * const format, ...) { + + if (!current_logger_.load()->shouldLog(debug)) return; FILL_BUFFER - spdlog_->debug(buffer); + current_logger_.load()->log_str(debug, buffer); } /** * @brief Log trace message * @param format format string ('man printf' for syntax) * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match */ - void log_trace(const char *const format, ...) { - if(spdlog_ == NULL || !spdlog_->should_log(spdlog::level::level_enum::trace)) + void log_trace(const char * const format, ...) { + + if (!current_logger_.load()->shouldLog(trace)) return; FILL_BUFFER - spdlog_->trace(buffer); + current_logger_.load()->log_str(trace, buffer); } -protected: + /** + * @brief Log message + * @param format format string ('man printf' for syntax) + * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match + */ + virtual void log_str(LOG_LEVEL_E level, const std::string &buffer) { + current_logger_.load()->log_str(level, buffer); + } -private: - // Prevent default copy constructor and assignment operation - // Only support pass by reference or pointer - Logger(const Logger &parent); - Logger &operator=(const Logger &parent); - //! Constructor - /*! - * Create a logger - * */ - Logger(const std::string logger_name = LOG_NAME, const std::string filename = LOG_FILE_NAME, size_t max_file_size = DEFAULT_LOG_FILE_SIZE, size_t max_files = DEFAULT_LOG_FILE_NUMBER, bool force_flush = true) { - spdlog_ = rotating_logger_mt(logger_name, filename, max_file_size, max_files); - spdlog_->set_level((spdlog::level::level_enum) debug); + //! Destructor + ~Logger() { } - //! spdlog - std::shared_ptr<logger> spdlog_; - //! Singleton logger instance - static Logger *logger_; + explicit Logger(const singleton &a) { + + /** + * flush on info to maintain current functionality + */ + std::shared_ptr<spdlog::logger> defaultsink = spdlog::rotating_logger_mt(LOG_NAME, + LOG_FILE_NAME, + DEFAULT_LOG_FILE_SIZE, DEFAULT_LOG_FILE_NUMBER); + defaultsink->flush_on(spdlog::level::level_enum::info); + + std::unique_ptr<BaseLogger> new_logger_ = std::unique_ptr<BaseLogger>( + new BaseLogger("info", defaultsink)); + + new_logger_->setLogLevel(info); + current_logger_.store(new_logger_.release()); + } + + Logger(const Logger &parent) = delete; + Logger &operator=(const Logger &parent) = delete; + +protected: + + /** + * Allows for a null constructor above so that we can have a public constructor that + * effectively limits us to being a singleton by having a protected argument in the constructor + */ + struct singleton { + explicit singleton(int) { + } + }; + + std::atomic<BaseLogger*> current_logger_; + +//! Singleton logger instance + static std::shared_ptr<Logger> singleton_logger_; }; #endif http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ProcessContext.h ---------------------------------------------------------------------- diff --git a/libminifi/include/ProcessContext.h b/libminifi/include/ProcessContext.h index 469c87e..585e187 100644 --- a/libminifi/include/ProcessContext.h +++ b/libminifi/include/ProcessContext.h @@ -106,7 +106,7 @@ private: //! Processor Processor *_processor; //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; }; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ProcessGroup.h ---------------------------------------------------------------------- diff --git a/libminifi/include/ProcessGroup.h b/libminifi/include/ProcessGroup.h index 28661ae..dbff7b0 100644 --- a/libminifi/include/ProcessGroup.h +++ b/libminifi/include/ProcessGroup.h @@ -29,11 +29,11 @@ #include <algorithm> #include <set> -#include "Logger.h" #include "Processor.h" #include "Exception.h" #include "TimerDrivenSchedulingAgent.h" #include "EventDrivenSchedulingAgent.h" +#include "Logger.h" //! Process Group Type enum ProcessGroupType @@ -175,7 +175,7 @@ private: //! Mutex for protection std::mutex mtx_; //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; // Prevent default copy constructor and assignment operation // Only support pass by reference or pointer ProcessGroup(const ProcessGroup &parent); http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ProcessSession.h ---------------------------------------------------------------------- diff --git a/libminifi/include/ProcessSession.h b/libminifi/include/ProcessSession.h index 7146553..6f01506 100644 --- a/libminifi/include/ProcessSession.h +++ b/libminifi/include/ProcessSession.h @@ -29,11 +29,11 @@ #include <algorithm> #include <set> -#include "Logger.h" #include "Processor.h" #include "ProcessContext.h" #include "FlowFileRecord.h" #include "Exception.h" +#include "Logger.h" #include "Provenance.h" //! ProcessSession Class @@ -121,7 +121,7 @@ private: //! ProcessContext ProcessContext *_processContext; //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; //! Provenance Report ProvenanceReporter *_provenanceReport; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Processor.h ---------------------------------------------------------------------- diff --git a/libminifi/include/Processor.h b/libminifi/include/Processor.h index b675b7c..1634bc0 100644 --- a/libminifi/include/Processor.h +++ b/libminifi/include/Processor.h @@ -354,7 +354,7 @@ private: //! Check all incoming connections for work bool isWorkAvailable(); //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; // Prevent default copy constructor and assignment operation // Only support pass by reference or pointer Processor(const Processor &parent); http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Property.h ---------------------------------------------------------------------- diff --git a/libminifi/include/Property.h b/libminifi/include/Property.h index 93f9c0e..bf33b35 100644 --- a/libminifi/include/Property.h +++ b/libminifi/include/Property.h @@ -244,7 +244,6 @@ public: return false; } - protected: //! Name std::string _name; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Provenance.h ---------------------------------------------------------------------- diff --git a/libminifi/include/Provenance.h b/libminifi/include/Provenance.h index 10945c3..52489fc 100644 --- a/libminifi/include/Provenance.h +++ b/libminifi/include/Provenance.h @@ -451,7 +451,7 @@ protected: private: //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; // Prevent default copy constructor and assignment operation // Only support pass by reference or pointer @@ -555,7 +555,7 @@ private: //! Incoming connection Iterator std::set<ProvenanceEventRecord *> _events; //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; // Prevent default copy constructor and assignment operation // Only support pass by reference or pointer @@ -710,7 +710,7 @@ private: //! repository directory std::string _directory; //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; //! Configure //! max db entry life time Configure *configure_; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/PutFile.h ---------------------------------------------------------------------- diff --git a/libminifi/include/PutFile.h b/libminifi/include/PutFile.h index bf48f79..015605e 100644 --- a/libminifi/include/PutFile.h +++ b/libminifi/include/PutFile.h @@ -69,7 +69,7 @@ public: bool commit(); private: - Logger *logger_; + std::shared_ptr<Logger> logger_; std::ofstream _tmpFileOs; bool _writeSucceeded = false; std::string _tmpFile; @@ -80,7 +80,7 @@ protected: private: //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; bool putFile(ProcessSession *session, FlowFileRecord *flowFile, const std::string &tmpFile, const std::string &destFile); }; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/RealTimeDataCollector.h ---------------------------------------------------------------------- diff --git a/libminifi/include/RealTimeDataCollector.h b/libminifi/include/RealTimeDataCollector.h index 6458f6d..3b6d05f 100644 --- a/libminifi/include/RealTimeDataCollector.h +++ b/libminifi/include/RealTimeDataCollector.h @@ -113,7 +113,7 @@ private: int _realTimeSocket; int _batchSocket; //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; //! Mutex for protection std::mutex _mtx; //! Queued data size http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/RemoteProcessorGroupPort.h ---------------------------------------------------------------------- diff --git a/libminifi/include/RemoteProcessorGroupPort.h b/libminifi/include/RemoteProcessorGroupPort.h index 73e8ac2..05ecd17 100644 --- a/libminifi/include/RemoteProcessorGroupPort.h +++ b/libminifi/include/RemoteProcessorGroupPort.h @@ -27,23 +27,21 @@ #include "Site2SiteClientProtocol.h" //! RemoteProcessorGroupPort Class -class RemoteProcessorGroupPort : public Processor -{ +class RemoteProcessorGroupPort: public Processor { public: //! Constructor /*! * Create a new processor */ - RemoteProcessorGroupPort(std::string name, uuid_t uuid = NULL) - : Processor(name, uuid), direction_(SEND),transmitting_(false), peer_() - { - logger_ = Logger::getLogger(); - protocol_ = std::unique_ptr<Site2SiteClientProtocol>(new Site2SiteClientProtocol(0)); - protocol_->setPortId(uuid); + RemoteProcessorGroupPort(std::string name, uuid_t uuid = NULL) : + Processor(name, uuid), direction_(SEND), transmitting_(false), peer_() { + logger_ = Logger::getLogger(); + protocol_ = std::unique_ptr<Site2SiteClientProtocol>( + new Site2SiteClientProtocol(0)); + protocol_->setPortId(uuid); } //! Destructor - virtual ~RemoteProcessorGroupPort() - { + virtual ~RemoteProcessorGroupPort() { } //! Processor Name @@ -59,20 +57,17 @@ public: //! Initialize, over write by NiFi RemoteProcessorGroupPort virtual void initialize(void); //! Set Direction - void setDirection(TransferDirection direction) - { + void setDirection(TransferDirection direction) { direction_ = direction; if (direction_ == RECEIVE) this->setTriggerWhenEmpty(true); } //! Set Timeout - void setTimeOut(uint64_t timeout) - { + void setTimeOut(uint64_t timeout) { protocol_->setTimeOut(timeout); } //! SetTransmitting - void setTransmitting(bool val) - { + void setTransmitting(bool val) { transmitting_ = val; } @@ -80,8 +75,8 @@ protected: private: //! Logger - Logger *logger_; - + std::shared_ptr<Logger> logger_; + //! Peer Connection Site2SitePeer peer_; //! Peer Protocol std::unique_ptr<Site2SiteClientProtocol> protocol_; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ResourceClaim.h ---------------------------------------------------------------------- diff --git a/libminifi/include/ResourceClaim.h b/libminifi/include/ResourceClaim.h index dcbb558..1dd2704 100644 --- a/libminifi/include/ResourceClaim.h +++ b/libminifi/include/ResourceClaim.h @@ -83,7 +83,7 @@ private: //! Configure Configure *configure_; //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; // Prevent default copy constructor and assignment operation // Only support pass by reference or pointer ResourceClaim(const ResourceClaim &parent); http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/SchedulingAgent.h ---------------------------------------------------------------------- diff --git a/libminifi/include/SchedulingAgent.h b/libminifi/include/SchedulingAgent.h index c814fa3..f6d5a1c 100644 --- a/libminifi/include/SchedulingAgent.h +++ b/libminifi/include/SchedulingAgent.h @@ -31,6 +31,7 @@ #include "Logger.h" #include "Configure.h" #include "FlowFileRecord.h" +#include "Logger.h" #include "Processor.h" #include "ProcessContext.h" @@ -75,7 +76,7 @@ public: protected: //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; //! Configure Configure *configure_; //! Mutex for protection http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Site2SiteClientProtocol.h ---------------------------------------------------------------------- diff --git a/libminifi/include/Site2SiteClientProtocol.h b/libminifi/include/Site2SiteClientProtocol.h index fc1c411..444eed5 100644 --- a/libminifi/include/Site2SiteClientProtocol.h +++ b/libminifi/include/Site2SiteClientProtocol.h @@ -34,11 +34,11 @@ #include <thread> #include <algorithm> #include <uuid/uuid.h> -#include "Logger.h" #include "Configure.h" #include "Property.h" #include "Site2SitePeer.h" #include "FlowFileRecord.h" +#include "Logger.h" #include "ProcessContext.h" #include "ProcessSession.h" #include "io/CRCStream.h" @@ -588,7 +588,7 @@ private: //! Mutex for protection std::mutex _mtx; //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; //! Configure Configure *configure_; //! Batch Count http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Site2SitePeer.h ---------------------------------------------------------------------- diff --git a/libminifi/include/Site2SitePeer.h b/libminifi/include/Site2SitePeer.h index bd49e55..e89bb74 100644 --- a/libminifi/include/Site2SitePeer.h +++ b/libminifi/include/Site2SitePeer.h @@ -37,6 +37,7 @@ #include "utils/TimeUtil.h" + static const char MAGIC_BYTES[] = { 'N', 'i', 'F', 'i' }; //! Site2SitePeer Class @@ -251,7 +252,7 @@ private: //! socket timeout; std::atomic<uint64_t> _timeOut; //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; //! Configure Configure *configure_; //! Yield Period in Milliseconds http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/TailFile.h ---------------------------------------------------------------------- diff --git a/libminifi/include/TailFile.h b/libminifi/include/TailFile.h index c2fe555..d68748e 100644 --- a/libminifi/include/TailFile.h +++ b/libminifi/include/TailFile.h @@ -65,7 +65,7 @@ protected: private: //! Logger - Logger *logger_; + std::shared_ptr<Logger> logger_; std::string _fileLocation; //! Property Specified Tailed File Name std::string _fileName; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ThreadedSchedulingAgent.h ---------------------------------------------------------------------- diff --git a/libminifi/include/ThreadedSchedulingAgent.h b/libminifi/include/ThreadedSchedulingAgent.h index 78d56f2..5eb5d8a 100644 --- a/libminifi/include/ThreadedSchedulingAgent.h +++ b/libminifi/include/ThreadedSchedulingAgent.h @@ -20,8 +20,8 @@ #ifndef __THREADED_SCHEDULING_AGENT_H__ #define __THREADED_SCHEDULING_AGENT_H__ -#include "Logger.h" #include "Configure.h" +#include "Logger.h" #include "Processor.h" #include "ProcessContext.h" #include "SchedulingAgent.h" http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/io/ClientSocket.h ---------------------------------------------------------------------- diff --git a/libminifi/include/io/ClientSocket.h b/libminifi/include/io/ClientSocket.h index f73b0b4..7d3dbe2 100644 --- a/libminifi/include/io/ClientSocket.h +++ b/libminifi/include/io/ClientSocket.h @@ -222,7 +222,7 @@ protected: */ virtual short select_descriptor(const uint16_t msec); - Logger *logger_; + std::shared_ptr<Logger> logger_; addrinfo *addr_info_; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/io/TLSSocket.h ---------------------------------------------------------------------- diff --git a/libminifi/include/io/TLSSocket.h b/libminifi/include/io/TLSSocket.h index 909cfc2..56845fe 100644 --- a/libminifi/include/io/TLSSocket.h +++ b/libminifi/include/io/TLSSocket.h @@ -103,7 +103,7 @@ private: TLSContext(); - Logger *logger; + std::shared_ptr<Logger> logger_; Configure *configuration; SSL_CTX *ctx; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/src/BaseLogger.cpp ---------------------------------------------------------------------- diff --git a/libminifi/src/BaseLogger.cpp b/libminifi/src/BaseLogger.cpp new file mode 100644 index 0000000..1b3b2fd --- /dev/null +++ b/libminifi/src/BaseLogger.cpp @@ -0,0 +1,153 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "BaseLogger.h" + +// Logger related configuration items. +const char *BaseLogger::nifi_log_level = "nifi.log.level"; +const char *BaseLogger::nifi_log_appender = "nifi.log.appender"; + +/** + * @brief Log error message + * @param format format string ('man printf' for syntax) + * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match + */ + void BaseLogger::log_error(const char * const format, ...) { + if (logger_ == NULL || !logger_->should_log(spdlog::level::level_enum::err)) + return; + FILL_BUFFER + log_str(err,buffer); +} +/** + * @brief Log warn message + * @param format format string ('man printf' for syntax) + * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match + */ + void BaseLogger::log_warn(const char * const format, ...) { + if (logger_ == NULL + || !logger_->should_log(spdlog::level::level_enum::warn)) + return; + FILL_BUFFER + log_str(warn,buffer); +} +/** + * @brief Log info message + * @param format format string ('man printf' for syntax) + * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match + */ + void BaseLogger::log_info(const char * const format, ...) { + if (logger_ == NULL + || !logger_->should_log(spdlog::level::level_enum::info)) + return; + FILL_BUFFER + log_str(info,buffer); +} +/** + * @brief Log debug message + * @param format format string ('man printf' for syntax) + * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match + */ + void BaseLogger::log_debug(const char * const format, ...) { + + if (logger_ == NULL + || !logger_->should_log(spdlog::level::level_enum::debug)) + return; + FILL_BUFFER + log_str(debug,buffer); +} +/** + * @brief Log trace message + * @param format format string ('man printf' for syntax) + * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match + */ + void BaseLogger::log_trace(const char * const format, ...) { + + if (logger_ == NULL + || !logger_->should_log(spdlog::level::level_enum::trace)) + return; + FILL_BUFFER + log_str(debug,buffer); +} + +// overridables + +/** + * @brief Log error message + * @param format format string ('man printf' for syntax) + * @warning does not check @p log or @p format for null. Caller must ensure parameters and format string lengths match + */ +void BaseLogger::log_str(LOG_LEVEL_E level, const std::string &buffer) { + switch (level) { + case err: + case critical: + if (stderr_ != nullptr) { + stderr_->error(buffer); + } else { + logger_->error(buffer); + } + break; + case warn: + logger_->warn(buffer); + break; + case info: + logger_->info(buffer); + break; + case debug: + logger_->debug(buffer); + break; + case trace: + logger_->trace(buffer); + break; + case off: + break; + default: + logger_->info(buffer); + break; + } + +} + +void BaseLogger::setLogLevel(const std::string &level, + LOG_LEVEL_E defaultLevel) { + std::string logLevel = level; + std::transform(logLevel.begin(), logLevel.end(), logLevel.begin(), + ::tolower); + + if (logLevel == "trace") { + setLogLevel(trace); + } else if (logLevel == "debug") { + setLogLevel(debug); + } else if (logLevel == "info") { + setLogLevel(info); + } else if (logLevel == "warn") { + setLogLevel(warn); + } else if (logLevel == "error") { + setLogLevel(err); + } else if (logLevel == "critical") { + setLogLevel(critical); + } else if (logLevel == "off") { + setLogLevel(off); + } else { + setLogLevel(defaultLevel); + } +} + +void BaseLogger::set_error_logger(std::shared_ptr<spdlog::logger> other) { + stderr_ = std::move(other); +} + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/src/Configure.cpp ---------------------------------------------------------------------- diff --git a/libminifi/src/Configure.cpp b/libminifi/src/Configure.cpp index dac8408..94e33a1 100644 --- a/libminifi/src/Configure.cpp +++ b/libminifi/src/Configure.cpp @@ -25,7 +25,6 @@ const char *Configure::nifi_flow_configuration_file = "nifi.flow.configuration.f const char *Configure::nifi_administrative_yield_duration = "nifi.administrative.yield.duration"; const char *Configure::nifi_bored_yield_duration = "nifi.bored.yield.duration"; const char *Configure::nifi_graceful_shutdown_seconds = "nifi.graceful.shutdown.seconds"; -const char *Configure::nifi_log_level = "nifi.log.level"; const char *Configure::nifi_server_name = "nifi.server.name"; const char *Configure::nifi_server_port = "nifi.server.port"; const char *Configure::nifi_server_report_interval= "nifi.server.report.interval"; @@ -39,6 +38,7 @@ const char *Configure::nifi_security_client_private_key = "nifi.security.client. const char *Configure::nifi_security_client_pass_phrase = "nifi.security.client.pass.phrase"; const char *Configure::nifi_security_client_ca_certificate = "nifi.security.client.ca.certificate"; + //! Get the config value bool Configure::get(std::string key, std::string &value) { http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/src/FlowFileRecord.cpp ---------------------------------------------------------------------- diff --git a/libminifi/src/FlowFileRecord.cpp b/libminifi/src/FlowFileRecord.cpp index 1d509f5..362602e 100644 --- a/libminifi/src/FlowFileRecord.cpp +++ b/libminifi/src/FlowFileRecord.cpp @@ -27,8 +27,9 @@ #include <cstdio> #include "FlowFileRecord.h" -#include "Relationship.h" + #include "Logger.h" +#include "Relationship.h" std::atomic<uint64_t> FlowFileRecord::_localFlowSeqNumber(0); http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/src/LogAppenders.cpp ---------------------------------------------------------------------- diff --git a/libminifi/src/LogAppenders.cpp b/libminifi/src/LogAppenders.cpp new file mode 100644 index 0000000..c90588d --- /dev/null +++ b/libminifi/src/LogAppenders.cpp @@ -0,0 +1,25 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../include/LogAppenders.h" + +const char *OutputStreamAppender::nifi_log_output_stream_error_stderr="nifi.log.outputstream.appender.error.stderr"; + +const char *RollingAppender::nifi_log_rolling_apender_file = "nifi.log.rolling.appender.file"; +const char *RollingAppender::nifi_log_rolling_appender_max_files = "nifi.log.rolling.appender.max.files"; +const char *RollingAppender::nifi_log_rolling_appender_max_file_size = "nifi.log.rolling.appender.max.file_size"; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/src/Logger.cpp ---------------------------------------------------------------------- diff --git a/libminifi/src/Logger.cpp b/libminifi/src/Logger.cpp index fb3023d..e90667d 100644 --- a/libminifi/src/Logger.cpp +++ b/libminifi/src/Logger.cpp @@ -17,11 +17,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "../include/Logger.h" + #include <vector> #include <queue> #include <map> -#include "Logger.h" -Logger *Logger::logger_(NULL); +std::shared_ptr<Logger> Logger::singleton_logger_(nullptr); http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/src/Provenance.cpp ---------------------------------------------------------------------- diff --git a/libminifi/src/Provenance.cpp b/libminifi/src/Provenance.cpp index ace3b45..ff4d8f5 100644 --- a/libminifi/src/Provenance.cpp +++ b/libminifi/src/Provenance.cpp @@ -23,8 +23,9 @@ #include "io/DataStream.h" #include "io/Serializable.h" #include "Provenance.h" -#include "Relationship.h" + #include "Logger.h" +#include "Relationship.h" #include "FlowController.h" //! DeSerialize http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/src/io/TLSSocket.cpp ---------------------------------------------------------------------- diff --git a/libminifi/src/io/TLSSocket.cpp b/libminifi/src/io/TLSSocket.cpp index b38214e..b5fa596 100644 --- a/libminifi/src/io/TLSSocket.cpp +++ b/libminifi/src/io/TLSSocket.cpp @@ -28,7 +28,7 @@ std::atomic<TLSContext*> TLSContext::context_instance; std::mutex TLSContext::context_mutex; TLSContext::TLSContext() : - error_value(0), ctx(0), logger(Logger::getLogger()), configuration( + error_value(0), ctx(0), logger_(Logger::getLogger()), configuration( Configure::getConfigure()) { } @@ -56,7 +56,7 @@ short TLSContext::initialize() { method = TLSv1_2_client_method(); ctx = SSL_CTX_new(method); if (ctx == NULL) { - logger->log_error("Could not create SSL context, error: %s.", + logger_->log_error("Could not create SSL context, error: %s.", std::strerror(errno)); error_value = TLS_ERROR_CONTEXT; return error_value; @@ -71,7 +71,7 @@ short TLSContext::initialize() { certificate) && configuration->get( Configure::nifi_security_client_private_key, privatekey))) { - logger->log_error( + logger_->log_error( "Certificate and Private Key PEM file not configured, error: %s.", std::strerror(errno)); error_value = TLS_ERROR_PEM_MISSING; @@ -80,7 +80,7 @@ short TLSContext::initialize() { // load certificates and private key in PEM format if (SSL_CTX_use_certificate_file(ctx, certificate.c_str(), SSL_FILETYPE_PEM) <= 0) { - logger->log_error("Could not create load certificate, error : %s", + logger_->log_error("Could not create load certificate, error : %s", std::strerror(errno)); error_value = TLS_ERROR_CERT_MISSING; return error_value; @@ -96,14 +96,14 @@ short TLSContext::initialize() { int retp = SSL_CTX_use_PrivateKey_file(ctx, privatekey.c_str(), SSL_FILETYPE_PEM); if (retp != 1) { - logger->log_error("Could not create load private key,%i on %s error : %s", + logger_->log_error("Could not create load private key,%i on %s error : %s", retp,privatekey.c_str(),std::strerror(errno)); error_value = TLS_ERROR_KEY_ERROR; return error_value; } // verify private key if (!SSL_CTX_check_private_key(ctx)) { - logger->log_error( + logger_->log_error( "Private key does not match the public certificate, error : %s", std::strerror(errno)); error_value = TLS_ERROR_KEY_ERROR; @@ -114,7 +114,7 @@ short TLSContext::initialize() { caCertificate)) { retp = SSL_CTX_load_verify_locations(ctx, caCertificate.c_str(), 0); if (retp==0) { - logger->log_error( + logger_->log_error( "Can not load CA certificate, Exiting, error : %s", std::strerror(errno)); error_value = TLS_ERROR_CERT_ERROR; @@ -122,7 +122,7 @@ short TLSContext::initialize() { } } - logger->log_info("Load/Verify Client Certificate OK."); + logger_->log_info("Load/Verify Client Certificate OK."); } return 0; } http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/TestBase.h ---------------------------------------------------------------------- diff --git a/libminifi/test/TestBase.h b/libminifi/test/TestBase.h index 4e7e73f..97c32e6 100644 --- a/libminifi/test/TestBase.h +++ b/libminifi/test/TestBase.h @@ -22,8 +22,8 @@ #include <cstdlib> #include "ResourceClaim.h" #include "catch.hpp" -#include "Logger.h" #include <vector> +#include "Logger.h" class LogTestController { http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/unit/CRCTests.cpp ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/CRCTests.cpp b/libminifi/test/unit/CRCTests.cpp new file mode 100644 index 0000000..197b5be --- /dev/null +++ b/libminifi/test/unit/CRCTests.cpp @@ -0,0 +1,81 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <string> +#include <vector> +#include "io/CRCStream.h" +#include "io/DataStream.h" +#include "../TestBase.h" + + +TEST_CASE("Test CRC1", "[testcrc1]") { + + BaseStream base; + CRCStream<BaseStream> test(&base); + test.writeData((uint8_t*)"cow",3); + REQUIRE(2580823964 == test.getCRC()); + + +} + +TEST_CASE("Test CRC2", "[testcrc2]") { + + BaseStream base; + CRCStream<BaseStream> test(&base); + std::string fox = "the quick brown fox jumped over the brown fox"; + std::vector<uint8_t> charvect(fox.begin(), fox.end()); + test.writeData(charvect,charvect.size()); + REQUIRE(1922388889 == test.getCRC()); + + +} + + +TEST_CASE("Test CRC3", "[testcrc3]") { + + BaseStream base; + CRCStream<BaseStream> test(&base); + uint64_t number=7; + test.write(number); + REQUIRE(4215687882 == test.getCRC()); + + +} + + +TEST_CASE("Test CRC4", "[testcrc4]") { + + BaseStream base; + CRCStream<BaseStream> test(&base); + uint32_t number=7; + test.write(number); + REQUIRE(3206564543 == test.getCRC()); + + +} + +TEST_CASE("Test CRC5", "[testcrc5]") { + + BaseStream base; + CRCStream<BaseStream> test(&base); + uint16_t number=7; + test.write(number); + REQUIRE(3753740124 == test.getCRC()); + + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/unit/CRCTests.h ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/CRCTests.h b/libminifi/test/unit/CRCTests.h deleted file mode 100644 index de96eee..0000000 --- a/libminifi/test/unit/CRCTests.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <string> -#include <vector> -#include "io/CRCStream.h" -#include "io/DataStream.h" -TEST_CASE("Test CRC1", "[testcrc1]") { - - BaseStream base; - CRCStream<BaseStream> test(&base); - test.writeData((uint8_t*)"cow",3); - REQUIRE(2580823964 == test.getCRC()); - - -} - -TEST_CASE("Test CRC2", "[testcrc2]") { - - BaseStream base; - CRCStream<BaseStream> test(&base); - std::string fox = "the quick brown fox jumped over the brown fox"; - std::vector<uint8_t> charvect(fox.begin(), fox.end()); - test.writeData(charvect,charvect.size()); - REQUIRE(1922388889 == test.getCRC()); - - -} - - -TEST_CASE("Test CRC3", "[testcrc3]") { - - BaseStream base; - CRCStream<BaseStream> test(&base); - uint64_t number=7; - test.write(number); - REQUIRE(4215687882 == test.getCRC()); - - -} - - -TEST_CASE("Test CRC4", "[testcrc4]") { - - BaseStream base; - CRCStream<BaseStream> test(&base); - uint32_t number=7; - test.write(number); - REQUIRE(3206564543 == test.getCRC()); - - -} - -TEST_CASE("Test CRC5", "[testcrc5]") { - - BaseStream base; - CRCStream<BaseStream> test(&base); - uint16_t number=7; - test.write(number); - REQUIRE(3753740124 == test.getCRC()); - - -} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/unit/LoggerTests.cpp ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/LoggerTests.cpp b/libminifi/test/unit/LoggerTests.cpp new file mode 100644 index 0000000..8359037 --- /dev/null +++ b/libminifi/test/unit/LoggerTests.cpp @@ -0,0 +1,143 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <memory> + +#include "../TestBase.h" +#include "../../include/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<BaseLogger> outputLogger = std::unique_ptr<BaseLogger>(new OutputStreamAppender(oss,0)); + std::shared_ptr<Logger> logger = Logger::getLogger(); + logger->updateLogger(std::move(outputLogger)); + logger->setLogLevel("trace"); + logger->log_info("hello world"); + + REQUIRE( true == contains(oss.str(),"[minifi log -- OutputStreamAppender] [info] hello world")); +} + +TEST_CASE("Test log Levels debug", "[ttl2]") { + std::ostringstream oss; + + std::unique_ptr<BaseLogger> outputLogger = std::unique_ptr<BaseLogger>(new OutputStreamAppender(oss,0)); + std::shared_ptr<Logger> logger = Logger::getLogger(); + logger->updateLogger(std::move(outputLogger)); + logger->setLogLevel("trace"); + logger->log_debug("hello world"); + + REQUIRE( true == contains(oss.str(),"[minifi log -- OutputStreamAppender] [debug] hello world")); +} + +TEST_CASE("Test log Levels trace", "[ttl3]") { + std::ostringstream oss; + + std::unique_ptr<BaseLogger> outputLogger = std::unique_ptr<BaseLogger>(new OutputStreamAppender(oss,0)); + std::shared_ptr<Logger> logger = Logger::getLogger(); + logger->updateLogger(std::move(outputLogger)); + logger->setLogLevel("trace"); + + logger->log_trace("hello world"); + + REQUIRE( true == contains(oss.str(),"[minifi log -- OutputStreamAppender] [trace] hello world")); +} + +TEST_CASE("Test log Levels error", "[ttl4]") { + std::ostringstream oss; + + std::unique_ptr<BaseLogger> outputLogger = std::unique_ptr<BaseLogger>(new OutputStreamAppender(oss,0)); + std::shared_ptr<Logger> logger = Logger::getLogger(); + logger->updateLogger(std::move(outputLogger)); + logger->setLogLevel("trace"); + + logger->log_error("hello world"); + + REQUIRE( true == contains(oss.str(),"[minifi log -- OutputStreamAppender] [error] hello world")); +} + +TEST_CASE("Test log Levels change", "[ttl5]") { + std::ostringstream oss; + + std::unique_ptr<BaseLogger> outputLogger = std::unique_ptr<BaseLogger>(new OutputStreamAppender(oss,0)); + std::shared_ptr<Logger> logger = Logger::getLogger(); + logger->updateLogger(std::move(outputLogger)); + logger->setLogLevel("trace"); + + logger->log_error("hello world"); + + REQUIRE( true == contains(oss.str(),"[minifi log -- 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() ); +} + +TEST_CASE("Test log LevelsConfigured", "[ttl6]") { + std::ostringstream oss; + + Configure *config = Configure::getConfigure(); + + config->set(BaseLogger::nifi_log_appender,"outputstreamappender"); + config->set(OutputStreamAppender::nifi_log_output_stream_error_stderr,"true"); + + std::shared_ptr<Logger> logger = Logger::getLogger(); + + auto oldrdbuf = std::cerr.rdbuf(); + std::cerr.rdbuf(oss.rdbuf()); + + std::unique_ptr<BaseLogger> newLogger =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 -- OutputStreamAppender] [error] hello world")); + + std::cerr.rdbuf(oldrdbuf); + + config->set(BaseLogger::nifi_log_appender,"nullappender"); + + newLogger =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"); +// logger->log_error("hello world"); + + REQUIRE( 0 == oss.str().length() ); + +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/unit/ProcessorTests.cpp ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/ProcessorTests.cpp b/libminifi/test/unit/ProcessorTests.cpp new file mode 100644 index 0000000..955d125 --- /dev/null +++ b/libminifi/test/unit/ProcessorTests.cpp @@ -0,0 +1,150 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <uuid/uuid.h> +#include <fstream> +#include "FlowController.h" +#include "ProvenanceTestHelper.h" +#include "../TestBase.h" +#include "GetFile.h" + + +TEST_CASE("Test Creation of GetFile", "[getfileCreate]"){ + GetFile processor("processorname"); + REQUIRE( processor.getName() == "processorname"); +} + + +TEST_CASE("Test Find file", "[getfileCreate2]"){ + + TestController testController; + + testController.enableDebug(); + + ProvenanceTestRepository repo; + TestFlowController controller(repo); + FlowControllerFactory::getFlowController( dynamic_cast<FlowController*>(&controller)); + + GetFile processor("getfileCreate2"); + + char format[] ="/tmp/gt.XXXXXX"; + char *dir = testController.createTempDirectory(format); + + + uuid_t processoruuid; + REQUIRE( true == processor.getUUID(processoruuid) ); + + Connection connection("getfileCreate2Connection"); + connection.setRelationship(Relationship("success","description")); + + // link the connections so that we can test results at the end for this + + connection.setSourceProcessor(&processor); + + + connection.setSourceProcessorUUID(processoruuid); + connection.setDestinationProcessorUUID(processoruuid); + + processor.addConnection(&connection); + REQUIRE( dir != NULL ); + + ProcessContext context(&processor); + context.setProperty(GetFile::Directory,dir); + ProcessSession session(&context); + + + REQUIRE( processor.getName() == "getfileCreate2"); + + FlowFileRecord *record; + processor.setScheduledState(ScheduledState::RUNNING); + processor.onTrigger(&context,&session); + + ProvenanceReporter *reporter = session.getProvenanceReporter(); + std::set<ProvenanceEventRecord*> records = reporter->getEvents(); + + record = session.get(); + REQUIRE( record== 0 ); + REQUIRE( records.size() == 0 ); + + std::fstream file; + std::stringstream ss; + ss << dir << "/" << "tstFile.ext"; + file.open(ss.str(),std::ios::out); + file << "tempFile"; + file.close(); + + processor.incrementActiveTasks(); + processor.setScheduledState(ScheduledState::RUNNING); + processor.onTrigger(&context,&session); + unlink(ss.str().c_str()); + rmdir(dir); + + reporter = session.getProvenanceReporter(); + + records = reporter->getEvents(); + + for(ProvenanceEventRecord *provEventRecord : records) + { + REQUIRE (provEventRecord->getComponentType() == processor.getName()); + } + session.commit(); + + FlowFileRecord *ffr = session.get(); + + ffr->getResourceClaim()->decreaseFlowFileRecordOwnedCount(); + + delete ffr; + + std::set<FlowFileRecord*> expiredFlows; + + REQUIRE( 2 == repo.getRepoMap().size() ); + + for(auto entry: repo.getRepoMap()) + { + ProvenanceEventRecord newRecord; + newRecord.DeSerialize((uint8_t*)entry.second.data(),entry.second.length()); + + bool found = false; + for ( auto provRec : records) + { + if (provRec->getEventId() == newRecord.getEventId() ) + { + REQUIRE( provRec->getEventId() == newRecord.getEventId()); + REQUIRE( provRec->getComponentId() == newRecord.getComponentId()); + REQUIRE( provRec->getComponentType() == newRecord.getComponentType()); + REQUIRE( provRec->getDetails() == newRecord.getDetails()); + REQUIRE( provRec->getEventDuration() == newRecord.getEventDuration()); + found = true; + break; + } + } + if (!found) + throw std::runtime_error("Did not find record"); + + + } + + + + + + +} + + + + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/unit/ProcessorTests.h ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/ProcessorTests.h b/libminifi/test/unit/ProcessorTests.h deleted file mode 100644 index 0c17824..0000000 --- a/libminifi/test/unit/ProcessorTests.h +++ /dev/null @@ -1,154 +0,0 @@ -/** - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <uuid/uuid.h> -#include <fstream> -#include "FlowController.h" -#include "ProvenanceTests.h" -#include "../TestBase.h" -#include "GetFile.h" - -#ifndef PROCESSOR_TESTS -#define PROCESSOR_TESTS - -TEST_CASE("Test Creation of GetFile", "[getfileCreate]"){ - GetFile processor("processorname"); - REQUIRE( processor.getName() == "processorname"); -} - - -TEST_CASE("Test Find file", "[getfileCreate2]"){ - - TestController testController; - - testController.enableDebug(); - - ProvenanceTestRepository repo; - TestFlowController controller(repo); - FlowControllerFactory::getFlowController( dynamic_cast<FlowController*>(&controller)); - - GetFile processor("getfileCreate2"); - - char format[] ="/tmp/gt.XXXXXX"; - char *dir = testController.createTempDirectory(format); - - - uuid_t processoruuid; - REQUIRE( true == processor.getUUID(processoruuid) ); - - Connection connection("getfileCreate2Connection"); - connection.setRelationship(Relationship("success","description")); - - // link the connections so that we can test results at the end for this - - connection.setSourceProcessor(&processor); - - - connection.setSourceProcessorUUID(processoruuid); - connection.setDestinationProcessorUUID(processoruuid); - - processor.addConnection(&connection); - REQUIRE( dir != NULL ); - - ProcessContext context(&processor); - context.setProperty(GetFile::Directory,dir); - ProcessSession session(&context); - - - REQUIRE( processor.getName() == "getfileCreate2"); - - FlowFileRecord *record; - processor.setScheduledState(ScheduledState::RUNNING); - processor.onTrigger(&context,&session); - - ProvenanceReporter *reporter = session.getProvenanceReporter(); - std::set<ProvenanceEventRecord*> records = reporter->getEvents(); - - record = session.get(); - REQUIRE( record== 0 ); - REQUIRE( records.size() == 0 ); - - std::fstream file; - std::stringstream ss; - ss << dir << "/" << "tstFile.ext"; - file.open(ss.str(),std::ios::out); - file << "tempFile"; - file.close(); - - processor.incrementActiveTasks(); - processor.setScheduledState(ScheduledState::RUNNING); - processor.onTrigger(&context,&session); - unlink(ss.str().c_str()); - rmdir(dir); - - reporter = session.getProvenanceReporter(); - - records = reporter->getEvents(); - - for(ProvenanceEventRecord *provEventRecord : records) - { - REQUIRE (provEventRecord->getComponentType() == processor.getName()); - } - session.commit(); - - FlowFileRecord *ffr = session.get(); - - ffr->getResourceClaim()->decreaseFlowFileRecordOwnedCount(); - - delete ffr; - - std::set<FlowFileRecord*> expiredFlows; - - REQUIRE( 2 == repo.getRepoMap().size() ); - - for(auto entry: repo.getRepoMap()) - { - ProvenanceEventRecord newRecord; - newRecord.DeSerialize((uint8_t*)entry.second.data(),entry.second.length()); - - bool found = false; - for ( auto provRec : records) - { - if (provRec->getEventId() == newRecord.getEventId() ) - { - REQUIRE( provRec->getEventId() == newRecord.getEventId()); - REQUIRE( provRec->getComponentId() == newRecord.getComponentId()); - REQUIRE( provRec->getComponentType() == newRecord.getComponentType()); - REQUIRE( provRec->getDetails() == newRecord.getDetails()); - REQUIRE( provRec->getEventDuration() == newRecord.getEventDuration()); - found = true; - break; - } - } - if (!found) - throw std::runtime_error("Did not find record"); - - - } - - - - - - -} - - - -#endif - - http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/unit/PropertyTests.cpp ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/PropertyTests.cpp b/libminifi/test/unit/PropertyTests.cpp new file mode 100644 index 0000000..e9f1c19 --- /dev/null +++ b/libminifi/test/unit/PropertyTests.cpp @@ -0,0 +1,103 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "utils/StringUtils.h" +#include "../TestBase.h" +#include "Property.h" + +TEST_CASE("Test Boolean Conversion", "[testboolConversion]") { + + bool b; + REQUIRE(true == StringUtils::StringToBool("true",b)); + REQUIRE(true == StringUtils::StringToBool("True",b)); + REQUIRE(true == StringUtils::StringToBool("TRue",b)); + REQUIRE(true == StringUtils::StringToBool("tRUE",b)); + + REQUIRE(false == StringUtils::StringToBool("FALSE",b)); + REQUIRE(false == StringUtils::StringToBool("FALLSEY",b)); + REQUIRE(false == StringUtils::StringToBool("FaLSE",b)); + REQUIRE(false == StringUtils::StringToBool("false",b)); + +} + +TEST_CASE("Test Trimmer Right", "[testTrims]") { + + std::string test = "a quick brown fox jumped over the road\t\n"; + + REQUIRE(test.c_str()[test.length() - 1] == '\n'); + REQUIRE(test.c_str()[test.length() - 2] == '\t'); + test = StringUtils::trimRight(test); + + REQUIRE(test.c_str()[test.length() - 1] == 'd'); + REQUIRE(test.c_str()[test.length() - 2] == 'a'); + + test = "a quick brown fox jumped over the road\v\t"; + + REQUIRE(test.c_str()[test.length() - 1] == '\t'); + REQUIRE(test.c_str()[test.length() - 2] == '\v'); + + test = StringUtils::trimRight(test); + + REQUIRE(test.c_str()[test.length() - 1] == 'd'); + REQUIRE(test.c_str()[test.length() - 2] == 'a'); + + test = "a quick brown fox jumped over the road \f"; + + REQUIRE(test.c_str()[test.length() - 1] == '\f'); + REQUIRE(test.c_str()[test.length() - 2] == ' '); + + test = StringUtils::trimRight(test); + + REQUIRE(test.c_str()[test.length() - 1] == 'd'); + +} + +TEST_CASE("Test Trimmer Left", "[testTrims]") { + + std::string test = "\t\na quick brown fox jumped over the road\t\n"; + + REQUIRE(test.c_str()[0] == '\t'); + REQUIRE(test.c_str()[1] == '\n'); + + test = StringUtils::trimLeft(test); + + REQUIRE(test.c_str()[0] == 'a'); + REQUIRE(test.c_str()[1] == ' '); + + test = "\v\ta quick brown fox jumped over the road\v\t"; + + REQUIRE(test.c_str()[0] == '\v'); + REQUIRE(test.c_str()[1] == '\t'); + + test = StringUtils::trimLeft(test); + + REQUIRE(test.c_str()[0] == 'a'); + REQUIRE(test.c_str()[1] == ' '); + + test = " \fa quick brown fox jumped over the road \f"; + + REQUIRE(test.c_str()[0] == ' '); + REQUIRE(test.c_str()[1] == '\f'); + + test = StringUtils::trimLeft(test); + + REQUIRE(test.c_str()[0] == 'a'); + REQUIRE(test.c_str()[1] == ' '); + +} + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/unit/PropertyTests.h ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/PropertyTests.h b/libminifi/test/unit/PropertyTests.h deleted file mode 100644 index 2633de9..0000000 --- a/libminifi/test/unit/PropertyTests.h +++ /dev/null @@ -1,106 +0,0 @@ -/** - * - * 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. - */ -#ifndef LIBMINIFI_TEST_UNIT_PROPERTYTESTS_H_ -#define LIBMINIFI_TEST_UNIT_PROPERTYTESTS_H_ - -#include "utils/StringUtils.h" -#include "../TestBase.h" -#include "Property.h" - -TEST_CASE("Test Boolean Conversion", "[testboolConversion]") { - - bool b; - REQUIRE(true == StringUtils::StringToBool("true",b)); - REQUIRE(true == StringUtils::StringToBool("True",b)); - REQUIRE(true == StringUtils::StringToBool("TRue",b)); - REQUIRE(true == StringUtils::StringToBool("tRUE",b)); - - REQUIRE(false == StringUtils::StringToBool("FALSE",b)); - REQUIRE(false == StringUtils::StringToBool("FALLSEY",b)); - REQUIRE(false == StringUtils::StringToBool("FaLSE",b)); - REQUIRE(false == StringUtils::StringToBool("false",b)); - -} - -TEST_CASE("Test Trimmer Right", "[testTrims]") { - - std::string test = "a quick brown fox jumped over the road\t\n"; - - REQUIRE(test.c_str()[test.length() - 1] == '\n'); - REQUIRE(test.c_str()[test.length() - 2] == '\t'); - test = StringUtils::trimRight(test); - - REQUIRE(test.c_str()[test.length() - 1] == 'd'); - REQUIRE(test.c_str()[test.length() - 2] == 'a'); - - test = "a quick brown fox jumped over the road\v\t"; - - REQUIRE(test.c_str()[test.length() - 1] == '\t'); - REQUIRE(test.c_str()[test.length() - 2] == '\v'); - - test = StringUtils::trimRight(test); - - REQUIRE(test.c_str()[test.length() - 1] == 'd'); - REQUIRE(test.c_str()[test.length() - 2] == 'a'); - - test = "a quick brown fox jumped over the road \f"; - - REQUIRE(test.c_str()[test.length() - 1] == '\f'); - REQUIRE(test.c_str()[test.length() - 2] == ' '); - - test = StringUtils::trimRight(test); - - REQUIRE(test.c_str()[test.length() - 1] == 'd'); - -} - -TEST_CASE("Test Trimmer Left", "[testTrims]") { - - std::string test = "\t\na quick brown fox jumped over the road\t\n"; - - REQUIRE(test.c_str()[0] == '\t'); - REQUIRE(test.c_str()[1] == '\n'); - - test = StringUtils::trimLeft(test); - - REQUIRE(test.c_str()[0] == 'a'); - REQUIRE(test.c_str()[1] == ' '); - - test = "\v\ta quick brown fox jumped over the road\v\t"; - - REQUIRE(test.c_str()[0] == '\v'); - REQUIRE(test.c_str()[1] == '\t'); - - test = StringUtils::trimLeft(test); - - REQUIRE(test.c_str()[0] == 'a'); - REQUIRE(test.c_str()[1] == ' '); - - test = " \fa quick brown fox jumped over the road \f"; - - REQUIRE(test.c_str()[0] == ' '); - REQUIRE(test.c_str()[1] == '\f'); - - test = StringUtils::trimLeft(test); - - REQUIRE(test.c_str()[0] == 'a'); - REQUIRE(test.c_str()[1] == ' '); - -} - -#endif /* LIBMINIFI_TEST_UNIT_PROPERTYTESTS_H_ */
