You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by al...@apache.org on 2016/10/13 15:07:28 UTC

[10/18] nifi-minifi-cpp git commit: MINIFI-34 Establishing CMake build system to provide build functionality equivalent to pre-existing Makefile.

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/line_logger.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/line_logger.h b/include/spdlog/details/line_logger.h
new file mode 100644
index 0000000..80d7cc1
--- /dev/null
+++ b/include/spdlog/details/line_logger.h
@@ -0,0 +1,221 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library.     */
+/* Copyright (c) 2014 Gabi Melman.                                       */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#pragma once
+#include <type_traits>
+#include "../common.h"
+#include "../logger.h"
+
+// Line logger class - aggregates operator<< calls to fast ostream
+// and logs upon destruction
+
+namespace spdlog
+{
+namespace details
+{
+class line_logger
+{
+public:
+    line_logger(logger* callback_logger, level::level_enum msg_level, bool enabled):
+        _callback_logger(callback_logger),
+        _log_msg(msg_level),
+        _enabled(enabled)
+    {}
+
+    // No copy intended. Only move
+    line_logger(const line_logger& other) = delete;
+    line_logger& operator=(const line_logger&) = delete;
+    line_logger& operator=(line_logger&&) = delete;
+
+
+    line_logger(line_logger&& other) :
+        _callback_logger(other._callback_logger),
+        _log_msg(std::move(other._log_msg)),
+        _enabled(other._enabled)
+    {
+        other.disable();
+    }
+
+    //Log the log message using the callback logger
+    ~line_logger()
+    {
+        if (_enabled)
+        {
+#ifndef SPDLOG_NO_NAME
+            _log_msg.logger_name = _callback_logger->name();
+#endif
+#ifndef SPDLOG_NO_DATETIME
+            _log_msg.time = os::now();
+#endif
+
+#ifndef SPDLOG_NO_THREAD_ID
+            _log_msg.thread_id = os::thread_id();
+#endif
+            _callback_logger->_log_msg(_log_msg);
+        }
+    }
+
+    //
+    // Support for format string with variadic args
+    //
+
+
+    void write(const char* what)
+    {
+        if (_enabled)
+            _log_msg.raw << what;
+    }
+
+    template <typename... Args>
+    void write(const char* fmt, const Args&... args)
+    {
+        if (!_enabled)
+            return;
+        try
+        {
+            _log_msg.raw.write(fmt, args...);
+        }
+        catch (const fmt::FormatError& e)
+        {
+            throw spdlog_ex(fmt::format("formatting error while processing format string '{}': {}", fmt, e.what()));
+        }
+    }
+
+
+    //
+    // Support for operator<<
+    //
+    line_logger& operator<<(const char* what)
+    {
+        if (_enabled)
+            _log_msg.raw << what;
+        return *this;
+    }
+
+    line_logger& operator<<(const std::string& what)
+    {
+        if (_enabled)
+            _log_msg.raw << what;
+        return *this;
+    }
+
+    line_logger& operator<<(int what)
+    {
+        if (_enabled)
+            _log_msg.raw << what;
+        return *this;
+    }
+
+    line_logger& operator<<(unsigned int what)
+    {
+        if (_enabled)
+            _log_msg.raw << what;
+        return *this;
+    }
+
+
+    line_logger& operator<<(long what)
+    {
+        if (_enabled)
+            _log_msg.raw << what;
+        return *this;
+    }
+
+    line_logger& operator<<(unsigned long what)
+    {
+        if (_enabled)
+            _log_msg.raw << what;
+        return *this;
+    }
+
+    line_logger& operator<<(long long what)
+    {
+        if (_enabled)
+            _log_msg.raw << what;
+        return *this;
+    }
+
+    line_logger& operator<<(unsigned long long what)
+    {
+        if (_enabled)
+            _log_msg.raw << what;
+        return *this;
+    }
+
+    line_logger& operator<<(double what)
+    {
+        if (_enabled)
+            _log_msg.raw << what;
+        return *this;
+    }
+
+    line_logger& operator<<(long double what)
+    {
+        if (_enabled)
+            _log_msg.raw << what;
+        return *this;
+    }
+
+    line_logger& operator<<(float what)
+    {
+        if (_enabled)
+            _log_msg.raw << what;
+        return *this;
+    }
+
+    line_logger& operator<<(char what)
+    {
+        if (_enabled)
+            _log_msg.raw << what;
+        return *this;
+    }
+
+    //Support user types which implements operator<<
+    template<typename T>
+    line_logger& operator<<(const T& what)
+    {
+        if (_enabled)
+            _log_msg.raw.write("{}", what);
+        return *this;
+    }
+
+
+    void disable()
+    {
+        _enabled = false;
+    }
+
+    bool is_enabled() const
+    {
+        return _enabled;
+    }
+
+
+private:
+    logger* _callback_logger;
+    log_msg _log_msg;
+    bool _enabled;
+};
+} //Namespace details
+} // Namespace spdlog

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/log_msg.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h
new file mode 100644
index 0000000..bf58aca
--- /dev/null
+++ b/include/spdlog/details/log_msg.h
@@ -0,0 +1,98 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library.     */
+/* Copyright (c) 2014 Gabi Melman.                                       */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#pragma once
+
+#include <thread>
+#include "../common.h"
+#include "./format.h"
+
+namespace spdlog
+{
+namespace details
+{
+struct log_msg
+{
+    log_msg() = default;
+    log_msg(level::level_enum l):
+        logger_name(),
+        level(l),
+        raw(),
+        formatted() {}
+
+
+    log_msg(const log_msg& other) :
+        logger_name(other.logger_name),
+        level(other.level),
+        time(other.time),
+        thread_id(other.thread_id)
+    {
+        if (other.raw.size())
+            raw << fmt::BasicStringRef<char>(other.raw.data(), other.raw.size());
+        if (other.formatted.size())
+            formatted << fmt::BasicStringRef<char>(other.formatted.data(), other.formatted.size());
+    }
+
+    log_msg(log_msg&& other) :
+        logger_name(std::move(other.logger_name)),
+        level(other.level),
+        time(std::move(other.time)),
+        thread_id(other.thread_id),
+        raw(std::move(other.raw)),
+        formatted(std::move(other.formatted))
+    {
+        other.clear();
+    }
+
+    log_msg& operator=(log_msg&& other)
+    {
+        if (this == &other)
+            return *this;
+
+        logger_name = std::move(other.logger_name);
+        level = other.level;
+        time = std::move(other.time);
+        thread_id = other.thread_id;
+        raw = std::move(other.raw);
+        formatted = std::move(other.formatted);
+        other.clear();
+        return *this;
+    }
+
+    void clear()
+    {
+        level = level::off;
+        raw.clear();
+        formatted.clear();
+    }
+
+    std::string logger_name;
+    level::level_enum level;
+    log_clock::time_point time;
+    size_t thread_id;
+    fmt::MemoryWriter raw;
+    fmt::MemoryWriter formatted;
+};
+}
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/logger_impl.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h
new file mode 100644
index 0000000..d658ac0
--- /dev/null
+++ b/include/spdlog/details/logger_impl.h
@@ -0,0 +1,320 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library.     */
+/* Copyright (c) 2014 Gabi Melman.                                       */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#pragma once
+//
+// Logger implementation
+//
+
+#include "./line_logger.h"
+
+
+// create logger with given name, sinks and the default pattern formatter
+// all other ctors will call this one
+template<class It>
+inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end) :
+    _name(logger_name),
+    _sinks(begin, end),
+    _formatter(std::make_shared<pattern_formatter>("%+"))
+{
+
+    // no support under vs2013 for member initialization for std::atomic
+    _level = level::info;
+}
+
+// ctor with sinks as init list
+inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list) :
+    logger(logger_name, sinks_list.begin(), sinks_list.end()) {}
+
+
+// ctor with single sink
+inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink) :
+    logger(logger_name, {
+    single_sink
+}) {}
+
+
+inline spdlog::logger::~logger() = default;
+
+
+inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter)
+{
+    _set_formatter(msg_formatter);
+}
+
+inline void spdlog::logger::set_pattern(const std::string& pattern)
+{
+    _set_pattern(pattern);
+}
+
+//
+// log only if given level>=logger's log level
+//
+
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl, const char* fmt, const Args&... args)
+{
+    bool msg_enabled = should_log(lvl);
+    details::line_logger l(this, lvl, msg_enabled);
+    l.write(fmt, args...);
+    return l;
+}
+
+inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl)
+{
+    return details::line_logger(this, lvl, should_log(lvl));
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl, const T& msg)
+{
+    bool msg_enabled = should_log(lvl);
+    details::line_logger l(this, lvl, msg_enabled);
+    l << msg;
+    return l;
+}
+
+//
+// logger.info(cppformat_string, arg1, arg2, arg3, ...) call style
+//
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::trace(const char* fmt, const Args&... args)
+{
+    return _log_if_enabled(level::trace, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::debug(const char* fmt, const Args&... args)
+{
+    return _log_if_enabled(level::debug, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::info(const char* fmt, const Args&... args)
+{
+    return _log_if_enabled(level::info, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::notice(const char* fmt, const Args&... args)
+{
+    return _log_if_enabled(level::notice, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::warn(const char* fmt, const Args&... args)
+{
+    return _log_if_enabled(level::warn, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::error(const char* fmt, const Args&... args)
+{
+    return _log_if_enabled(level::err, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::critical(const char* fmt, const Args&... args)
+{
+    return _log_if_enabled(level::critical, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::alert(const char* fmt, const Args&... args)
+{
+    return _log_if_enabled(level::alert, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::emerg(const char* fmt, const Args&... args)
+{
+    return _log_if_enabled(level::emerg, fmt, args...);
+}
+
+//
+// logger.info(msg) << ".." call style
+//
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::trace(const T& msg)
+{
+    return _log_if_enabled(level::trace, msg);
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::debug(const T& msg)
+{
+    return _log_if_enabled(level::debug, msg);
+}
+
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::info(const T& msg)
+{
+    return _log_if_enabled(level::info, msg);
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::notice(const T& msg)
+{
+    return _log_if_enabled(level::notice, msg);
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::warn(const T& msg)
+{
+    return _log_if_enabled(level::warn, msg);
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::error(const T& msg)
+{
+    return _log_if_enabled(level::err, msg);
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::critical(const T& msg)
+{
+    return _log_if_enabled(level::critical, msg);
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::alert(const T& msg)
+{
+    return _log_if_enabled(level::alert, msg);
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::emerg(const T& msg)
+{
+    return _log_if_enabled(level::emerg, msg);
+}
+
+
+
+
+//
+// logger.info() << ".." call  style
+//
+inline spdlog::details::line_logger spdlog::logger::trace()
+{
+    return _log_if_enabled(level::trace);
+}
+
+inline spdlog::details::line_logger spdlog::logger::debug()
+{
+    return _log_if_enabled(level::debug);
+}
+
+inline spdlog::details::line_logger spdlog::logger::info()
+{
+    return _log_if_enabled(level::info);
+}
+
+inline spdlog::details::line_logger spdlog::logger::notice()
+{
+    return _log_if_enabled(level::notice);
+}
+
+inline spdlog::details::line_logger spdlog::logger::warn()
+{
+    return _log_if_enabled(level::warn);
+}
+
+inline spdlog::details::line_logger spdlog::logger::error()
+{
+    return _log_if_enabled(level::err);
+}
+
+inline spdlog::details::line_logger spdlog::logger::critical()
+{
+    return _log_if_enabled(level::critical);
+}
+
+inline spdlog::details::line_logger spdlog::logger::alert()
+{
+    return _log_if_enabled(level::alert);
+}
+
+inline spdlog::details::line_logger spdlog::logger::emerg()
+{
+    return _log_if_enabled(level::emerg);
+}
+
+
+// always log, no matter what is the actual logger's log level
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::force_log(level::level_enum lvl, const char* fmt, const Args&... args)
+{
+    details::line_logger l(this, lvl, true);
+    l.write(fmt, args...);
+    return l;
+}
+
+//
+// name and level
+//
+inline const std::string& spdlog::logger::name() const
+{
+    return _name;
+}
+
+inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
+{
+    _level.store(log_level);
+}
+
+inline spdlog::level::level_enum spdlog::logger::level() const
+{
+    return static_cast<spdlog::level::level_enum>(_level.load(std::memory_order_relaxed));
+}
+
+inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const
+{
+    return msg_level >= _level.load(std::memory_order_relaxed);
+}
+
+//
+// protected virtual called at end of each user log call (if enabled) by the line_logger
+//
+inline void spdlog::logger::_log_msg(details::log_msg& msg)
+{
+    _formatter->format(msg);
+    for (auto &sink : _sinks)
+        sink->log(msg);
+}
+
+inline void spdlog::logger::_set_pattern(const std::string& pattern)
+{
+    _formatter = std::make_shared<pattern_formatter>(pattern);
+}
+inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter)
+{
+    _formatter = msg_formatter;
+}
+
+inline void spdlog::logger::flush() {
+    for (auto& sink : _sinks)
+        sink->flush();
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/mpmc_bounded_q.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/mpmc_bounded_q.h b/include/spdlog/details/mpmc_bounded_q.h
new file mode 100644
index 0000000..7cbcfd7
--- /dev/null
+++ b/include/spdlog/details/mpmc_bounded_q.h
@@ -0,0 +1,175 @@
+/*
+A modified version of Bounded MPMC queue by Dmitry Vyukov.
+
+Original code from:
+http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue
+
+licensed by Dmitry Vyukov under the terms below:
+
+Simplified BSD license
+
+Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice, this list of
+conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list
+of conditions and the following disclaimer in the documentation and/or other materials
+provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation are those of the authors and
+should not be interpreted as representing official policies, either expressed or implied, of Dmitry Vyukov.
+*/
+
+/*
+The code in its current form adds the license below:
+
+spdlog - an extremely fast and easy to use c++11 logging library.
+Copyright (c) 2014 Gabi Melman.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include <atomic>
+#include "../common.h"
+
+namespace spdlog
+{
+namespace details
+{
+
+template<typename T>
+class mpmc_bounded_queue
+{
+public:
+
+    using item_type = T;
+    mpmc_bounded_queue(size_t buffer_size)
+        : buffer_(new cell_t [buffer_size]),
+          buffer_mask_(buffer_size - 1)
+    {
+        //queue size must be power of two
+        if(!((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0)))
+            throw spdlog_ex("async logger queue size must be power of two");
+
+        for (size_t i = 0; i != buffer_size; i += 1)
+            buffer_[i].sequence_.store(i, std::memory_order_relaxed);
+        enqueue_pos_.store(0, std::memory_order_relaxed);
+        dequeue_pos_.store(0, std::memory_order_relaxed);
+    }
+
+    ~mpmc_bounded_queue()
+    {
+        delete [] buffer_;
+    }
+
+
+    bool enqueue(T&& data)
+    {
+        cell_t* cell;
+        size_t pos = enqueue_pos_.load(std::memory_order_relaxed);
+        for (;;)
+        {
+            cell = &buffer_[pos & buffer_mask_];
+            size_t seq = cell->sequence_.load(std::memory_order_acquire);
+            intptr_t dif = (intptr_t)seq - (intptr_t)pos;
+            if (dif == 0)
+            {
+                if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
+                    break;
+            }
+            else if (dif < 0)
+            {
+                return false;
+            }
+            else
+            {
+                pos = enqueue_pos_.load(std::memory_order_relaxed);
+            }
+        }
+        cell->data_ = std::move(data);
+        cell->sequence_.store(pos + 1, std::memory_order_release);
+        return true;
+    }
+
+    bool dequeue(T& data)
+    {
+        cell_t* cell;
+        size_t pos = dequeue_pos_.load(std::memory_order_relaxed);
+        for (;;)
+        {
+            cell = &buffer_[pos & buffer_mask_];
+            size_t seq =
+                cell->sequence_.load(std::memory_order_acquire);
+            intptr_t dif = (intptr_t)seq - (intptr_t)(pos + 1);
+            if (dif == 0)
+            {
+                if (dequeue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
+                    break;
+            }
+            else if (dif < 0)
+                return false;
+            else
+                pos = dequeue_pos_.load(std::memory_order_relaxed);
+        }
+        data = std::move(cell->data_);
+        cell->sequence_.store(pos + buffer_mask_ + 1, std::memory_order_release);
+        return true;
+    }
+
+private:
+    struct cell_t
+    {
+        std::atomic<size_t>   sequence_;
+        T                     data_;
+    };
+
+    static size_t const     cacheline_size = 64;
+    typedef char            cacheline_pad_t [cacheline_size];
+
+    cacheline_pad_t         pad0_;
+    cell_t* const           buffer_;
+    size_t const            buffer_mask_;
+    cacheline_pad_t         pad1_;
+    std::atomic<size_t>     enqueue_pos_;
+    cacheline_pad_t         pad2_;
+    std::atomic<size_t>     dequeue_pos_;
+    cacheline_pad_t         pad3_;
+
+    mpmc_bounded_queue(mpmc_bounded_queue const&);
+    void operator = (mpmc_bounded_queue const&);
+};
+
+} // ns details
+} // ns spdlog

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/null_mutex.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/null_mutex.h b/include/spdlog/details/null_mutex.h
new file mode 100644
index 0000000..ebb56a5
--- /dev/null
+++ b/include/spdlog/details/null_mutex.h
@@ -0,0 +1,43 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library.     */
+/* Copyright (c) 2014 Gabi Melman.                                       */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#pragma once
+
+// null, no cost mutex
+
+namespace spdlog
+{
+namespace details
+{
+struct null_mutex
+{
+    void lock() {}
+    void unlock() {}
+    bool try_lock()
+    {
+        return true;
+    }
+};
+}
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/os.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/os.h b/include/spdlog/details/os.h
new file mode 100644
index 0000000..753b6d9
--- /dev/null
+++ b/include/spdlog/details/os.h
@@ -0,0 +1,198 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library.     */
+/* Copyright (c) 2014 Gabi Melman.                                       */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#pragma once
+#include<string>
+#include<cstdio>
+#include<ctime>
+
+#ifdef _WIN32
+# ifndef WIN32_LEAN_AND_MEAN
+#  define WIN32_LEAN_AND_MEAN
+# endif
+# include <Windows.h>
+
+#ifdef __MINGW32__
+#include <share.h>
+#endif
+
+#elif __linux__
+#include <sys/syscall.h> //Use gettid() syscall under linux to get thread id
+#include <unistd.h>
+#else
+#include <thread>
+#endif
+
+#include "../common.h"
+
+namespace spdlog
+{
+namespace details
+{
+namespace os
+{
+
+inline spdlog::log_clock::time_point now()
+{
+
+#if defined __linux__ && defined SPDLOG_CLOCK_COARSE
+    timespec ts;
+    ::clock_gettime(CLOCK_REALTIME_COARSE, &ts);
+    return std::chrono::time_point<log_clock, typename log_clock::duration>(
+               std::chrono::duration_cast<typename log_clock::duration>(
+                   std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec)));
+
+#else
+    return log_clock::now();
+#endif
+
+}
+inline std::tm localtime(const std::time_t &time_tt)
+{
+
+#ifdef _WIN32
+    std::tm tm;
+    localtime_s(&tm, &time_tt);
+#else
+    std::tm tm;
+    localtime_r(&time_tt, &tm);
+#endif
+    return tm;
+}
+
+inline std::tm localtime()
+{
+    std::time_t now_t = time(nullptr);
+    return localtime(now_t);
+}
+
+
+inline std::tm gmtime(const std::time_t &time_tt)
+{
+
+#ifdef _WIN32
+    std::tm tm;
+    gmtime_s(&tm, &time_tt);
+#else
+    std::tm tm;
+    gmtime_r(&time_tt, &tm);
+#endif
+    return tm;
+}
+
+inline std::tm gmtime()
+{
+    std::time_t now_t = time(nullptr);
+    return gmtime(now_t);
+}
+inline bool operator==(const std::tm& tm1, const std::tm& tm2)
+{
+    return (tm1.tm_sec == tm2.tm_sec &&
+            tm1.tm_min == tm2.tm_min &&
+            tm1.tm_hour == tm2.tm_hour &&
+            tm1.tm_mday == tm2.tm_mday &&
+            tm1.tm_mon == tm2.tm_mon &&
+            tm1.tm_year == tm2.tm_year &&
+            tm1.tm_isdst == tm2.tm_isdst);
+}
+
+inline bool operator!=(const std::tm& tm1, const std::tm& tm2)
+{
+    return !(tm1 == tm2);
+}
+
+#ifdef _WIN32
+inline const char* eol()
+{
+    return "\r\n";
+}
+#else
+constexpr inline const char* eol()
+{
+    return "\n";
+}
+#endif
+
+#ifdef _WIN32
+inline unsigned short eol_size()
+{
+    return 2;
+}
+#else
+constexpr inline unsigned short eol_size()
+{
+    return 1;
+}
+#endif
+
+//fopen_s on non windows for writing
+inline int fopen_s(FILE** fp, const std::string& filename, const char* mode)
+{
+#ifdef _WIN32
+    *fp = _fsopen((filename.c_str()), mode, _SH_DENYWR);
+    return *fp == nullptr;
+#else
+    *fp = fopen((filename.c_str()), mode);
+    return *fp == nullptr;
+#endif
+
+
+}
+
+//Return utc offset in minutes or -1 on failure
+inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
+{
+
+#ifdef _WIN32
+    (void)tm; // avoid unused param warning
+    DYNAMIC_TIME_ZONE_INFORMATION tzinfo;
+    auto rv = GetDynamicTimeZoneInformation(&tzinfo);
+    if (!rv)
+        return -1;
+    return -1 * (tzinfo.Bias + tzinfo.DaylightBias);
+#else
+    return static_cast<int>(tm.tm_gmtoff / 60);
+#endif
+}
+
+//Return current thread id as size_t
+//It exists because the std::this_thread::get_id() is much slower(espcially under VS 2013)
+inline size_t thread_id()
+{
+#ifdef _WIN32
+    return  static_cast<size_t>(::GetCurrentThreadId());
+#elif __linux__
+    return  static_cast<size_t>(syscall(SYS_gettid));
+#else //Default to standard C++11 (OSX and other Unix)
+    return static_cast<size_t>(std::hash<std::thread::id>()(std::this_thread::get_id()));
+#endif
+
+}
+
+} //os
+} //details
+} //spdlog
+
+
+

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/pattern_formatter_impl.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/pattern_formatter_impl.h b/include/spdlog/details/pattern_formatter_impl.h
new file mode 100644
index 0000000..a5b2d21
--- /dev/null
+++ b/include/spdlog/details/pattern_formatter_impl.h
@@ -0,0 +1,628 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library.     */
+/* Copyright (c) 2014 Gabi Melman.                                       */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#pragma once
+
+#include <string>
+#include <chrono>
+#include <memory>
+#include <vector>
+#include <thread>
+
+
+#include "../formatter.h"
+#include "./log_msg.h"
+#include "./os.h"
+
+namespace spdlog
+{
+namespace details
+{
+class flag_formatter
+{
+public:
+    virtual ~flag_formatter() {}
+    virtual void format(details::log_msg& msg, const std::tm& tm_time) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////
+// name & level pattern appenders
+///////////////////////////////////////////////////////////////////////
+namespace
+{
+class name_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm&) override
+    {
+        msg.formatted << msg.logger_name;
+    }
+};
+}
+
+// log level appender
+class level_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm&) override
+    {
+        msg.formatted << level::to_str(msg.level);
+    }
+};
+
+// short log level appender
+class short_level_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm&) override
+    {
+        msg.formatted << level::to_short_str(msg.level);
+    }
+};
+
+///////////////////////////////////////////////////////////////////////
+// Date time pattern appenders
+///////////////////////////////////////////////////////////////////////
+
+static const char* ampm(const tm& t)
+{
+    return t.tm_hour >= 12 ? "PM" : "AM";
+}
+
+static int to12h(const tm& t)
+{
+    return t.tm_hour > 12 ? t.tm_hour - 12 : t.tm_hour;
+}
+
+//Abbreviated weekday name
+static const std::string days[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+class a_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        msg.formatted << days[tm_time.tm_wday];
+    }
+};
+
+//Full weekday name
+static const std::string full_days[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
+class A_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        msg.formatted << full_days[tm_time.tm_wday];
+    }
+};
+
+//Abbreviated month
+static const std::string  months[] { "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec" };
+class b_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        msg.formatted<< months[tm_time.tm_mon];
+    }
+};
+
+//Full month name
+static const std::string full_months[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
+class B_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        msg.formatted << full_months[tm_time.tm_mon];
+    }
+};
+
+
+//write 2 ints seperated by sep with padding of 2
+static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, char sep)
+{
+    w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0');
+    return w;
+}
+
+//write 3 ints seperated by sep with padding of 2
+static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, int v3, char sep)
+{
+    w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0') << sep << fmt::pad(v3, 2, '0');
+    return w;
+}
+
+
+//Date and time representation (Thu Aug 23 15:35:46 2014)
+class c_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        msg.formatted << days[tm_time.tm_wday] << ' ' << months[tm_time.tm_mon] << ' ' << tm_time.tm_mday << ' ';
+        pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << tm_time.tm_year + 1900;
+    }
+};
+
+
+// year - 2 digit
+class C_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        msg.formatted << fmt::pad(tm_time.tm_year % 100, 2, '0');
+    }
+};
+
+
+
+// Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01
+class D_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        pad_n_join(msg.formatted, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_year % 100, '/');
+    }
+};
+
+
+// year - 4 digit
+class Y_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        msg.formatted << tm_time.tm_year + 1900;
+    }
+};
+
+// month 1-12
+class m_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        msg.formatted << fmt::pad(tm_time.tm_mon + 1, 2, '0');
+    }
+};
+
+// day of month 1-31
+class d_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        msg.formatted << fmt::pad(tm_time.tm_mday, 2, '0');
+    }
+};
+
+// hours in 24 format  0-23
+class H_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        msg.formatted << fmt::pad(tm_time.tm_hour, 2, '0');
+    }
+};
+
+// hours in 12 format  1-12
+class I_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        msg.formatted << fmt::pad(to12h(tm_time), 2, '0');
+    }
+};
+
+// ninutes 0-59
+class M_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        msg.formatted << fmt::pad(tm_time.tm_min, 2, '0');
+    }
+};
+
+// seconds 0-59
+class S_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        msg.formatted << fmt::pad(tm_time.tm_sec, 2, '0');
+    }
+};
+
+// milliseconds
+class e_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm&) override
+    {
+        auto duration = msg.time.time_since_epoch();
+        auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
+        msg.formatted << fmt::pad(static_cast<int>(millis), 3, '0');
+    }
+};
+
+// microseconds
+class f_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm&) override
+    {
+        auto duration = msg.time.time_since_epoch();
+        auto micros = std::chrono::duration_cast<std::chrono::microseconds>(duration).count() % 1000000;
+        msg.formatted << fmt::pad(static_cast<int>(micros), 6, '0');
+    }
+};
+
+// AM/PM
+class p_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        msg.formatted << ampm(tm_time);
+    }
+};
+
+
+// 12 hour clock 02:55:02 pm
+class r_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        pad_n_join(msg.formatted, to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << ampm(tm_time);
+    }
+};
+
+// 24-hour HH:MM time, equivalent to %H:%M
+class R_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, ':');
+    }
+};
+
+// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S
+class T_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+        pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':');
+    }
+};
+
+
+// ISO 8601 offset from UTC in timezone (+-HH:MM)
+class z_formatter :public flag_formatter
+{
+public:
+    const std::chrono::seconds cache_refresh = std::chrono::seconds(5);
+
+    z_formatter() :_last_update(std::chrono::seconds(0)) {}
+    z_formatter(const z_formatter&) = delete;
+    z_formatter& operator=(const z_formatter&) = delete;
+
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+#ifdef _WIN32
+        int total_minutes = get_cached_offset(msg, tm_time);
+#else
+        // No need to chache under gcc,
+        // it is very fast (already stored in tm.tm_gmtoff)
+        int total_minutes = os::utc_minutes_offset(tm_time);
+#endif
+
+        int h = total_minutes / 60;
+        int m = total_minutes % 60;
+        char sign = h >= 0 ? '+' : '-';
+        msg.formatted << sign;
+        pad_n_join(msg.formatted, h, m, ':');
+    }
+private:
+    log_clock::time_point _last_update;
+    int _offset_minutes;
+    std::mutex _mutex;
+
+    int get_cached_offset(const log_msg& msg, const std::tm& tm_time)
+    {
+        using namespace std::chrono;
+        std::lock_guard<std::mutex> l(_mutex);
+        if (msg.time - _last_update >= cache_refresh)
+        {
+            _offset_minutes = os::utc_minutes_offset(tm_time);
+            _last_update = msg.time;
+        }
+        return _offset_minutes;
+    }
+};
+
+
+
+//Thread id
+class t_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm&) override
+    {
+        msg.formatted << msg.thread_id;
+    }
+};
+
+
+class v_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm&) override
+    {
+        msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size());
+    }
+};
+
+class ch_formatter :public flag_formatter
+{
+public:
+    explicit ch_formatter(char ch) : _ch(ch)
+    {}
+    void format(details::log_msg& msg, const std::tm&) override
+    {
+        msg.formatted << _ch;
+    }
+private:
+    char _ch;
+};
+
+
+//aggregate user chars to display as is
+class aggregate_formatter :public flag_formatter
+{
+public:
+    aggregate_formatter()
+    {}
+    void add_ch(char ch)
+    {
+        _str += ch;
+    }
+    void format(details::log_msg& msg, const std::tm&) override
+    {
+        msg.formatted << _str;
+    }
+private:
+    std::string _str;
+};
+
+// Full info formatter
+// pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v
+class full_formatter :public flag_formatter
+{
+    void format(details::log_msg& msg, const std::tm& tm_time) override
+    {
+#ifndef SPDLOG_NO_DATETIME
+        auto duration = msg.time.time_since_epoch();
+        auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
+
+        /* Slower version(while still very fast - about 3.2 million lines/sec under 10 threads),
+        msg.formatted.write("[{:d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}.{:03d}] [{}] [{}] {} ",
+        tm_time.tm_year + 1900,
+        tm_time.tm_mon + 1,
+        tm_time.tm_mday,
+        tm_time.tm_hour,
+        tm_time.tm_min,
+        tm_time.tm_sec,
+        static_cast<int>(millis),
+        msg.logger_name,
+        level::to_str(msg.level),
+        msg.raw.str());*/
+
+
+        // Faster (albeit uglier) way to format the line (5.6 million lines/sec under 10 threads)
+        msg.formatted << '[' << static_cast<unsigned int>(tm_time.tm_year + 1900) << '-'
+                      << fmt::pad(static_cast<unsigned int>(tm_time.tm_mon + 1), 2, '0') << '-'
+                      << fmt::pad(static_cast<unsigned int>(tm_time.tm_mday), 2, '0') << ' '
+                      << fmt::pad(static_cast<unsigned int>(tm_time.tm_hour), 2, '0') << ':'
+                      << fmt::pad(static_cast<unsigned int>(tm_time.tm_min), 2, '0') << ':'
+                      << fmt::pad(static_cast<unsigned int>(tm_time.tm_sec), 2, '0') << '.'
+                      << fmt::pad(static_cast<unsigned int>(millis), 3, '0') << "] ";
+
+//no datetime needed
+#else
+        (void)tm_time;
+#endif
+
+#ifndef SPDLOG_NO_NAME
+        msg.formatted << '[' << msg.logger_name << "] ";
+#endif
+
+        msg.formatted << '[' << level::to_str(msg.level) << "] ";
+        msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size());
+    }
+};
+
+}
+}
+///////////////////////////////////////////////////////////////////////////////
+// pattern_formatter inline impl
+///////////////////////////////////////////////////////////////////////////////
+inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern)
+{
+    compile_pattern(pattern);
+}
+
+inline void spdlog::pattern_formatter::compile_pattern(const std::string& pattern)
+{
+    auto end = pattern.end();
+    std::unique_ptr<details::aggregate_formatter> user_chars;
+    for (auto it = pattern.begin(); it != end; ++it)
+    {
+        if (*it == '%')
+        {
+            if (user_chars) //append user chars found so far
+                _formatters.push_back(std::move(user_chars));
+
+            if (++it != end)
+                handle_flag(*it);
+            else
+                break;
+        }
+        else // chars not following the % sign should be displayed as is
+        {
+            if (!user_chars)
+                user_chars = std::unique_ptr<details::aggregate_formatter>(new details::aggregate_formatter());
+            user_chars->add_ch(*it);
+        }
+    }
+    if (user_chars) //append raw chars found so far
+    {
+        _formatters.push_back(std::move(user_chars));
+    }
+
+}
+inline void spdlog::pattern_formatter::handle_flag(char flag)
+{
+    switch (flag)
+    {
+    // logger name
+    case 'n':
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::name_formatter()));
+        break;
+
+    case 'l':
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::level_formatter()));
+        break;
+
+    case 'L':
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::short_level_formatter()));
+        break;
+
+    case('t') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::t_formatter()));
+        break;
+
+    case('v') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::v_formatter()));
+        break;
+
+    case('a') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::a_formatter()));
+        break;
+
+    case('A') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::A_formatter()));
+        break;
+
+    case('b') :
+    case('h') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::b_formatter()));
+        break;
+
+    case('B') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::B_formatter()));
+        break;
+    case('c') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::c_formatter()));
+        break;
+
+    case('C') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::C_formatter()));
+        break;
+
+    case('Y') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::Y_formatter()));
+        break;
+
+    case('D') :
+    case('x') :
+
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::D_formatter()));
+        break;
+
+    case('m') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::m_formatter()));
+        break;
+
+    case('d') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::d_formatter()));
+        break;
+
+    case('H') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::H_formatter()));
+        break;
+
+    case('I') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::I_formatter()));
+        break;
+
+    case('M') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::M_formatter()));
+        break;
+
+    case('S') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::S_formatter()));
+        break;
+
+    case('e') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::e_formatter()));
+        break;
+
+    case('f') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::f_formatter()));
+        break;
+
+    case('p') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::p_formatter()));
+        break;
+
+    case('r') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::r_formatter()));
+        break;
+
+    case('R') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::R_formatter()));
+        break;
+
+    case('T') :
+    case('X') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::T_formatter()));
+        break;
+
+    case('z') :
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::z_formatter()));
+        break;
+
+    case ('+'):
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::full_formatter()));
+        break;
+
+    default: //Unkown flag appears as is
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter('%')));
+        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter(flag)));
+        break;
+    }
+}
+
+
+inline void spdlog::pattern_formatter::format(details::log_msg& msg)
+{
+    try
+    {
+        auto tm_time = details::os::localtime(log_clock::to_time_t(msg.time));
+        for (auto &f : _formatters)
+        {
+            f->format(msg, tm_time);
+        }
+        //write eol
+        msg.formatted << details::os::eol();
+    }
+    catch(const fmt::FormatError& e)
+    {
+        throw spdlog_ex(fmt::format("formatting error while processing format string: {}", e.what()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/registry.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h
new file mode 100644
index 0000000..fd8e4be
--- /dev/null
+++ b/include/spdlog/details/registry.h
@@ -0,0 +1,180 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library.     */
+/* Copyright (c) 2014 Gabi Melman.                                       */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#pragma once
+// Loggers registy of unique name->logger pointer
+// An attempt to create a logger with an alreasy existing name will be ignored
+// If user requests a non existing logger, nullptr will be returned
+// This class is thread safe
+
+#include <string>
+#include <mutex>
+#include <unordered_map>
+#include <functional>
+
+#include "./null_mutex.h"
+#include "../logger.h"
+#include "../async_logger.h"
+#include "../common.h"
+
+namespace spdlog
+{
+namespace details
+{
+template <class Mutex> class registry_t
+{
+public:
+
+    void register_logger(std::shared_ptr<logger> logger)
+    {
+        std::lock_guard<Mutex> lock(_mutex);
+        register_logger_impl(logger);
+    }
+
+
+    std::shared_ptr<logger> get(const std::string& logger_name)
+    {
+        std::lock_guard<Mutex> lock(_mutex);
+        auto found = _loggers.find(logger_name);
+        return found == _loggers.end() ? nullptr : found->second;
+    }
+
+    template<class It>
+    std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
+    {
+
+        std::shared_ptr<logger> new_logger;
+
+        std::lock_guard<Mutex> lock(_mutex);
+
+
+        if (_async_mode)
+            new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms);
+        else
+            new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end);
+
+        if (_formatter)
+            new_logger->set_formatter(_formatter);
+
+        new_logger->set_level(_level);
+        register_logger_impl(new_logger);
+        return new_logger;
+    }
+
+    void drop(const std::string& logger_name)
+    {
+        std::lock_guard<Mutex> lock(_mutex);
+        _loggers.erase(logger_name);
+    }
+
+    void drop_all()
+    {
+        std::lock_guard<Mutex> lock(_mutex);
+        _loggers.clear();
+    }
+    std::shared_ptr<logger> create(const std::string& logger_name, sinks_init_list sinks)
+    {
+        return create(logger_name, sinks.begin(), sinks.end());
+    }
+
+    std::shared_ptr<logger> create(const std::string& logger_name, sink_ptr sink)
+    {
+        return create(logger_name, { sink });
+    }
+
+
+    void formatter(formatter_ptr f)
+    {
+        std::lock_guard<Mutex> lock(_mutex);
+        _formatter = f;
+        for (auto& l : _loggers)
+            l.second->set_formatter(_formatter);
+    }
+
+    void set_pattern(const std::string& pattern)
+    {
+        std::lock_guard<Mutex> lock(_mutex);
+        _formatter = std::make_shared<pattern_formatter>(pattern);
+        for (auto& l : _loggers)
+            l.second->set_formatter(_formatter);
+    }
+
+    void set_level(level::level_enum log_level)
+    {
+        std::lock_guard<Mutex> lock(_mutex);
+        for (auto& l : _loggers)
+            l.second->set_level(log_level);
+        _level = log_level;
+    }
+
+    void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms)
+    {
+        std::lock_guard<Mutex> lock(_mutex);
+        _async_mode = true;
+        _async_q_size = q_size;
+        _overflow_policy = overflow_policy;
+        _worker_warmup_cb = worker_warmup_cb;
+        _flush_interval_ms = flush_interval_ms;
+    }
+
+    void set_sync_mode()
+    {
+        std::lock_guard<Mutex> lock(_mutex);
+        _async_mode = false;
+    }
+
+    static registry_t<Mutex>& instance()
+    {
+        static registry_t<Mutex> s_instance;
+        return s_instance;
+    }
+
+private:
+    void register_logger_impl(std::shared_ptr<logger> logger)
+    {
+        auto logger_name = logger->name();
+        if (_loggers.find(logger_name) != std::end(_loggers))
+            throw spdlog_ex("logger with name " + logger_name + " already exists");
+        _loggers[logger->name()] = logger;
+    }
+    registry_t<Mutex>(){}
+    registry_t<Mutex>(const registry_t<Mutex>&) = delete;
+    registry_t<Mutex>& operator=(const registry_t<Mutex>&) = delete;
+    Mutex _mutex;
+    std::unordered_map <std::string, std::shared_ptr<logger>> _loggers;
+    formatter_ptr _formatter;
+    level::level_enum _level = level::info;
+    bool _async_mode = false;
+    size_t _async_q_size = 0;
+    async_overflow_policy _overflow_policy = async_overflow_policy::block_retry;
+    std::function<void()> _worker_warmup_cb = nullptr;
+    std::chrono::milliseconds _flush_interval_ms;
+};
+#ifdef SPDLOG_NO_REGISTRY_MUTEX
+typedef registry_t<spdlog::details::null_mutex> registry;
+#else
+typedef registry_t<std::mutex> registry;
+#endif
+}
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/spdlog_impl.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/spdlog_impl.h b/include/spdlog/details/spdlog_impl.h
new file mode 100644
index 0000000..cfd6f82
--- /dev/null
+++ b/include/spdlog/details/spdlog_impl.h
@@ -0,0 +1,154 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library.     */
+/* Copyright (c) 2014 Gabi Melman.                                       */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#pragma once
+
+//
+// Global registry functions
+//
+#include "registry.h"
+#include "../sinks/file_sinks.h"
+#include "../sinks/stdout_sinks.h"
+#include "../sinks/syslog_sink.h"
+
+inline void spdlog::register_logger(std::shared_ptr<logger> logger)
+{
+    return details::registry::instance().register_logger(logger);
+}
+
+inline std::shared_ptr<spdlog::logger> spdlog::get(const std::string& name)
+{
+    return details::registry::instance().get(name);
+}
+
+inline void spdlog::drop(const std::string &name)
+{
+    details::registry::instance().drop(name);
+}
+
+// Create multi/single threaded rotating file logger
+inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush)
+{
+    return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, "txt", max_file_size, max_files, force_flush);
+}
+
+inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush)
+{
+    return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, "txt", max_file_size, max_files, force_flush);
+}
+
+// Create file logger which creates new file at midnight):
+inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const std::string& filename, int hour, int minute, bool force_flush)
+{
+    return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, "txt", hour, minute, force_flush);
+}
+inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const std::string& filename, int hour, int minute, bool force_flush)
+{
+    return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, "txt", hour, minute, force_flush);
+}
+
+
+// Create stdout/stderr loggers
+inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string& logger_name)
+{
+    return details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_mt::instance());
+}
+
+inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st(const std::string& logger_name)
+{
+    return details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_st::instance());
+}
+
+inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt(const std::string& logger_name)
+{
+    return details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_mt::instance());
+}
+
+inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::string& logger_name)
+{
+    return details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_st::instance());
+}
+
+#ifdef __linux__
+// Create syslog logger
+inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(const std::string& logger_name, const std::string& syslog_ident, int syslog_option)
+{
+    return create<spdlog::sinks::syslog_sink>(logger_name, syslog_ident, syslog_option);
+}
+#endif
+
+
+//Create logger with multiple sinks
+
+inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, spdlog::sinks_init_list sinks)
+{
+    return details::registry::instance().create(logger_name, sinks);
+}
+
+
+template <typename Sink, typename... Args>
+inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const Args&... args)
+{
+    sink_ptr sink = std::make_shared<Sink>(args...);
+    return details::registry::instance().create(logger_name, { sink });
+}
+
+
+template<class It>
+inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
+{
+    return details::registry::instance().create(logger_name, sinks_begin, sinks_end);
+}
+
+inline void spdlog::set_formatter(spdlog::formatter_ptr f)
+{
+    details::registry::instance().formatter(f);
+}
+
+inline void spdlog::set_pattern(const std::string& format_string)
+{
+    return details::registry::instance().set_pattern(format_string);
+}
+
+inline void spdlog::set_level(level::level_enum log_level)
+{
+    return details::registry::instance().set_level(log_level);
+}
+
+
+inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms)
+{
+    details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms);
+}
+
+inline void spdlog::set_sync_mode()
+{
+    details::registry::instance().set_sync_mode();
+}
+
+inline void spdlog::drop_all()
+{
+    details::registry::instance().drop_all();
+}
+

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/formatter.h
----------------------------------------------------------------------
diff --git a/include/spdlog/formatter.h b/include/spdlog/formatter.h
new file mode 100644
index 0000000..35ea041
--- /dev/null
+++ b/include/spdlog/formatter.h
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library.     */
+/* Copyright (c) 2014 Gabi Melman.                                       */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+#pragma once
+
+#include "details/log_msg.h"
+namespace spdlog
+{
+namespace details
+{
+class flag_formatter;
+}
+
+class formatter
+{
+public:
+    virtual ~formatter() {}
+    virtual void format(details::log_msg& msg) = 0;
+};
+
+class pattern_formatter : public formatter
+{
+
+public:
+    explicit pattern_formatter(const std::string& pattern);
+    pattern_formatter(const pattern_formatter&) = delete;
+    pattern_formatter& operator=(const pattern_formatter&) = delete;
+    void format(details::log_msg& msg) override;
+private:
+    const std::string _pattern;
+    std::vector<std::unique_ptr<details::flag_formatter>> _formatters;
+    void handle_flag(char flag);
+    void compile_pattern(const std::string& pattern);
+};
+}
+
+#include "details/pattern_formatter_impl.h"
+

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/logger.h
----------------------------------------------------------------------
diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h
new file mode 100644
index 0000000..7aefcc7
--- /dev/null
+++ b/include/spdlog/logger.h
@@ -0,0 +1,132 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library.     */
+/* Copyright (c) 2014 Gabi Melman.                                       */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#pragma once
+
+// Thread safe logger
+// Has name, log level, vector of std::shared sink pointers and formatter
+// Upon each log write the logger:
+// 1. Checks if its log level is enough to log the message
+// 2. Format the message using the formatter function
+// 3. Pass the formatted message to its sinks to performa the actual logging
+
+#include<vector>
+#include<memory>
+#include "sinks/base_sink.h"
+#include "common.h"
+
+namespace spdlog
+{
+
+namespace details
+{
+class line_logger;
+}
+
+class logger
+{
+public:
+    logger(const std::string& logger_name, sink_ptr single_sink);
+    logger(const std::string& name, sinks_init_list);
+    template<class It>
+    logger(const std::string& name, const It& begin, const It& end);
+
+    virtual ~logger();
+    logger(const logger&) = delete;
+    logger& operator=(const logger&) = delete;
+
+    void set_level(level::level_enum);
+    level::level_enum level() const;
+
+    const std::string& name() const;
+    bool should_log(level::level_enum) const;
+
+    // logger.info(cppformat_string, arg1, arg2, arg3, ...) call style
+    template <typename... Args> details::line_logger trace(const char* fmt, const Args&... args);
+    template <typename... Args> details::line_logger debug(const char* fmt, const Args&... args);
+    template <typename... Args> details::line_logger info(const char* fmt, const Args&... args);
+    template <typename... Args> details::line_logger notice(const char* fmt, const Args&... args);
+    template <typename... Args> details::line_logger warn(const char* fmt, const Args&... args);
+    template <typename... Args> details::line_logger error(const char* fmt, const Args&... args);
+    template <typename... Args> details::line_logger critical(const char* fmt, const Args&... args);
+    template <typename... Args> details::line_logger alert(const char* fmt, const Args&... args);
+    template <typename... Args> details::line_logger emerg(const char* fmt, const Args&... args);
+
+
+    // logger.info(msg) << ".." call style
+    template <typename T> details::line_logger trace(const T&);
+    template <typename T> details::line_logger debug(const T&);
+    template <typename T> details::line_logger info(const T&);
+    template <typename T> details::line_logger notice(const T&);
+    template <typename T> details::line_logger warn(const T&);
+    template <typename T> details::line_logger error(const T&);
+    template <typename T> details::line_logger critical(const T&);
+    template <typename T> details::line_logger alert(const T&);
+    template <typename T> details::line_logger emerg(const T&);
+
+
+    // logger.info() << ".." call  style
+    details::line_logger trace();
+    details::line_logger debug();
+    details::line_logger info();
+    details::line_logger notice();
+    details::line_logger warn();
+    details::line_logger error();
+    details::line_logger critical();
+    details::line_logger alert();
+    details::line_logger emerg();
+
+
+
+    // Create log message with the given level, no matter what is the actual logger's level
+    template <typename... Args>
+    details::line_logger force_log(level::level_enum lvl, const char* fmt, const Args&... args);
+
+    // Set the format of the log messages from this logger
+    void set_pattern(const std::string&);
+    void set_formatter(formatter_ptr);
+
+    void flush();
+
+protected:
+    virtual void _log_msg(details::log_msg&);
+    virtual void _set_pattern(const std::string&);
+    virtual void _set_formatter(formatter_ptr);
+    details::line_logger _log_if_enabled(level::level_enum lvl);
+    template <typename... Args>
+    details::line_logger _log_if_enabled(level::level_enum lvl, const char* fmt, const Args&... args);
+    template<typename T>
+    inline details::line_logger _log_if_enabled(level::level_enum lvl, const T& msg);
+
+
+    friend details::line_logger;
+    std::string _name;
+    std::vector<sink_ptr> _sinks;
+    formatter_ptr _formatter;
+    std::atomic_int _level;
+
+};
+}
+
+#include "details/logger_impl.h"

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/sinks/base_sink.h
----------------------------------------------------------------------
diff --git a/include/spdlog/sinks/base_sink.h b/include/spdlog/sinks/base_sink.h
new file mode 100644
index 0000000..12d63ea
--- /dev/null
+++ b/include/spdlog/sinks/base_sink.h
@@ -0,0 +1,66 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library.     */
+/* Copyright (c) 2014 Gabi Melman.                                       */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#pragma once
+//
+// base sink templated over a mutex (either dummy or realy)
+// concrete implementation should only overrid the _sink_it method.
+// all locking is taken care of here so no locking needed by the implementors..
+//
+
+#include<string>
+#include<mutex>
+#include<atomic>
+#include "./sink.h"
+#include "../formatter.h"
+#include "../common.h"
+#include "../details/log_msg.h"
+
+
+namespace spdlog
+{
+namespace sinks
+{
+template<class Mutex>
+class base_sink:public sink
+{
+public:
+    base_sink():_mutex() {}
+    virtual ~base_sink() = default;
+
+    base_sink(const base_sink&) = delete;
+    base_sink& operator=(const base_sink&) = delete;
+
+    void log(const details::log_msg& msg) override
+    {
+        std::lock_guard<Mutex> lock(_mutex);
+        _sink_it(msg);
+    }
+
+protected:
+    virtual void _sink_it(const details::log_msg& msg) = 0;
+    Mutex _mutex;
+};
+}
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/sinks/file_sinks.h
----------------------------------------------------------------------
diff --git a/include/spdlog/sinks/file_sinks.h b/include/spdlog/sinks/file_sinks.h
new file mode 100644
index 0000000..79cbb4e
--- /dev/null
+++ b/include/spdlog/sinks/file_sinks.h
@@ -0,0 +1,232 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library.     */
+/* Copyright (c) 2014 Gabi Melman.                                       */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#pragma once
+
+#include <mutex>
+#include "base_sink.h"
+#include "../details/null_mutex.h"
+#include "../details/file_helper.h"
+#include "../details/format.h"
+
+namespace spdlog
+{
+namespace sinks
+{
+/*
+* Trivial file sink with single file as target
+*/
+template<class Mutex>
+class simple_file_sink : public base_sink < Mutex >
+{
+public:
+    explicit simple_file_sink(const std::string &filename,
+                              bool force_flush = false) :
+        _file_helper(force_flush)
+    {
+        _file_helper.open(filename);
+    }
+    void flush() override
+    {
+        _file_helper.flush();
+    }
+
+protected:
+    void _sink_it(const details::log_msg& msg) override
+    {
+        _file_helper.write(msg);
+    }
+private:
+    details::file_helper _file_helper;
+};
+
+typedef simple_file_sink<std::mutex> simple_file_sink_mt;
+typedef simple_file_sink<details::null_mutex> simple_file_sink_st;
+
+/*
+ * Rotating file sink based on size
+ */
+template<class Mutex>
+class rotating_file_sink : public base_sink < Mutex >
+{
+public:
+    rotating_file_sink(const std::string &base_filename, const std::string &extension,
+                       std::size_t max_size, std::size_t max_files,
+                       bool force_flush = false) :
+        _base_filename(base_filename),
+        _extension(extension),
+        _max_size(max_size),
+        _max_files(max_files),
+        _current_size(0),
+        _file_helper(force_flush)
+    {
+        _file_helper.open(calc_filename(_base_filename, 0, _extension));
+    }
+
+    void flush() override
+    {
+        _file_helper.flush();
+    }
+
+protected:
+    void _sink_it(const details::log_msg& msg) override
+    {
+        _current_size += msg.formatted.size();
+        if (_current_size > _max_size)
+        {
+            _rotate();
+            _current_size = msg.formatted.size();
+        }
+        _file_helper.write(msg);
+    }
+
+private:
+    static std::string calc_filename(const std::string& filename, std::size_t index, const std::string& extension)
+    {
+        fmt::MemoryWriter w;
+        if (index)
+            w.write("{}.{}.{}", filename, index, extension);
+        else
+            w.write("{}.{}", filename, extension);
+        return w.str();
+    }
+
+    // Rotate files:
+    // log.txt -> log.1.txt
+    // log.1.txt -> log2.txt
+    // log.2.txt -> log3.txt
+    // log.3.txt -> delete
+
+    void _rotate()
+    {
+        _file_helper.close();
+        for (auto i = _max_files; i > 0; --i)
+        {
+            std::string src = calc_filename(_base_filename, i - 1, _extension);
+            std::string target = calc_filename(_base_filename, i, _extension);
+
+            if (details::file_helper::file_exists(target))
+            {
+                if (std::remove(target.c_str()) != 0)
+                {
+                    throw spdlog_ex("rotating_file_sink: failed removing " + target);
+                }
+            }
+            if (details::file_helper::file_exists(src) && std::rename(src.c_str(), target.c_str()))
+            {
+                throw spdlog_ex("rotating_file_sink: failed renaming " + src + " to " + target);
+            }
+        }
+        _file_helper.reopen(true);
+    }
+    std::string _base_filename;
+    std::string _extension;
+    std::size_t _max_size;
+    std::size_t _max_files;
+    std::size_t _current_size;
+    details::file_helper _file_helper;
+};
+
+typedef rotating_file_sink<std::mutex> rotating_file_sink_mt;
+typedef rotating_file_sink<details::null_mutex>rotating_file_sink_st;
+
+/*
+ * Rotating file sink based on date. rotates at midnight
+ */
+template<class Mutex>
+class daily_file_sink :public base_sink < Mutex >
+{
+public:
+    //create daily file sink which rotates on given time
+    daily_file_sink(
+        const std::string& base_filename,
+        const std::string& extension,
+        int rotation_hour,
+        int rotation_minute,
+        bool force_flush = false) : _base_filename(base_filename),
+        _extension(extension),
+        _rotation_h(rotation_hour),
+        _rotation_m(rotation_minute),
+        _file_helper(force_flush)
+    {
+        if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
+            throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor");
+        _rotation_tp = _next_rotation_tp();
+        _file_helper.open(calc_filename(_base_filename, _extension));
+    }
+
+    void flush() override
+    {
+        _file_helper.flush();
+    }
+
+protected:
+    void _sink_it(const details::log_msg& msg) override
+    {
+        if (std::chrono::system_clock::now() >= _rotation_tp)
+        {
+            _file_helper.open(calc_filename(_base_filename, _extension));
+            _rotation_tp = _next_rotation_tp();
+        }
+        _file_helper.write(msg);
+    }
+
+private:
+    std::chrono::system_clock::time_point _next_rotation_tp()
+    {
+        using namespace std::chrono;
+        auto now = system_clock::now();
+        time_t tnow = std::chrono::system_clock::to_time_t(now);
+        tm date = spdlog::details::os::localtime(tnow);
+        date.tm_hour = _rotation_h;
+        date.tm_min = _rotation_m;
+        date.tm_sec = 0;
+        auto rotation_time = std::chrono::system_clock::from_time_t(std::mktime(&date));
+        if (rotation_time > now)
+            return rotation_time;
+        else
+            return system_clock::time_point(rotation_time + hours(24));
+    }
+
+    //Create filename for the form basename.YYYY-MM-DD.extension
+    static std::string calc_filename(const std::string& basename, const std::string& extension)
+    {
+        std::tm tm = spdlog::details::os::localtime();
+        fmt::MemoryWriter w;
+        w.write("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}.{}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, extension);
+        return w.str();
+    }
+
+    std::string _base_filename;
+    std::string _extension;
+    int _rotation_h;
+    int _rotation_m;
+    std::chrono::system_clock::time_point _rotation_tp;
+    details::file_helper _file_helper;
+};
+
+typedef daily_file_sink<std::mutex> daily_file_sink_mt;
+typedef daily_file_sink<details::null_mutex> daily_file_sink_st;
+}
+}