http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/Properties.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/Properties.cpp b/libminifi/src/Properties.cpp
new file mode 100644
index 0000000..f877e7a
--- /dev/null
+++ b/libminifi/src/Properties.cpp
@@ -0,0 +1,148 @@
+/**
+ *
+ * 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 "properties/Properties.h"
+#include <string>
+#include "utils/StringUtils.h"
+#include "core/Core.h"
+#include "core/logging/LoggerConfiguration.h"
+
+namespace org {
+namespace apache {
+namespace nifi {
+namespace minifi {
+
+#define BUFFER_SIZE 512
+
+Properties::Properties() : 
logger_(logging::LoggerFactory<Properties>::getLogger()) {}
+
+// Get the config value
+bool Properties::get(std::string key, std::string &value) {
+  std::lock_guard<std::mutex> lock(mutex_);
+  auto it = properties_.find(key);
+
+  if (it != properties_.end()) {
+    value = it->second;
+    return true;
+  } else {
+    return false;
+  }
+}
+
+int Properties::getInt(const std::string &key, int default_value) {
+  std::lock_guard<std::mutex> lock(mutex_);
+  auto it = properties_.find(key);
+
+  if (it != properties_.end()) {
+    return std::atol(it->second.c_str());
+  } else {
+    return default_value;
+  }
+}
+
+// Parse one line in configure file like key=value
+void Properties::parseConfigureFileLine(char *buf) {
+  char *line = buf;
+
+  while ((line[0] == ' ') || (line[0] == '\t'))
+    ++line;
+
+  char first = line[0];
+  if ((first == '\0') || (first == '#') || (first == '\r') || (first == '\n')
+      || (first == '=')) {
+    return;
+  }
+
+  char *equal = strchr(line, '=');
+  if (equal == NULL) {
+    return;
+  }
+
+  equal[0] = '\0';
+  std::string key = line;
+
+  equal++;
+  while ((equal[0] == ' ') || (equal[0] == '\t'))
+    ++equal;
+
+  first = equal[0];
+  if ((first == '\0') || (first == '\r') || (first == '\n')) {
+    return;
+  }
+
+  std::string value = equal;
+  key = org::apache::nifi::minifi::utils::StringUtils::trimRight(key);
+  value = org::apache::nifi::minifi::utils::StringUtils::trimRight(value);
+  set(key, value);
+}
+
+// Load Configure File
+void Properties::loadConfigureFile(const char *fileName) {
+  std::string adjustedFilename;
+  if (fileName) {
+    // perform a naive determination if this is a relative path
+    if (fileName[0] != '/') {
+      adjustedFilename = adjustedFilename + getHome() + "/"
+          + fileName;
+    } else {
+      adjustedFilename += fileName;
+    }
+  }
+  char *path = NULL;
+  char full_path[PATH_MAX];
+  path = realpath(adjustedFilename.c_str(), full_path);
+  logger_->log_info("Using configuration file located at %s", path);
+
+  std::ifstream file(path, std::ifstream::in);
+  if (!file.good()) {
+    logger_->log_error("load configure file failed %s", path);
+    return;
+  }
+  this->clear();
+
+  char buf[BUFFER_SIZE];
+  for (file.getline(buf, BUFFER_SIZE); file.good();
+      file.getline(buf, BUFFER_SIZE)) {
+    parseConfigureFileLine(buf);
+  }
+}
+
+// Parse Command Line
+void Properties::parseCommandLine(int argc, char **argv) {
+  int i;
+  bool keyFound = false;
+  std::string key, value;
+
+  for (i = 1; i < argc; i++) {
+    if (argv[i][0] == '-' && argv[i][1] != '\0') {
+      keyFound = true;
+      key = &argv[i][1];
+      continue;
+    }
+    if (keyFound) {
+      value = argv[i];
+      set(key, value);
+      keyFound = false;
+    }
+  }
+  return;
+}
+
+} /* namespace minifi */
+} /* namespace nifi */
+} /* namespace apache */
+} /* namespace org */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/ResourceClaim.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/ResourceClaim.cpp b/libminifi/src/ResourceClaim.cpp
index b71032b..818e99b 100644
--- a/libminifi/src/ResourceClaim.cpp
+++ b/libminifi/src/ResourceClaim.cpp
@@ -17,12 +17,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <vector>
-#include <queue>
+#include <uuid/uuid.h>
+
 #include <map>
+#include <queue>
 #include <string>
+#include <vector>
 
 #include "ResourceClaim.h"
