Commit 2757b777 authored by David Auer's avatar David Auer
Browse files

TBD: Update spdlog to 1.6.1

Silence warning in bundled fmt: https://github.com/fmtlib/fmt/issues/1267
parent 2ea31d25
Loading
Loading
Loading
Loading
+17 −11
Original line number Diff line number Diff line

//
// Copyright(c) 2018 Gabi Melman.
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

#pragma once

//
// Async logging using global thread pool
// All loggers created here share same global thread pool.
// Each log message is pushed to a queue along withe a shared pointer to the
// Each log message is pushed to a queue along with a shared pointer to the
// logger.
// If a logger deleted while having pending messages in the queue, it's actual
// destruction will defer
@@ -17,12 +14,13 @@
// This is because each message in the queue holds a shared_ptr to the
// originating logger.

#include "spdlog/async_logger.h"
#include "spdlog/details/registry.h"
#include "spdlog/details/thread_pool.h"
#include <spdlog/async_logger.h>
#include <spdlog/details/registry.h>
#include <spdlog/details/thread_pool.h>

#include <memory>
#include <mutex>
#include <functional>

namespace spdlog {

@@ -42,7 +40,9 @@ struct async_factory_impl
        auto &registry_inst = details::registry::instance();

        // create global thread pool if not already exists..
        std::lock_guard<std::recursive_mutex> tp_lock(registry_inst.tp_mutex());