+#include "core/logging/LoggerConfiguration.h"
 
 namespace org {
 namespace apache {
@@ -35,7 +38,8 @@ char *ResourceClaim::default_directory_path = 
const_cast<char*>(DEFAULT_CONTENT_
 
 ResourceClaim::ResourceClaim(const std::string contentDirectory)
     : _id(_localResourceClaimNumber.load()),
-      _flowFileRecordOwnedCount(0) {
+      _flowFileRecordOwnedCount(0),
+      logger_(logging::LoggerFactory<ResourceClaim>::getLogger()) {
 
   char uuidStr[37];
 
@@ -47,7 +51,6 @@ ResourceClaim::ResourceClaim(const std::string 
contentDirectory)
   // Create the full content path for the content
   _contentFullPath = contentDirectory + "/" + uuidStr;
 
-  logger_ = logging::Logger::getLogger();
   logger_->log_debug("Resource Claim created %s", _contentFullPath.c_str());
 }
 

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/core/ClassLoader.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/core/ClassLoader.cpp 
b/libminifi/src/core/ClassLoader.cpp
index 77c4a85..72ac80c 100644
--- a/libminifi/src/core/ClassLoader.cpp
+++ b/libminifi/src/core/ClassLoader.cpp
@@ -15,17 +15,21 @@
  * limitations under the License.
  */
 
-#include "core/ClassLoader.h"
 #include <sys/mman.h>
 #include <memory>
 #include <string>
 
+#include "core/ClassLoader.h"
+#include "core/logging/LoggerConfiguration.h"
+
 namespace org {
 namespace apache {
 namespace nifi {
 namespace minifi {
 namespace core {
 
+ClassLoader::ClassLoader() : 
logger_(logging::LoggerFactory<ClassLoader>::getLogger()) {}
+
 ClassLoader &ClassLoader::getDefaultClassLoader() {
   static ClassLoader ret;
   // populate ret

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/core/ConfigurableComponent.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/core/ConfigurableComponent.cpp 
b/libminifi/src/core/ConfigurableComponent.cpp
index cf2089e..94fa599 100644
--- a/libminifi/src/core/ConfigurableComponent.cpp
+++ b/libminifi/src/core/ConfigurableComponent.cpp
@@ -22,24 +22,23 @@
 #include <string>
 #include <set>
 #include "core/Property.h"
-#include "core/logging/Logger.h"
+#include "core/logging/LoggerConfiguration.h"
 
 namespace org {
 namespace apache {
 namespace nifi {
 namespace minifi {
 namespace core {
-
-ConfigurableComponent::ConfigurableComponent(
-    std::shared_ptr<logging::Logger> logger)
-    : my_logger_(logger) {
+ConfigurableComponent::ConfigurableComponent()
+    : logger_(logging::LoggerFactory<ConfigurableComponent>::getLogger()) {
 }
 
 ConfigurableComponent::ConfigurableComponent(
     const ConfigurableComponent &&other)
     : properties_(std::move(other.properties_)),
-      my_logger_(std::move(other.my_logger_)) {
+      logger_(logging::LoggerFactory<ConfigurableComponent>::getLogger()) {
 }
+
 ConfigurableComponent::~ConfigurableComponent() {
 }
 
@@ -71,7 +70,7 @@ bool ConfigurableComponent::getProperty(const std::string 
name,
   if (it != properties_.end()) {
     Property item = it->second;
     value = item.getValue();
-    my_logger_->log_info("Processor %s property name %s value %s", name,
+    logger_->log_info("Processor %s property name %s value %s", name,
                          item.getName(), value);
     return true;
   } else {
@@ -93,7 +92,7 @@ bool ConfigurableComponent::setProperty(const std::string 
name,
     Property item = it->second;
     item.setValue(value);
     properties_[item.getName()] = item;
-    my_logger_->log_info("Component %s property name %s value %s", 
name.c_str(),
+    logger_->log_info("Component %s property name %s value %s", name.c_str(),
                          item.getName().c_str(), value.c_str());
     return true;
   } else {
@@ -116,7 +115,7 @@ bool ConfigurableComponent::updateProperty(const 
std::string &name,
     Property item = it->second;
     item.addValue(value);
     properties_[item.getName()] = item;
-    my_logger_->log_info("Component %s property name %s value %s", 
name.c_str(),
+    logger_->log_info("Component %s property name %s value %s", name.c_str(),
                          item.getName().c_str(), value.c_str());
     return true;
   } else {
@@ -138,7 +137,7 @@ bool ConfigurableComponent::setProperty(Property &prop, 
std::string value) {
     Property item = it->second;
     item.setValue(value);
     properties_[item.getName()] = item;
-    my_logger_->log_info("property name %s value %s", prop.getName().c_str(),
+    logger_->log_info("property name %s value %s", prop.getName().c_str(),
                          item.getName().c_str(), value.c_str());
     return true;
   } else {

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/core/Connectable.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/core/Connectable.cpp 
b/libminifi/src/core/Connectable.cpp
index 58ae6d4..5bd32e9 100644
--- a/libminifi/src/core/Connectable.cpp
+++ b/libminifi/src/core/Connectable.cpp
@@ -21,7 +21,7 @@
 #include <memory>
 #include <string>
 #include <set>
-#include "core/logging/Logger.h"
+#include "core/logging/LoggerConfiguration.h"
 #include "core/Relationship.h"
 
 namespace org {
@@ -32,12 +32,14 @@ namespace core {
 
 Connectable::Connectable(std::string name, uuid_t uuid)
     : CoreComponent(name, uuid),
-      max_concurrent_tasks_(1) {
+      max_concurrent_tasks_(1),
+      logger_(logging::LoggerFactory<Connectable>::getLogger()) {
 }
 
 Connectable::Connectable(const Connectable &&other)
     : CoreComponent(std::move(other)),
-      max_concurrent_tasks_(std::move(other.max_concurrent_tasks_)) {
+      max_concurrent_tasks_(std::move(other.max_concurrent_tasks_)),
+      logger_(std::move(other.logger_)) {
   has_work_ = other.has_work_.load();
   strategy_ = other.strategy_.load();
 }

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/core/FlowFile.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/core/FlowFile.cpp b/libminifi/src/core/FlowFile.cpp
index b3ab741..8c693bf 100644
--- a/libminifi/src/core/FlowFile.cpp
+++ b/libminifi/src/core/FlowFile.cpp
@@ -20,7 +20,7 @@
 #include <memory>
 #include <string>
 #include <set>
-#include "core/logging/Logger.h"
+#include "core/logging/LoggerConfiguration.h"
 namespace org {
 namespace apache {
 namespace nifi {
@@ -38,7 +38,8 @@ FlowFile::FlowFile()
       claim_(nullptr),
       marked_delete_(false),
       connection_(nullptr),
-      original_connection_() {
+      original_connection_(),
+      logger_(logging::LoggerFactory<FlowFile>::getLogger()) {
   entry_date_ = getTimeMillis();
   lineage_start_date_ = entry_date_;
 
@@ -49,8 +50,6 @@ FlowFile::FlowFile()
 
   uuid_unparse_lower(uuid_, uuidStr);
   uuid_str_ = uuidStr;
-
-  logger_ = logging::Logger::getLogger();
 }
 
 FlowFile::~FlowFile() {

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/core/ProcessGroup.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/core/ProcessGroup.cpp 
b/libminifi/src/core/ProcessGroup.cpp
index 01d3dbf..c33800d 100644
--- a/libminifi/src/core/ProcessGroup.cpp
+++ b/libminifi/src/core/ProcessGroup.cpp
@@ -29,6 +29,7 @@
 #include <chrono>
 #include <thread>
 #include "core/Processor.h"
+#include "core/logging/LoggerConfiguration.h"
 
 namespace org {
 namespace apache {
@@ -38,7 +39,8 @@ namespace core {
 
 ProcessGroup::ProcessGroup(ProcessGroupType type, std::string name, uuid_t 
uuid,
                            ProcessGroup *parent)
-    : name_(name),
+    : logger_(logging::LoggerFactory<ProcessGroup>::getLogger()),
+      name_(name),
       type_(type),
       parent_process_group_(parent) {
   if (!uuid)
@@ -50,7 +52,6 @@ ProcessGroup::ProcessGroup(ProcessGroupType type, std::string 
name, uuid_t uuid,
   yield_period_msec_ = 0;
   transmitting_ = false;
 
-  logger_ = logging::Logger::getLogger();
   logger_->log_info("ProcessGroup %s created", name_.c_str());
 }
 

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/core/Processor.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/core/Processor.cpp b/libminifi/src/core/Processor.cpp
index ac03fde..dbeb46f 100644
--- a/libminifi/src/core/Processor.cpp
+++ b/libminifi/src/core/Processor.cpp
@@ -36,6 +36,7 @@
 #include "core/ProcessSession.h"
 #include "core/ProcessSessionFactory.h"
 #include "../include/io/StreamFactory.h"
+#include "core/logging/LoggerConfiguration.h"
 
 namespace org {
 namespace apache {
@@ -44,8 +45,8 @@ namespace minifi {
 namespace core {
 
 Processor::Processor(std::string name, uuid_t uuid)
-    : Connectable(name, uuid),
-      ConfigurableComponent(logging::Logger::getLogger()) {
+    : Connectable(name, uuid), ConfigurableComponent(),
+    logger_(logging::LoggerFactory<Processor>::getLogger()) {
   has_work_.store(false);
   // Setup the default values
   state_ = DISABLED;
@@ -60,7 +61,6 @@ Processor::Processor(std::string name, uuid_t uuid)
   active_tasks_ = 0;
   yield_expiration_ = 0;
   incoming_connections_Iter = this->_incomingConnections.begin();
-  logger_ = logging::Logger::getLogger();
   logger_->log_info("Processor %s created UUID %s", name_.c_str(),
                     uuidStr_.c_str());
 }

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/core/ProcessorNode.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/core/ProcessorNode.cpp 
b/libminifi/src/core/ProcessorNode.cpp
index 8979e32..bf39738 100644
--- a/libminifi/src/core/ProcessorNode.cpp
+++ b/libminifi/src/core/ProcessorNode.cpp
@@ -25,8 +25,7 @@ namespace core {
 
 ProcessorNode::ProcessorNode(const std::shared_ptr<Connectable> processor)
     : processor_(processor),
-      Connectable(processor->getName(), 0),
-      ConfigurableComponent(logging::Logger::getLogger()) {
+      Connectable(processor->getName(), 0), ConfigurableComponent() {
   uuid_t copy;
   processor->getUUID(copy);
   setUUID(copy);
@@ -34,8 +33,7 @@ ProcessorNode::ProcessorNode(const 
std::shared_ptr<Connectable> processor)
 
 ProcessorNode::ProcessorNode(const ProcessorNode &other)
     : processor_(other.processor_),
-      Connectable(other.getName(), 0),
-      ConfigurableComponent(logging::Logger::getLogger()) {
+      Connectable(other.getName(), 0) {
   uuid_t copy;
   processor_->getUUID(copy);
   setUUID(copy);

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/core/logging/BaseLogger.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/core/logging/BaseLogger.cpp 
b/libminifi/src/core/logging/BaseLogger.cpp
deleted file mode 100644
index 9164270..0000000
--- a/libminifi/src/core/logging/BaseLogger.cpp
+++ /dev/null
@@ -1,107 +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 "core/logging/BaseLogger.h"
-#include <utility>
-#include <memory>
-#include <algorithm>
-#include <string>
-
-namespace org {
-namespace apache {
-namespace nifi {
-namespace minifi {
-namespace core {
-namespace logging {
-
-// Logger related configuration items.
-const char *BaseLogger::nifi_log_level = "nifi.log.level";
-const char *BaseLogger::nifi_log_appender = "nifi.log.appender";
-
-
-// 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);
-}
-
-} /* namespace logging */
-} /* namespace core */
-} /* namespace minifi */
-} /* namespace nifi */
-} /* namespace apache */
-} /* namespace org */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/core/logging/LogAppenders.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/core/logging/LogAppenders.cpp 
b/libminifi/src/core/logging/LogAppenders.cpp
deleted file mode 100644
index 1918a0d..0000000
--- a/libminifi/src/core/logging/LogAppenders.cpp
+++ /dev/null
@@ -1,42 +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 "core/logging/LogAppenders.h"
-namespace org {
-namespace apache {
-namespace nifi {
-namespace minifi {
-namespace core {
-namespace logging {
-
-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";
-
-} /* namespace logging */
-} /* namespace core */
-} /* namespace minifi */
-} /* namespace nifi */
-} /* namespace apache */
-} /* namespace org */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/core/logging/Logger.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/core/logging/Logger.cpp 
b/libminifi/src/core/logging/Logger.cpp
deleted file mode 100644
index 5c08fa8..0000000
--- a/libminifi/src/core/logging/Logger.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * @file Logger.cpp
- * Logger class implementation
- *
- * 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 "core/logging/Logger.h"
-
-#include <vector>
-#include <queue>
-#include <memory>
-#include <map>
-
-namespace org {
-namespace apache {
-namespace nifi {
-namespace minifi {
-namespace core {
-namespace logging {
-
-std::shared_ptr<Logger> Logger::singleton_logger_(nullptr);
-
-} /* namespace logging */
-} /* namespace core */
-} /* namespace minifi */
-} /* namespace nifi */
-} /* namespace apache */
-} /* namespace org */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/core/logging/LoggerConfiguration.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/core/logging/LoggerConfiguration.cpp 
b/libminifi/src/core/logging/LoggerConfiguration.cpp
new file mode 100644
index 0000000..4bb6615
--- /dev/null
+++ b/libminifi/src/core/logging/LoggerConfiguration.cpp
@@ -0,0 +1,254 @@
+/**
+ * @file Logger.cpp
+ * Logger class implementation
+ *
+ * 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 <algorithm>
+#include <vector>
+#include <queue>
+#include <memory>
+#include <map>
+#include <string>
+
+#include "core/Core.h"
+#include "core/logging/LoggerConfiguration.h"
+#include "utils/StringUtils.h"
+
+#include "spdlog/spdlog.h"
+#include "spdlog/sinks/stdout_sinks.h"
+#include "spdlog/sinks/null_sink.h"
+
+namespace org {
+namespace apache {
+namespace nifi {
+namespace minifi {
+namespace core {
+namespace logging {
+
+const char* LoggerConfiguration::spdlog_default_pattern = "[%Y-%m-%d 
%H:%M:%S.%e] [%n] [%l] %v";
+
+std::vector< std::string > LoggerProperties::get_keys_of_type(const 
std::string &type) {
+  std::vector<std::string> appenders;
+  std::string prefix = type + ".";
+  for (auto const & entry : properties_) {
+    if (entry.first.rfind(prefix, 0) == 0 &&
+      entry.first.find(".", prefix.length() + 1) == std::string::npos) {
+      appenders.push_back(entry.first);
+    }
+  }
+  return appenders;
+}
+
+LoggerConfiguration::LoggerConfiguration() : 
root_namespace_(create_default_root()), 
loggers(std::vector<std::shared_ptr<LoggerImpl>>()),
+                                             
formatter_(std::make_shared<spdlog::pattern_formatter>(spdlog_default_pattern)) 
{
+  logger_ = std::shared_ptr<LoggerImpl>(new 
LoggerImpl(core::getClassName<LoggerConfiguration>(), get_logger(nullptr, 
root_namespace_, core::getClassName<LoggerConfiguration>(), formatter_)));
+  loggers.push_back(logger_);
+}
+
+void LoggerConfiguration::initialize(const std::shared_ptr<LoggerProperties> 
&logger_properties)  {
+  std::lock_guard<std::mutex> lock(mutex);
+  root_namespace_ = initialize_namespaces(logger_properties);
+  std::string spdlog_pattern;
+  if (!logger_properties->get("spdlog.pattern", spdlog_pattern)) {
+    spdlog_pattern = spdlog_default_pattern;
+  }
+  formatter_ = std::make_shared<spdlog::pattern_formatter>(spdlog_pattern);
+  std::map<std::string, std::shared_ptr<spdlog::logger>> spdloggers;
+  for (auto const & logger_impl : loggers) {
+    std::shared_ptr<spdlog::logger> spdlogger;
+    auto it = spdloggers.find(logger_impl->name);
+    if (it == spdloggers.end()) {
+      spdlogger = get_logger(logger_, root_namespace_, logger_impl->name, 
formatter_, true);
+      spdloggers[logger_impl->name] = spdlogger;
+    } else {
+      spdlogger = it->second;
+    }
+    logger_impl->set_delegate(spdlogger);
+  }
+  logger_->log_debug("Set following pattern on loggers: %s", spdlog_pattern);
+}
+
+std::shared_ptr<Logger> LoggerConfiguration::getLogger(const std::string 
&name) {
+  std::lock_guard<std::mutex> lock(mutex);
+  std::shared_ptr<LoggerImpl> result = std::make_shared<LoggerImpl>(name, 
get_logger(logger_, root_namespace_, name, formatter_));
+  loggers.push_back(result);
+  return result;
+}
+
+std::shared_ptr<internal::LoggerNamespace> LoggerConfiguration::
+     initialize_namespaces(const std::shared_ptr<LoggerProperties> 
&logger_properties) {
+  std::map<std::string, std::shared_ptr<spdlog::sinks::sink>> sink_map = 
logger_properties->initial_sinks();
+
+  std::string appender_type = "appender";
+  for (auto const & appender_key : 
logger_properties->get_keys_of_type(appender_type)) {
+    std::string appender_name = appender_key.substr(appender_type.length() + 
1);
+    std::string appender_type;
+    if (!logger_properties->get(appender_key, appender_type)) {
+      appender_type = "stderr";
+    }
+    std::transform(appender_type.begin(), appender_type.end(), 
appender_type.begin(), ::tolower);
+
+    if ("nullappender" == appender_type || "null appender" == appender_type || 
"null" == appender_type) {
+      sink_map[appender_name] = 
std::make_shared<spdlog::sinks::null_sink_st>();
+    } else if ("rollingappender" == appender_type || "rolling appender" == 
appender_type || "rolling" == appender_type) {
+      std::string file_name = "";
+      if (!logger_properties->get(appender_key + ".file_name", file_name)) {
+        file_name = "minifi-app.log";
+      }
+
+      int max_files = 3;
+      std::string max_files_str = "";
+      if (logger_properties->get(appender_key + ".max_files", max_files_str)) {
+        try {
+          max_files = std::stoi(max_files_str);
+        } catch (const std::invalid_argument &ia) {
+        } catch (const std::out_of_range &oor) {}
+      }
+
+      int max_file_size = 5*1024*1024;
+      std::string max_file_size_str = "";
+      if (logger_properties->get(appender_key + ".max_file_size", 
max_file_size_str)) {
+        try {
+          max_file_size = std::stoi(max_file_size_str);
+        } catch (const std::invalid_argument &ia) {
+        } catch (const std::out_of_range &oor) {}
+      }
+      sink_map[appender_name] = 
std::make_shared<spdlog::sinks::rotating_file_sink_mt>(file_name, 
max_file_size, max_files);
+    } else if ("stdout" == appender_type) {
+      sink_map[appender_name] = spdlog::sinks::stdout_sink_mt::instance();
+    } else {
+      sink_map[appender_name] = spdlog::sinks::stderr_sink_mt::instance();
+    }
+  }
+
+  std::shared_ptr<internal::LoggerNamespace> root_namespace = 
std::make_shared<internal::LoggerNamespace>();
+  std::string logger_type = "logger";
+  for (auto const & logger_key : 
logger_properties->get_keys_of_type(logger_type)) {
+    std::string logger_def;
+    if (!logger_properties->get(logger_key, logger_def)) {
+      continue;
+    }
+    bool first = true;
+    spdlog::level::level_enum level = spdlog::level::info;
+    std::vector<std::shared_ptr<spdlog::sinks::sink>> sinks;
+    for (auto const & segment : utils::StringUtils::split(logger_def, ",")) {
+      std::string level_name = utils::StringUtils::trim(segment);
+      if (first) {
+        first = false;
+        std::transform(level_name.begin(), level_name.end(), 
level_name.begin(), ::tolower);
+        if ("trace" == level_name) {
+          level = spdlog::level::trace;
+        } else if ("debug" == level_name) {
+          level = spdlog::level::debug;
+        } else if ("warn" == level_name) {
+          level = spdlog::level::warn;
+        } else if ("critical" == level_name) {
+          level = spdlog::level::critical;
+        } else if ("error" == level_name) {
+          level = spdlog::level::err;
+        } else if ("off" == level_name) {
+          level = spdlog::level::off;
+        }
+      } else {
+        sinks.push_back(sink_map[level_name]);
+      }
+    }
+    std::shared_ptr<internal::LoggerNamespace> current_namespace = 
root_namespace;
+    if (logger_key != "logger.root") {
+      for (auto const & name : 
utils::StringUtils::split(logger_key.substr(logger_type.length() + 1,
+          logger_key.length() - logger_type.length()), "::")) {
+        auto child_pair = current_namespace->children.find(name);
+        std::shared_ptr<internal::LoggerNamespace> child;
+        if (child_pair == current_namespace->children.end()) {
+          child = std::make_shared<internal::LoggerNamespace>();
+          current_namespace->children[name] = child;
+        } else {
+          child = child_pair->second;
+        }
+        current_namespace = child;
+      }
+    }
+    current_namespace->level = level;
+    current_namespace->has_level = true;
+    current_namespace->sinks = sinks;
+  }
+  return root_namespace;
+}
+
+std::shared_ptr<spdlog::logger> 
LoggerConfiguration::get_logger(std::shared_ptr<Logger> logger, const 
std::shared_ptr<internal::LoggerNamespace> &root_namespace,
+                                                                const 
std::string &name, std::shared_ptr<spdlog::formatter> formatter, bool 
remove_if_present) {
+  std::shared_ptr<spdlog::logger> spdlogger = spdlog::get(name);
+  if (spdlogger) {
+    if (remove_if_present) {
+      spdlog::drop(name);
+    } else {
+      return spdlogger;
+    }
+  }
+  std::shared_ptr<internal::LoggerNamespace> current_namespace = 
root_namespace;
+  std::vector<std::shared_ptr<spdlog::sinks::sink>> sinks = 
root_namespace->sinks;
+  spdlog::level::level_enum level = root_namespace->level;
+  std::string current_namespace_str = "";
+  std::string sink_namespace_str = "root";
+  std::string level_namespace_str = "root";
+  for (auto const & name_segment : utils::StringUtils::split(name, "::")) {
+    current_namespace_str += name_segment;
+    auto child_pair = current_namespace->children.find(name_segment);
+    if (child_pair == current_namespace->children.end()) {
+      break;
+    }
+    current_namespace = child_pair->second;
+    if (current_namespace->sinks.size() > 0) {
+      sinks = current_namespace->sinks;
+      sink_namespace_str = current_namespace_str;
+    }
+    if (current_namespace->has_level) {
+      level = current_namespace->level;
+      level_namespace_str = current_namespace_str;
+    }
+    current_namespace_str += "::";
+  }
+  if (logger != nullptr) {
+    logger->log_debug("%s logger got sinks from namespace %s and level %s from 
namespace %s", name, sink_namespace_str, spdlog::level::level_names[level], 
level_namespace_str);
+  }
+  spdlogger = std::make_shared<spdlog::logger>(name, begin(sinks), end(sinks));
+  spdlogger->set_level(level);
+  spdlogger->set_formatter(formatter);
+  spdlogger->flush_on(std::max(spdlog::level::info, current_namespace->level));
+  try {
+    spdlog::register_logger(spdlogger);
+  } catch (const spdlog::spdlog_ex &ex) {
+    // Ignore as someone else beat us to registration, we should get the one 
they made below
+  }
+  return spdlog::get(name);
+}
+
+std::shared_ptr<internal::LoggerNamespace> 
LoggerConfiguration::create_default_root() {
+  std::shared_ptr<internal::LoggerNamespace> result = 
std::make_shared<internal::LoggerNamespace>();
+  result->sinks = std::vector<std::shared_ptr<spdlog::sinks::sink>>();
+  result->sinks.push_back(spdlog::sinks::stderr_sink_mt::instance());
+  result->level = spdlog::level::info;
+  return result;
+}
+
+} /* namespace logging */
+} /* namespace core */
+} /* namespace minifi */
+} /* namespace nifi */
+} /* namespace apache */
+} /* namespace org */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/io/ClientSocket.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/io/ClientSocket.cpp 
b/libminifi/src/io/ClientSocket.cpp
index 7a4a191..bd99bc7 100644
--- a/libminifi/src/io/ClientSocket.cpp
+++ b/libminifi/src/io/ClientSocket.cpp
@@ -31,6 +31,7 @@
 #include <iostream>
 #include <string>
 #include "io/validation.h"
+#include "core/logging/LoggerConfiguration.h"
 
 namespace org {
 namespace apache {
@@ -38,8 +39,6 @@ namespace nifi {
 namespace minifi {
 namespace io {
 
-char *Socket::HOSTNAME = const_cast<char*>(Socket::getMyHostName(0).c_str());
-
 Socket::Socket(const std::shared_ptr<SocketContext> &context, const 
std::string &hostname, const uint16_t port,
                const uint16_t listeners = -1)
     : requested_hostname_(hostname),
@@ -48,8 +47,8 @@ Socket::Socket(const std::shared_ptr<SocketContext> &context, 
const std::string
       socket_file_descriptor_(-1),
       socket_max_(0),
       listeners_(listeners),
-      canonical_hostname_("") {
-  logger_ = logging::Logger::getLogger();
+      canonical_hostname_(""),
+      logger_(logging::LoggerFactory<Socket>::getLogger()) {
   FD_ZERO(&total_list_);
   FD_ZERO(&read_fds_);
 }
@@ -67,8 +66,8 @@ Socket::Socket(const Socket &&other)
       listeners_(other.listeners_),
       total_list_(other.total_list_),
       read_fds_(other.read_fds_),
-      canonical_hostname_(std::move(other.canonical_hostname_)) {
-  logger_ = logging::Logger::getLogger();
+      canonical_hostname_(std::move(other.canonical_hostname_)),
+      logger_(std::move(other.logger_)) {
 }
 
 Socket::~Socket() {

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/io/tls/TLSSocket.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/io/tls/TLSSocket.cpp 
b/libminifi/src/io/tls/TLSSocket.cpp
index 4c3bf51..b269cef 100644
--- a/libminifi/src/io/tls/TLSSocket.cpp
+++ b/libminifi/src/io/tls/TLSSocket.cpp
@@ -25,6 +25,7 @@
 #include "properties/Configure.h"
 #include "utils/StringUtils.h"
 #include "core/Property.h"
+#include "core/logging/LoggerConfiguration.h"
 
 namespace org {
 namespace apache {
@@ -39,7 +40,7 @@ TLSContext::TLSContext(const std::shared_ptr<Configure> 
&configure)
     : SocketContext(configure),
       error_value(0),
       ctx(0),
-      logger_(logging::Logger::getLogger()),
+      logger_(logging::LoggerFactory<TLSContext>::getLogger()),
       configure_(configure) {
 }
 /**
@@ -152,20 +153,20 @@ TLSSocket::TLSSocket(const std::shared_ptr<TLSContext> 
&context,
                      const std::string &hostname, const uint16_t port,
                      const uint16_t listeners)
     : Socket(context, hostname, port, listeners),
-      ssl(0) {
+      ssl(0), logger_(logging::LoggerFactory<TLSSocket>::getLogger()) {
   context_ = context;
 }
 
 TLSSocket::TLSSocket(const std::shared_ptr<TLSContext> &context,
                      const std::string &hostname, const uint16_t port)
     : Socket(context, hostname, port, 0),
-      ssl(0) {
+      ssl(0), logger_(logging::LoggerFactory<TLSSocket>::getLogger()) {
   context_ = context;
 }
 
 TLSSocket::TLSSocket(const TLSSocket &&d)
     : Socket(std::move(d)),
-      ssl(0) {
+      ssl(0), logger_(std::move(d.logger_)) {
   context_ = d.context_;
 }
 

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/processors/ListenHTTP.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/processors/ListenHTTP.cpp 
b/libminifi/src/processors/ListenHTTP.cpp
index 5c4a6bb..9fce69a 100644
--- a/libminifi/src/processors/ListenHTTP.cpp
+++ b/libminifi/src/processors/ListenHTTP.cpp
@@ -34,6 +34,7 @@
 #include "core/ProcessContext.h"
 #include "core/ProcessSession.h"
 #include "core/ProcessSessionFactory.h"
+#include "core/logging/LoggerConfiguration.h"
 
 namespace org {
 namespace apache {
@@ -75,7 +76,7 @@ core::Relationship ListenHTTP::Success("success",
                                        "All files are routed to success");
 
 void ListenHTTP::initialize() {
-  _logger->log_info("Initializing ListenHTTP");
+  logger_->log_info("Initializing ListenHTTP");
 
   // Set the supported properties
   std::set<core::Property> properties;
@@ -99,7 +100,7 @@ void ListenHTTP::onSchedule(core::ProcessContext *context,
   std::string basePath;
 
   if (!context->getProperty(BasePath.getName(), basePath)) {
-    _logger->log_info(
+    logger_->log_info(
         "%s attribute is missing, so default value of %s will be used",
         BasePath.getName().c_str(), BasePath.getValue().c_str());
     basePath = BasePath.getValue();
@@ -110,7 +111,7 @@ void ListenHTTP::onSchedule(core::ProcessContext *context,
   std::string listeningPort;
 
   if (!context->getProperty(Port.getName(), listeningPort)) {
-    _logger->log_error("%s attribute is missing or invalid",
+    logger_->log_error("%s attribute is missing or invalid",
                        Port.getName().c_str());
     return;
   }
@@ -119,7 +120,7 @@ void ListenHTTP::onSchedule(core::ProcessContext *context,
 
   if (context->getProperty(AuthorizedDNPattern.getName(), authDNPattern)
       && !authDNPattern.empty()) {
-    _logger->log_info("ListenHTTP using %s: %s",
+    logger_->log_info("ListenHTTP using %s: %s",
                       AuthorizedDNPattern.getName().c_str(),
                       authDNPattern.c_str());
   }
@@ -128,7 +129,7 @@ void ListenHTTP::onSchedule(core::ProcessContext *context,
 
   if (context->getProperty(SSLCertificate.getName(), sslCertFile)
       && !sslCertFile.empty()) {
-    _logger->log_info("ListenHTTP using %s: %s",
+    logger_->log_info("ListenHTTP using %s: %s",
                       SSLCertificate.getName().c_str(), sslCertFile.c_str());
   }
 
@@ -141,23 +142,23 @@ void ListenHTTP::onSchedule(core::ProcessContext *context,
     if (context->getProperty(SSLCertificateAuthority.getName(),
                              sslCertAuthorityFile)
         && !sslCertAuthorityFile.empty()) {
-      _logger->log_info("ListenHTTP using %s: %s",
+      logger_->log_info("ListenHTTP using %s: %s",
                         SSLCertificateAuthority.getName().c_str(),
                         sslCertAuthorityFile.c_str());
     }
 
     if (context->getProperty(SSLVerifyPeer.getName(), sslVerifyPeer)) {
       if (sslVerifyPeer.empty() || sslVerifyPeer.compare("no") == 0) {
-        _logger->log_info("ListenHTTP will not verify peers");
+        logger_->log_info("ListenHTTP will not verify peers");
       } else {
-        _logger->log_info("ListenHTTP will verify peers");
+        logger_->log_info("ListenHTTP will verify peers");
       }
     } else {
-      _logger->log_info("ListenHTTP will not verify peers");
+      logger_->log_info("ListenHTTP will not verify peers");
     }
 
     if (context->getProperty(SSLMinimumVersion.getName(), sslMinVer)) {
-      _logger->log_info("ListenHTTP using %s: %s",
+      logger_->log_info("ListenHTTP using %s: %s",
                         SSLMinimumVersion.getName().c_str(), 
sslMinVer.c_str());
     }
   }
@@ -167,14 +168,14 @@ void ListenHTTP::onSchedule(core::ProcessContext *context,
   if (context->getProperty(HeadersAsAttributesRegex.getName(),
                            headersAsAttributesPattern)
       && !headersAsAttributesPattern.empty()) {
-    _logger->log_info("ListenHTTP using %s: %s",
+    logger_->log_info("ListenHTTP using %s: %s",
                       HeadersAsAttributesRegex.getName().c_str(),
                       headersAsAttributesPattern.c_str());
   }
 
   auto numThreads = getMaxConcurrentTasks();
 
-  _logger->log_info(
+  logger_->log_info(
       "ListenHTTP starting HTTP server on port %s and path %s with %d threads",
       listeningPort.c_str(), basePath.c_str(), numThreads);
 
@@ -255,7 +256,8 @@ ListenHTTP::Handler::Handler(core::ProcessContext *context,
                              std::string &&authDNPattern,
                              std::string &&headersAsAttributesPattern)
     : _authDNRegex(std::move(authDNPattern)),
-      _headersAsAttributesRegex(std::move(headersAsAttributesPattern)) {
+      _headersAsAttributesRegex(std::move(headersAsAttributesPattern)),
+      logger_(logging::LoggerFactory<ListenHTTP::Handler>::getLogger()) {
   _processContext = context;
   _processSessionFactory = sessionFactory;
 }
@@ -268,10 +270,8 @@ void ListenHTTP::Handler::sendErrorResponse(struct 
mg_connection *conn) {
 
 bool ListenHTTP::Handler::handlePost(CivetServer *server,
                                      struct mg_connection *conn) {
-  _logger = logging::Logger::getLogger();
-
   auto req_info = mg_get_request_info(conn);
-  _logger->log_info("ListenHTTP handling POST request of length %d",
+  logger_->log_info("ListenHTTP handling POST request of length %d",
                     req_info->content_length);
 
   // If this is a two-way TLS connection, authorize the peer against the 
configured pattern
@@ -280,7 +280,7 @@ bool ListenHTTP::Handler::handlePost(CivetServer *server,
       mg_printf(conn, "HTTP/1.1 403 Forbidden\r\n"
                 "Content-Type: text/html\r\n"
                 "Content-Length: 0\r\n\r\n");
-      _logger->log_warn("ListenHTTP client DN not authorized: %s",
+      logger_->log_warn("ListenHTTP client DN not authorized: %s",
                         req_info->client_cert->subject);
       return true;
     }
@@ -319,12 +319,12 @@ bool ListenHTTP::Handler::handlePost(CivetServer *server,
     session->transfer(flowFile, Success);
     session->commit();
   } catch (std::exception &exception) {
-    _logger->log_debug("ListenHTTP Caught Exception %s", exception.what());
+    logger_->log_debug("ListenHTTP Caught Exception %s", exception.what());
     sendErrorResponse(conn);
     session->rollback();
     throw;
   } catch (...) {
-    _logger->log_debug("ListenHTTP Caught Exception Processor::onTrigger");
+    logger_->log_debug("ListenHTTP Caught Exception Processor::onTrigger");
     sendErrorResponse(conn);
     session->rollback();
     throw;
@@ -337,9 +337,8 @@ bool ListenHTTP::Handler::handlePost(CivetServer *server,
   return true;
 }
 
-ListenHTTP::WriteCallback::WriteCallback(
-    struct mg_connection *conn, const struct mg_request_info *reqInfo) {
-  _logger = logging::Logger::getLogger();
+ListenHTTP::WriteCallback::WriteCallback(struct mg_connection *conn, const 
struct mg_request_info *reqInfo) :
+    logger_(logging::LoggerFactory<ListenHTTP::WriteCallback>::getLogger()) {
   _conn = conn;
   _reqInfo = reqInfo;
 }

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/src/processors/PutFile.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/processors/PutFile.cpp 
b/libminifi/src/processors/PutFile.cpp
index bd08877..d8832c7 100644
--- a/libminifi/src/processors/PutFile.cpp
+++ b/libminifi/src/processors/PutFile.cpp
@@ -153,8 +153,8 @@ PutFile::ReadCallback::ReadCallback(const std::string 
&tmpFile,
                                     const std::string &destFile)
     : _tmpFile(tmpFile),
       _tmpFileOs(tmpFile),
-      _destFile(destFile) {
-  logger_ = logging::Logger::getLogger();
+      _destFile(destFile),
+      logger_(logging::LoggerFactory<PutFile::ReadCallback>::getLogger()) {
 }
 
 // Copy the entire file contents to the temporary file

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/TestBase.h
----------------------------------------------------------------------
diff --git a/libminifi/test/TestBase.h b/libminifi/test/TestBase.h
index 18d5d01..7b1ac6b 100644
--- a/libminifi/test/TestBase.h
+++ b/libminifi/test/TestBase.h
@@ -21,35 +21,124 @@
 #include <dirent.h>
 #include <cstdio>
 #include <cstdlib>
+#include <sstream>
 #include "ResourceClaim.h"
 #include "catch.hpp"
 #include <vector>
-#include "core/logging/LogAppenders.h"
 #include "core/logging/Logger.h"
 #include "core/Core.h"
 #include "properties/Configure.h"
+#include "properties/Properties.h"
+#include "core/logging/LoggerConfiguration.h"
+#include "spdlog/sinks/ostream_sink.h"
+#include "spdlog/sinks/dist_sink.h"
 
 class LogTestController {
  public:
-  LogTestController(const std::string level = "debug") {
-    logging::Logger::getLogger()->setLogLevel(level);
+  static LogTestController& getInstance() {
+   static LogTestController instance;
+   return instance;
   }
-
-  void enableDebug() {
-    logging::Logger::getLogger()->setLogLevel("debug");
+  
+  template<typename T>
+  void setTrace() {
+    setLevel<T>(spdlog::level::trace);
+  }
+  
+  template<typename T>
+  void setDebug() {
+    setLevel<T>(spdlog::level::debug);
+  }
+  
+  template<typename T>
+  void setInfo() {
+    setLevel<T>(spdlog::level::info);
+  }
+  
+  template<typename T>
+  void setWarn() {
+    setLevel<T>(spdlog::level::warn);
+  }
+  
+  template<typename T>
+  void setError() {
+    setLevel<T>(spdlog::level::err);
+  }
+  
+  template<typename T>
+  void setOff() {
+    setLevel<T>(spdlog::level::off);
+  }
+  
+  template<typename T>
+  void setLevel(spdlog::level::level_enum level) {
+    logging::LoggerFactory<T>::getLogger();
+    std::string name = core::getClassName<T>();
+    modified_loggers.push_back(name);
+    setLevel(name, level);
+  }
+  
+  bool contains(const std::string &ending) {
+   return contains(log_output, ending);
+  }
+  
+  bool contains(const std::ostringstream &stream, const std::string &ending) {
+    std::string str = stream.str();
+    logger_->log_info("Looking for %s in %s.", ending, str);
+    return (ending.length() > 0 && str.find(ending) != std::string::npos);
+  }
+  
+  void reset() {
+    for (auto const & name : modified_loggers) {
+      setLevel(name, spdlog::level::err);
+    }
+    modified_loggers = std::vector<std::string>();
+    resetStream(log_output);
+  }
+  
+  inline void resetStream(std::ostringstream &stream) {
+    stream.str("");
+    stream.clear();
+  }
+  
+  std::ostringstream log_output;
+  
+  std::shared_ptr<logging::Logger> logger_;
+ private:
+   class TestBootstrapLogger: public logging::Logger {
+    public:
+      TestBootstrapLogger(std::shared_ptr<spdlog::logger> 
logger):Logger(logger){};
+   };
+  LogTestController() {
+   std::shared_ptr<logging::LoggerProperties> logger_properties = 
std::make_shared<logging::LoggerProperties>();
+   logger_properties->set("logger.root", "ERROR,ostream");
+   logger_properties->set("logger." + core::getClassName<LogTestController>(), 
"INFO");
+   logger_properties->set("logger." + 
core::getClassName<logging::LoggerConfiguration>(), "DEBUG");
+   std::shared_ptr<spdlog::sinks::dist_sink_mt> dist_sink = 
std::make_shared<spdlog::sinks::dist_sink_mt>();
+   
dist_sink->add_sink(std::make_shared<spdlog::sinks::ostream_sink_mt>(log_output,
 true));
+   dist_sink->add_sink(spdlog::sinks::stderr_sink_mt::instance());
+   logger_properties->add_sink("ostream", dist_sink);
+   
logging::LoggerConfiguration::getConfiguration().initialize(logger_properties);
+   logger_ = logging::LoggerFactory<LogTestController>::getLogger();
   }
+  LogTestController(LogTestController const&);
+  LogTestController& operator=(LogTestController const&);
+  ~LogTestController() {};
 
-  ~LogTestController() {
-    logging::Logger::getLogger()->setLogLevel(logging::LOG_LEVEL_E::info);
+  void setLevel(const std::string name, spdlog::level::level_enum level) {
+    logger_->log_info("Setting log level for %s to %s", name, 
spdlog::level::to_str(level));
+    spdlog::get(name)->set_level(level);
   }
+  std::vector<std::string> modified_loggers;
 };
 
 class TestController {
  public:
 
   TestController()
-      : log("info") {
+      : log(LogTestController::getInstance()) {
     minifi::ResourceClaim::default_directory_path = const_cast<char*>("./");
+    log.reset();
   }
 
   ~TestController() {
@@ -73,30 +162,6 @@ class TestController {
     }
   }
 
-  void setDebugToConsole(
-      std::shared_ptr<org::apache::nifi::minifi::Configure> configure) {
-    std::ostringstream oss;
-    std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr<
-        logging::BaseLogger>(
-        new org::apache::nifi::minifi::core::logging::OutputStreamAppender(
-            std::cout, configure));
-    std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger();
-    logger->updateLogger(std::move(outputLogger));
-  }
-
-  void setNullAppender() {
-
-    std::unique_ptr<logging::BaseLogger> outputLogger = std::unique_ptr<
-        logging::BaseLogger>(
-        new org::apache::nifi::minifi::core::logging::NullAppender());
-    std::shared_ptr<logging::Logger> logger = logging::Logger::getLogger();
-    logger->updateLogger(std::move(outputLogger));
-  }
-
-  void enableDebug() {
-    log.enableDebug();
-  }
-
   char *createTempDirectory(char *format) {
     char *dir = mkdtemp(format);
     directories.push_back(dir);
@@ -104,7 +169,7 @@ class TestController {
   }
 
  protected:
-  LogTestController log;
+  LogTestController &log;
   std::vector<char*> directories;
 
 };

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/integration/ControllerServiceIntegrationTests.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/integration/ControllerServiceIntegrationTests.cpp 
b/libminifi/test/integration/ControllerServiceIntegrationTests.cpp
index 4668bb9..f1376e0 100644
--- a/libminifi/test/integration/ControllerServiceIntegrationTests.cpp
+++ b/libminifi/test/integration/ControllerServiceIntegrationTests.cpp
@@ -24,8 +24,6 @@
 #include <utility>
 #include <thread>
 #include <type_traits>
-#include "core/logging/LogAppenders.h"
-#include "core/logging/BaseLogger.h"
 #include <vector>
 
 #include "../include/core/controller/ControllerServiceMap.h"
@@ -33,7 +31,7 @@
 #include "../include/core/controller/StandardControllerServiceProvider.h"
 #include "controllers/SSLContextService.h"
 #include "../include/core/Core.h"
-#include "../include/core/logging/Logger.h"
+#include "../include/core/logging/LoggerConfiguration.h"
 #include "../include/core/ProcessGroup.h"
 #include "../include/core/Resource.h"
 #include "../include/core/yaml/YamlConfiguration.h"
@@ -71,8 +69,6 @@ int main(int argc, char **argv) {
     key_dir = argv[1];
   }
 
-  logging::Logger::getLogger()->setLogLevel("trace");
-
   std::shared_ptr<minifi::Configure> configuration = std::make_shared<
       minifi::Configure>();
 
@@ -138,8 +134,6 @@ int main(int argc, char **argv) {
   std::shared_ptr<core::controller::ControllerServiceNode> notexistNode = pg
       ->findControllerService("MockItLikeItsWrong");
   assert(notexistNode == nullptr);
-  logging::Logger::getLogger()->log_info(
-      "STARTING FLOW CONTROLLER INTEGRATION TEST");
   controller->load();
   controller->start();
   std::shared_ptr<core::controller::ControllerServiceNode> ssl_client_cont =

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/integration/HttpGetIntegrationTest.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/integration/HttpGetIntegrationTest.cpp 
b/libminifi/test/integration/HttpGetIntegrationTest.cpp
index 866309f..018ab59 100644
--- a/libminifi/test/integration/HttpGetIntegrationTest.cpp
+++ b/libminifi/test/integration/HttpGetIntegrationTest.cpp
@@ -29,9 +29,7 @@
 #include "../TestBase.h"
 #include "utils/StringUtils.h"
 #include "core/Core.h"
-#include "core/logging/LogAppenders.h"
-#include "core/logging/BaseLogger.h"
-#include "core/logging/Logger.h"
+#include "../include/core/logging/Logger.h"
 #include "core/ProcessGroup.h"
 #include "core/yaml/YamlConfiguration.h"
 #include "FlowController.h"
@@ -44,6 +42,8 @@ void waitToVerifyProcessor() {
 }
 
 int main(int argc, char **argv) {
+  LogTestController::getInstance().setInfo<minifi::processors::InvokeHTTP>();
+  LogTestController::getInstance().setInfo<minifi::processors::LogAttribute>();
   std::string key_dir, test_file_location;
   if (argc > 1) {
     test_file_location = argv[1];
@@ -53,14 +53,6 @@ int main(int argc, char **argv) {
       minifi::Configure>();
   configuration->set(minifi::Configure::nifi_default_directory, key_dir);
   mkdir("content_repository", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
-  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("debug");
 
   std::shared_ptr<core::Repository> test_repo =
       std::make_shared<TestRepository>();
@@ -98,8 +90,7 @@ int main(int argc, char **argv) {
   waitToVerifyProcessor();
 
   controller->waitUnload(60000);
-  std::string logs = oss.str();
-  std::cout << logs << std::endl;
+  std::string logs = LogTestController::getInstance().log_output.str();
   assert(logs.find("key:filename value:") != std::string::npos);
   assert(
       logs.find(
@@ -121,6 +112,7 @@ int main(int argc, char **argv) {
     if (loc == std::string::npos)
       break;
   }
+  LogTestController::getInstance().reset();
   rmdir("./content_repository");
   return 0;
 }

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/integration/HttpPostIntegrationTest.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/integration/HttpPostIntegrationTest.cpp 
b/libminifi/test/integration/HttpPostIntegrationTest.cpp
index 8e6ebec..e88fc57 100644
--- a/libminifi/test/integration/HttpPostIntegrationTest.cpp
+++ b/libminifi/test/integration/HttpPostIntegrationTest.cpp
@@ -28,15 +28,14 @@
 #include <vector>
 #include "utils/StringUtils.h"
 #include "core/Core.h"
-#include "core/logging/LogAppenders.h"
-#include "core/logging/BaseLogger.h"
-#include "core/logging/Logger.h"
+#include "../include/core/logging/Logger.h"
 #include "core/ProcessGroup.h"
 #include "core/yaml/YamlConfiguration.h"
 #include "FlowController.h"
 #include "properties/Configure.h"
 #include "../unit/ProvenanceTestHelper.h"
 #include "io/StreamFactory.h"
+#include "../TestBase.h"
 
 
 void waitToVerifyProcessor() {
@@ -44,6 +43,8 @@ void waitToVerifyProcessor() {
 }
 
 int main(int argc, char **argv) {
+  LogTestController::getInstance().setDebug<processors::InvokeHTTP>();
+  LogTestController::getInstance().setDebug<minifi::core::ProcessSession>();
   std::string test_file_location;
   if (argc > 1) {
     test_file_location = argv[1];
@@ -54,14 +55,6 @@ int main(int argc, char **argv) {
   myfile << "Hello world" << std::endl;
   myfile.close();
   mkdir("content_repository", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
-  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("debug");
 
   std::shared_ptr<minifi::Configure> configuration = std::make_shared<
       minifi::Configure>();
@@ -103,12 +96,12 @@ int main(int argc, char **argv) {
   waitToVerifyProcessor();
 
   controller->waitUnload(60000);
-  std::string logs = oss.str();
-  assert(logs.find("curl performed") != std::string::npos);
-  assert(logs.find("Import offset 0 length 12") != std::string::npos);
+  assert(LogTestController::getInstance().contains("curl performed") == true);
+  assert(LogTestController::getInstance().contains("Import offset 0 length 
12") == true);
 
   std::string stringtofind = "Resource Claim created ./content_repository/";
 
+  std::string logs = LogTestController::getInstance().log_output.str();
   size_t loc = logs.find(stringtofind);
   while (loc > 0 && loc != std::string::npos) {
     std::string id = logs.substr(loc + stringtofind.size(), 36);
@@ -120,5 +113,6 @@ int main(int argc, char **argv) {
   }
 
   rmdir("./content_repository");
+  LogTestController::getInstance().reset();
   return 0;
 }

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/integration/ProvenanceReportingTest.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/integration/ProvenanceReportingTest.cpp 
b/libminifi/test/integration/ProvenanceReportingTest.cpp
index ff5d563..5e2c7b8 100644
--- a/libminifi/test/integration/ProvenanceReportingTest.cpp
+++ b/libminifi/test/integration/ProvenanceReportingTest.cpp
@@ -28,8 +28,6 @@
 #include <vector>
 #include "utils/StringUtils.h"
 #include "core/Core.h"
-#include "core/logging/LogAppenders.h"
-#include "core/logging/BaseLogger.h"
 #include "core/logging/Logger.h"
 #include "core/ProcessGroup.h"
 #include "core/yaml/YamlConfiguration.h"
@@ -37,6 +35,7 @@
 #include "properties/Configure.h"
 #include "../unit/ProvenanceTestHelper.h"
 #include "io/StreamFactory.h"
+#include "../TestBase.h"
 
 
 void waitToVerifyProcessor() {
@@ -51,14 +50,8 @@ int main(int argc, char **argv) {
   mkdir("/tmp/aljs39/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
 
   mkdir("content_repository", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
-  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("debug");
+
+  LogTestController::getInstance().setDebug<core::ProcessGroup>();
 
   std::shared_ptr<minifi::Configure> configuration = std::make_shared<
       minifi::Configure>();
@@ -105,10 +98,9 @@ int main(int argc, char **argv) {
   waitToVerifyProcessor();
 
   controller->waitUnload(60000);
-  std::string logs = oss.str();
+  std::string logs = LogTestController::getInstance().log_output.str();
   assert(logs.find("Add processor SiteToSiteProvenanceReportingTask into 
process group MiNiFi Flow") != std::string::npos);
-
-
+  LogTestController::getInstance().reset();
   rmdir("./content_repository");
   rmdir("/tmp/aljs39/");
   return 0;

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/integration/TestExecuteProcess.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/integration/TestExecuteProcess.cpp 
b/libminifi/test/integration/TestExecuteProcess.cpp
index e947a46..c3a3f4c 100644
--- a/libminifi/test/integration/TestExecuteProcess.cpp
+++ b/libminifi/test/integration/TestExecuteProcess.cpp
@@ -16,6 +16,13 @@
  * limitations under the License.
  */
 
+
+#include <cassert>
+#include <chrono>
+#include <string>
+#include <thread>
+#include <type_traits>
+#include <sys/stat.h>
 #include <uuid/uuid.h>
 #include <utility>
 #include <memory>
@@ -24,8 +31,6 @@
 
 #include "../unit/ProvenanceTestHelper.h"
 #include "FlowController.h"
-#include "core/logging/LogAppenders.h"
-#include "core/logging/BaseLogger.h"
 #include "processors/GetFile.h"
 #include "core/Core.h"
 #include "core/FlowFile.h"
@@ -36,20 +41,10 @@
 #include "core/ProcessContext.h"
 #include "core/ProcessSession.h"
 #include "core/ProcessorNode.h"
+#include "../TestBase.h"
 
 int main(int argc, char **argv) {
-  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));
-
-  outputLogger = std::unique_ptr<logging::BaseLogger>(
-      new org::apache::nifi::minifi::core::logging::NullAppender());
-  logger->updateLogger(std::move(outputLogger));
-
+  TestController testController;
   std::shared_ptr<core::Processor> processor = std::make_shared<
       org::apache::nifi::minifi::processors::ExecuteProcess>("executeProcess");
   processor->setMaxConcurrentTasks(1);
@@ -118,9 +113,6 @@ int main(int argc, char **argv) {
                   t.join();
                 });
 
-  outputLogger = std::unique_ptr<logging::BaseLogger>(
-      new org::apache::nifi::minifi::core::logging::NullAppender());
-  logger->updateLogger(std::move(outputLogger));
 
   std::shared_ptr<org::apache::nifi::minifi::processors::ExecuteProcess> execp 
=
       std::static_pointer_cast<

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/unit/ClassLoaderTests.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/unit/ClassLoaderTests.cpp 
b/libminifi/test/unit/ClassLoaderTests.cpp
index 7928832..e27c753 100644
--- a/libminifi/test/unit/ClassLoaderTests.cpp
+++ b/libminifi/test/unit/ClassLoaderTests.cpp
@@ -21,10 +21,10 @@
 #include "io/ClientSocket.h"
 #include "core/Processor.h"
 #include "core/ClassLoader.h"
-#include "processors/AppendHostInfo.h"
-#include "core/logging/LogAppenders.h"
+#include "core/yaml/YamlConfiguration.h"
 
 TEST_CASE("TestLoader", "[TestLoader]") {
+  TestController controller;
   REQUIRE(
       nullptr
           != core::ClassLoader::getDefaultClassLoader().instantiate(

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/unit/ControllerServiceTests.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/unit/ControllerServiceTests.cpp 
b/libminifi/test/unit/ControllerServiceTests.cpp
index 508e37f..44d30d4 100644
--- a/libminifi/test/unit/ControllerServiceTests.cpp
+++ b/libminifi/test/unit/ControllerServiceTests.cpp
@@ -23,8 +23,6 @@
 #include "FlowController.h"
 #include "../TestBase.h"
 #include "properties/Configure.h"
-#include "core/logging/LogAppenders.h"
-#include "core/logging/BaseLogger.h"
 #include "processors/GetFile.h"
 #include "core/Core.h"
 #include "Exception.h"
@@ -35,6 +33,7 @@
 #include "core/Processor.h"
 #include "core/controller/ControllerServiceMap.h"
 #include "core/controller/StandardControllerServiceNode.h"
+
 namespace ControllerServiceTests {
 
 TEST_CASE("Test ControllerServicesMap", "[cs1]") {

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/unit/InvokeHTTPTests.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/unit/InvokeHTTPTests.cpp 
b/libminifi/test/unit/InvokeHTTPTests.cpp
index 458a1c7..95b4a2e 100644
--- a/libminifi/test/unit/InvokeHTTPTests.cpp
+++ b/libminifi/test/unit/InvokeHTTPTests.cpp
@@ -26,8 +26,6 @@
 #include <set>
 #include "FlowController.h"
 #include "../TestBase.h"
-#include "core/logging/LogAppenders.h"
-#include "core/logging/BaseLogger.h"
 #include "processors/GetFile.h"
 #include "core/Core.h"
 #include "../../include/core/FlowFile.h"
@@ -38,17 +36,8 @@
 #include "core/ProcessorNode.h"
 
 TEST_CASE("HTTPTestsPostNoResourceClaim", "[httptest1]") {
-  std::stringstream 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().setInfo<org::apache::nifi::minifi::processors::InvokeHTTP>();
 
   std::shared_ptr<TestRepository> repo = std::make_shared<TestRepository>();
 
@@ -149,25 +138,13 @@ TEST_CASE("HTTPTestsPostNoResourceClaim", "[httptest1]") {
     REQUIRE(provEventRecord->getComponentType() == processor->getName());
   }
   std::shared_ptr<core::FlowFile> ffr = session2.get();
-  std::string log_attribute_output = oss.str();
-  std::cout << log_attribute_output << std::endl;
-  REQUIRE(
-      log_attribute_output.find("exiting because method is POST")
-          != std::string::npos);
+  REQUIRE(true == LogTestController::getInstance().contains("exiting because 
method is POST"));
+  LogTestController::getInstance().reset();
 }
 
 TEST_CASE("HTTPTestsWithNoResourceClaimPOST", "[httptest1]") {
-  std::stringstream 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().setInfo<org::apache::nifi::minifi::processors::InvokeHTTP>();
 
   std::shared_ptr<TestRepository> repo = std::make_shared<TestRepository>();
 
@@ -279,10 +256,8 @@ TEST_CASE("HTTPTestsWithNoResourceClaimPOST", 
"[httptest1]") {
     REQUIRE(provEventRecord->getComponentType() == listenhttp->getName());
   }
   std::shared_ptr<core::FlowFile> ffr = session2.get();
-  std::string log_attribute_output = oss.str();
-  REQUIRE(
-      log_attribute_output.find("exiting because method is POST")
-          != std::string::npos);
+  REQUIRE(true == LogTestController::getInstance().contains("exiting because 
method is POST"));
+  LogTestController::getInstance().reset();
 }
 
 class CallBack : public minifi::OutputStreamCallback {
@@ -298,19 +273,11 @@ class CallBack : public minifi::OutputStreamCallback {
 };
 
 TEST_CASE("HTTPTestsWithResourceClaimPOST", "[httptest1]") {
-  std::stringstream 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;
+  
LogTestController::getInstance().setInfo<org::apache::nifi::minifi::processors::InvokeHTTP>();
 
-  testController.enableDebug();
-
-  std::shared_ptr<TestRepository> repo = std::make_shared<TestRepository>();
+  std::shared_ptr<TestRepository> repo = std::make_shared<
+      TestRepository>();
 
   std::shared_ptr<core::Processor> getfileprocessor = std::make_shared<
       org::apache::nifi::minifi::processors::GetFile>("getfileCreate2");
@@ -437,9 +404,7 @@ TEST_CASE("HTTPTestsWithResourceClaimPOST", "[httptest1]") {
     REQUIRE(provEventRecord->getComponentType() == listenhttp->getName());
   }
   std::shared_ptr<core::FlowFile> ffr = session2.get();
-  std::string log_attribute_output = oss.str();
-  REQUIRE(
-      log_attribute_output.find("exiting because method is POST")
-          != std::string::npos);
+  REQUIRE(true == LogTestController::getInstance().contains("exiting because 
method is POST"));
+  LogTestController::getInstance().reset();
 }
 

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/libminifi/test/unit/LoggerConfigurationTests.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/unit/LoggerConfigurationTests.cpp 
b/libminifi/test/unit/LoggerConfigurationTests.cpp
new file mode 100644
index 0000000..7c340d1
--- /dev/null
+++ b/libminifi/test/unit/LoggerConfigurationTests.cpp
@@ -0,0 +1,99 @@
+/**
+ *
+ * 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 <algorithm>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "../TestBase.h"
+#include "core/logging/LoggerConfiguration.h"
+#include "spdlog/formatter.h"
+
+TEST_CASE("TestLoggerProperties::get_keys_of_type", "[test get_keys_of_type]") 
{
+  TestController test_controller;
+  LogTestController::getInstance().setDebug<logging::LoggerProperties>();
+  logging::LoggerProperties logger_properties;
+  logger_properties.set("appender.rolling", "rolling");
+  logger_properties.set("notappender.notrolling", "notrolling");
+  logger_properties.set("appender.stdout", "stdout");
+  logger_properties.set("appender.stdout2.ignore", "stdout");
+  std::vector<std::string> expected = {"appender.rolling", "appender.stdout"};
+  std::vector<std::string> actual = 
logger_properties.get_keys_of_type("appender");
+  std::sort(actual.begin(), actual.end());
+  REQUIRE(expected == actual);
+}
+
+class TestLoggerConfiguration : public logging::LoggerConfiguration {
+ public:
+  static std::shared_ptr<logging::internal::LoggerNamespace> 
initialize_namespaces(const std::shared_ptr<logging::LoggerProperties>  
&logger_properties) {
+    return 
logging::LoggerConfiguration::initialize_namespaces(logger_properties);
+  }
+  static std::shared_ptr<spdlog::logger> get_logger(const 
std::shared_ptr<logging::internal::LoggerNamespace> &root_namespace, const 
std::string &name, std::shared_ptr<spdlog::formatter> formatter) {
+    return 
logging::LoggerConfiguration::get_logger(LogTestController::getInstance().logger_,
 root_namespace, name, formatter);
+  }
+};
+
+TEST_CASE("TestLoggerConfiguration::initialize_namespaces", "[test 
initialize_namespaces]") {
+  TestController test_controller;
+  LogTestController &logTestController = LogTestController::getInstance();
+  LogTestController::getInstance().setDebug<logging::LoggerProperties>();
+  std::shared_ptr<logging::LoggerProperties> logger_properties = 
std::make_shared<logging::LoggerProperties>();
+
+  std::ostringstream stdout;
+  std::ostringstream stderr;
+  logger_properties->add_sink("stdout", 
std::make_shared<spdlog::sinks::ostream_sink_mt>(stdout, true));
+  logger_properties->add_sink("stderr", 
std::make_shared<spdlog::sinks::ostream_sink_mt>(stderr, true));
+
+  std::string stdout_only_warn_class = 
"org::apache::nifi::minifi::fake::test::StdoutOnlyWarn";
+  std::string stderr_only_error_pkg = "org::apache::nifi::minifi::fake2";
+  std::string stderr_only_error_class = stderr_only_error_pkg + 
"::test::StderrOnlyError";
+  logger_properties->set("logger.root", "INFO,stdout,stderr");
+  logger_properties->set("logger." + stdout_only_warn_class, "WARN,stdout");
+  logger_properties->set("logger." + stderr_only_error_pkg, "ERROR,stderr");
+
+  std::shared_ptr<logging::internal::LoggerNamespace> root_namespace = 
TestLoggerConfiguration::initialize_namespaces(logger_properties);
+
+  std::shared_ptr<spdlog::formatter> formatter = 
std::make_shared<spdlog::pattern_formatter>(logging::LoggerConfiguration::spdlog_default_pattern);
+  std::shared_ptr<spdlog::logger> logger = 
TestLoggerConfiguration::get_logger(root_namespace, 
"org::apache::nifi::minifi::fake::test::ClassName1", formatter);
+  std::string test_log_statement = "Test log statement";
+  logger->info(test_log_statement);
+  REQUIRE(true == logTestController.contains(stdout, test_log_statement));
+  REQUIRE(true == logTestController.contains(stderr, test_log_statement));
+  logTestController.resetStream(stdout);
+  logTestController.resetStream(stderr);
+
+  logger = TestLoggerConfiguration::get_logger(root_namespace, 
stdout_only_warn_class, formatter);
+  logger->info(test_log_statement);
+  REQUIRE(false == logTestController.contains(stdout, test_log_statement));
+  logger->warn(test_log_statement);
+  REQUIRE(true == logTestController.contains(stdout, test_log_statement));
+  REQUIRE(false == logTestController.contains(stderr, test_log_statement));
+  logTestController.resetStream(stdout);
+  logTestController.resetStream(stderr);
+
+  logger = TestLoggerConfiguration::get_logger(root_namespace, 
stderr_only_error_class, formatter);
+  logger->warn(test_log_statement);
+  REQUIRE(false == logTestController.contains(stderr, test_log_statement));
+  logger->error(test_log_statement);
+  REQUIRE(false == logTestController.contains(stdout, test_log_statement));
+  REQUIRE(true == logTestController.contains(stderr, test_log_statement));
+  logTestController.resetStream(stdout);
+  logTestController.resetStream(stderr);
+}

Reply via email to