        auto &mutex = registry_inst.tp_mutex();
        std::lock_guard<std::recursive_mutex> tp_lock(mutex);
        auto tp = registry_inst.get_tp();
        if (tp == nullptr)
        {
@@ -73,12 +73,18 @@ inline std::shared_ptr<spdlog::logger> create_async_nb(std::string logger_name,
}

// set global thread pool.
inline void init_thread_pool(size_t q_size, size_t thread_count)
inline void init_thread_pool(size_t q_size, size_t thread_count, std::function<void()> on_thread_start)
{
    auto tp = std::make_shared<details::thread_pool>(q_size, thread_count);
    auto tp = std::make_shared<details::thread_pool>(q_size, thread_count, on_thread_start);
    details::registry::instance().set_tp(std::move(tp));
}

// set global thread pool.
inline void init_thread_pool(size_t q_size, size_t thread_count)
{
    init_thread_pool(q_size, thread_count, [] {});
}

// get the global thread pool.
inline std::shared_ptr<spdlog::details::thread_pool> thread_pool()
{
+92 −0
Original line number Diff line number Diff line
//
// Copyright(c) 2015 Gabi Melman.
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

#pragma once

// async logger implementation
// uses a thread pool to perform the actual logging
#ifndef SPDLOG_HEADER_ONLY
#include <spdlog/async_logger.h>
#endif

#include "spdlog/details/thread_pool.h"
#include <spdlog/sinks/sink.h>
#include <spdlog/details/thread_pool.h>

#include <chrono>
#include <memory>
#include <string>

template<typename It>
inline spdlog::async_logger::async_logger(
    std::string logger_name, It begin, It end, std::weak_ptr<details::thread_pool> tp, async_overflow_policy overflow_policy)
    : logger(std::move(logger_name), begin, end)
    , thread_pool_(std::move(tp))
    , overflow_policy_(overflow_policy)
{
}

inline spdlog::async_logger::async_logger(
SPDLOG_INLINE spdlog::async_logger::async_logger(
    std::string logger_name, sinks_init_list sinks_list, std::weak_ptr<details::thread_pool> tp, async_overflow_policy overflow_policy)
    : async_logger(std::move(logger_name), sinks_list.begin(), sinks_list.end(), std::move(tp), overflow_policy)
{
}
{}

inline spdlog::async_logger::async_logger(
SPDLOG_INLINE spdlog::async_logger::async_logger(
    std::string logger_name, sink_ptr single_sink, std::weak_ptr<details::thread_pool> tp, async_overflow_policy overflow_policy)
    : async_logger(std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy)
{
}
{}

// send the log message to the thread pool
inline void spdlog::async_logger::sink_it_(details::log_msg &msg)
SPDLOG_INLINE void spdlog::async_logger::sink_it_(const details::log_msg &msg)
{
#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
    incr_msg_counter_(msg);
#endif
    if (auto pool_ptr = thread_pool_.lock())
    {
        pool_ptr->post_log(shared_from_this(), msg, overflow_policy_);
    }
    else
    {
        throw spdlog_ex("async log: thread pool doesn't exist anymore");
        throw_spdlog_ex("async log: thread pool doesn't exist anymore");
    }
}

// send flush request to the thread pool
inline void spdlog::async_logger::flush_()
SPDLOG_INLINE void spdlog::async_logger::flush_()
{
    if (auto pool_ptr = thread_pool_.lock())
    {
@@ -60,51 +45,48 @@ inline void spdlog::async_logger::flush_()
    }
    else
    {
        throw spdlog_ex("async flush: thread pool doesn't exist anymore");
        throw_spdlog_ex("async flush: thread pool doesn't exist anymore");
    }
}

//
// backend functions - called from the thread pool to do the actual job
//
inline void spdlog::async_logger::backend_log_(const details::log_msg &incoming_log_msg)
SPDLOG_INLINE void spdlog::async_logger::backend_sink_it_(const details::log_msg &msg)
{
    try
    for (auto &sink : sinks_)
    {
        for (auto &s : sinks_)
        if (sink->should_log(msg.level))
        {
            if (s->should_log(incoming_log_msg.level))
            SPDLOG_TRY
            {
                s->log(incoming_log_msg);
                sink->log(msg);
            }
            SPDLOG_LOGGER_CATCH()
        }
    }
    SPDLOG_CATCH_AND_HANDLE

    if (should_flush_(incoming_log_msg))
    if (should_flush_(msg))
    {
        backend_flush_();
    }
}

inline void spdlog::async_logger::backend_flush_()
{
    try
SPDLOG_INLINE void spdlog::async_logger::backend_flush_()
{
    for (auto &sink : sinks_)
    {
        SPDLOG_TRY
        {
            sink->flush();
        }
        SPDLOG_LOGGER_CATCH()
    }
    SPDLOG_CATCH_AND_HANDLE
}

inline std::shared_ptr<spdlog::logger> spdlog::async_logger::clone(std::string new_name)
SPDLOG_INLINE std::shared_ptr<spdlog::logger> spdlog::async_logger::clone(std::string new_name)
{
    auto cloned = std::make_shared<spdlog::async_logger>(std::move(new_name), sinks_.begin(), sinks_.end(), thread_pool_, overflow_policy_);

    cloned->set_level(this->level());
    cloned->flush_on(this->flush_level());
    cloned->set_error_handler(this->error_handler());
    return std::move(cloned);
    auto cloned = std::make_shared<spdlog::async_logger>(*this);
    cloned->name_ = std::move(new_name);
    return cloned;
}
+15 −20
Original line number Diff line number Diff line
//
// Copyright(c) 2015 Gabi Melman.
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

#pragma once

// Very fast asynchronous logger (millions of logs per second on an average
// desktop)
// Uses pre allocated lockfree queue for maximum throughput even under large
// number of threads.
// Fast asynchronous logger.
// Uses pre allocated queue.
// Creates a single back thread to pop messages from the queue and log them.
//
// Upon each log write the logger:
//    1. Checks if its log level is enough to log the message
//    2. Push a new copy of the message to a queue (or block the caller until
//    space is available in the queue)
//    3. will throw spdlog_ex upon log exceptions
// Upon destruction, logs all remaining messages in the queue before
// destructing..

#include "spdlog/common.h"
#include "spdlog/logger.h"

#include <chrono>
#include <memory>
#include <string>
#include <spdlog/logger.h>

namespace spdlog {

@@ -40,14 +30,18 @@ namespace details {
class thread_pool;
}

class async_logger final : public std::enable_shared_from_this<async_logger>, public logger
class SPDLOG_API async_logger final : public std::enable_shared_from_this<async_logger>, public logger
{
    friend class details::thread_pool;

public:
    template<typename It>
    async_logger(std::string logger_name, It begin, It end, std::weak_ptr<details::thread_pool> tp,
        async_overflow_policy overflow_policy = async_overflow_policy::block);
        async_overflow_policy overflow_policy = async_overflow_policy::block)
        : logger(std::move(logger_name), begin, end)
        , thread_pool_(std::move(tp))
        , overflow_policy_(overflow_policy)
    {}

    async_logger(std::string logger_name, sinks_init_list sinks_list, std::weak_ptr<details::thread_pool> tp,
        async_overflow_policy overflow_policy = async_overflow_policy::block);
@@ -58,10 +52,9 @@ public:
    std::shared_ptr<logger> clone(std::string new_name) override;

protected:
    void sink_it_(details::log_msg &msg) override;
    void sink_it_(const details::log_msg &msg) override;
    void flush_() override;

    void backend_log_(const details::log_msg &incoming_log_msg);
    void backend_sink_it_(const details::log_msg &incoming_log_msg);
    void backend_flush_();

private:
@@ -70,4 +63,6 @@ private:
};
} // namespace spdlog

#include "details/async_logger_impl.h"
#ifdef SPDLOG_HEADER_ONLY
#include "async_logger-inl.h"
#endif
+45 −0
Original line number Diff line number Diff line
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)

#pragma once
#include <spdlog/cfg/helpers.h>
#include <spdlog/details/registry.h>

//
// Init log levels using each argv entry that starts with "SPDLOG_LEVEL="
//
// set all loggers to debug level:
// example.exe "SPDLOG_LEVEL=debug"

// set logger1 to trace level
// example.exe "SPDLOG_LEVEL=logger1=trace"

// turn off all logging except for logger1 and logger2:
// example.exe "SPDLOG_LEVEL=off,logger1=debug,logger2=info"

namespace spdlog {
namespace cfg {

// search for SPDLOG_LEVEL= in the args and use it to init the levels
void load_argv_levels(int argc, const char **argv)
{
    const std::string spdlog_level_prefix = "SPDLOG_LEVEL=";
    for (int i = 1; i < argc; i++)
    {
        std::string arg = argv[i];
        if (arg.find(spdlog_level_prefix) == 0)
        {
            auto levels_string = arg.substr(spdlog_level_prefix.size());
            auto levels = helpers::extract_levels(levels_string);
            details::registry::instance().update_levels(std::move(levels));
        }
    }
}

void load_argv_levels(int argc, char **argv)
{
    load_argv_levels(argc, const_cast<const char **>(argv));
}

} // namespace cfg
} // namespace spdlog
+36 −0
Original line number Diff line number Diff line
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)

#pragma once
#include <spdlog/cfg/helpers.h>
#include <spdlog/details/registry.h>
#include <spdlog/details/os.h>

//
// Init levels and patterns from env variables SPDLOG_LEVEL
// Inspired from Rust's "env_logger" crate (https://crates.io/crates/env_logger).
// Note - fallback to "info" level on unrecognized levels
//
// Examples:
//
// set global level to debug:
// export SPDLOG_LEVEL=debug
//
// turn off all logging except for logger1:
// export SPDLOG_LEVEL="off,logger1=debug"
//

// turn off all logging except for logger1 and logger2:
// export SPDLOG_LEVEL="off,logger1=debug,logger2=info"

namespace spdlog {
namespace cfg {
void load_env_levels()
{
    auto env_val = details::os::getenv("SPDLOG_LEVEL");
    auto levels = helpers::extract_levels(env_val);
    details::registry::instance().update_levels(std::move(levels));
}

} // namespace cfg
} // namespace spdlog
Loading