Added periodic flusher support, and fixed some registry issues
This commit is contained in:
		
							parent
							
								
									d5af87a8e1
								
							
						
					
					
						commit
						a96b4d7529
					
				
							
								
								
									
										11
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								README.md
									
									
									
									
									
								
							@ -145,6 +145,7 @@ void rotating_example()
 | 
				
			|||||||
    auto rotating_logger = spdlog::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3);
 | 
					    auto rotating_logger = spdlog::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
#### Daily files
 | 
					#### Daily files
 | 
				
			||||||
```c++
 | 
					```c++
 | 
				
			||||||
@ -157,6 +158,16 @@ void daily_example()
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					#### Periodic flush
 | 
				
			||||||
 | 
					```c++
 | 
				
			||||||
 | 
					// periodically flush all *registered* loggers every 3 seconds:
 | 
				
			||||||
 | 
					// warning: only use if all your loggers are thread safe!
 | 
				
			||||||
 | 
					spdlog::flush_every(std::chrono::seconds(3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
#### Asynchronous logging
 | 
					#### Asynchronous logging
 | 
				
			||||||
```c++
 | 
					```c++
 | 
				
			||||||
 | 
				
			|||||||
@ -45,8 +45,14 @@ int main(int, char *[])
 | 
				
			|||||||
        // custom  error handler
 | 
					        // custom  error handler
 | 
				
			||||||
        err_handler_example();
 | 
					        err_handler_example();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // flush all *registered* loggers using a worker thread every 3 seconds.
 | 
				
			||||||
 | 
							// note: registered loggers *must* be thread safe for this to work correctly!
 | 
				
			||||||
 | 
					        spdlog::flush_every(std::chrono::seconds(3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // apply some function on all registered loggers
 | 
					        // apply some function on all registered loggers
 | 
				
			||||||
        spdlog::apply_all([&](std::shared_ptr<spdlog::logger> l) { l->info("End of example."); });
 | 
					        spdlog::apply_all([&](std::shared_ptr<spdlog::logger> l) {
 | 
				
			||||||
 | 
					            l->info("End of example.");
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Release and close all loggers
 | 
					        // Release and close all loggers
 | 
				
			||||||
        spdlog::drop_all();
 | 
					        spdlog::drop_all();
 | 
				
			||||||
@ -172,7 +178,9 @@ void user_defined_example()
 | 
				
			|||||||
void err_handler_example()
 | 
					void err_handler_example()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // can be set globally or per logger(logger->set_error_handler(..))
 | 
					    // can be set globally or per logger(logger->set_error_handler(..))
 | 
				
			||||||
    spdlog::set_error_handler([](const std::string &msg) { spdlog::get("console")->error("*** ERROR HANDLER EXAMPLE ***: {}", msg); });
 | 
					    spdlog::set_error_handler([](const std::string &msg) {
 | 
				
			||||||
 | 
					        spdlog::get("console")->error("*** ERROR HANDLER EXAMPLE ***: {}", msg);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
    spdlog::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3);
 | 
					    spdlog::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Microsoft Visual Studio Solution File, Format Version 12.00
 | 
					Microsoft Visual Studio Solution File, Format Version 12.00
 | 
				
			||||||
# Visual Studio 15
 | 
					# Visual Studio 2013
 | 
				
			||||||
VisualStudioVersion = 15.0.27428.2037
 | 
					VisualStudioVersion = 12.0.40629.0
 | 
				
			||||||
MinimumVisualStudioVersion = 10.0.40219.1
 | 
					MinimumVisualStudioVersion = 10.0.40219.1
 | 
				
			||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example", "example.vcxproj", "{9E5AB93A-0CCE-4BAC-9FCB-0FC9CB5EB8D2}"
 | 
					Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example", "example.vcxproj", "{9E5AB93A-0CCE-4BAC-9FCB-0FC9CB5EB8D2}"
 | 
				
			||||||
EndProject
 | 
					EndProject
 | 
				
			||||||
@ -29,6 +29,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "details", "details", "{08E9
 | 
				
			|||||||
		..\include\spdlog\details\null_mutex.h = ..\include\spdlog\details\null_mutex.h
 | 
							..\include\spdlog\details\null_mutex.h = ..\include\spdlog\details\null_mutex.h
 | 
				
			||||||
		..\include\spdlog\details\os.h = ..\include\spdlog\details\os.h
 | 
							..\include\spdlog\details\os.h = ..\include\spdlog\details\os.h
 | 
				
			||||||
		..\include\spdlog\details\pattern_formatter.h = ..\include\spdlog\details\pattern_formatter.h
 | 
							..\include\spdlog\details\pattern_formatter.h = ..\include\spdlog\details\pattern_formatter.h
 | 
				
			||||||
 | 
							..\include\spdlog\details\periodic_worker.h = ..\include\spdlog\details\periodic_worker.h
 | 
				
			||||||
		..\include\spdlog\details\registry.h = ..\include\spdlog\details\registry.h
 | 
							..\include\spdlog\details\registry.h = ..\include\spdlog\details\registry.h
 | 
				
			||||||
		..\include\spdlog\details\spdlog_impl.h = ..\include\spdlog\details\spdlog_impl.h
 | 
							..\include\spdlog\details\spdlog_impl.h = ..\include\spdlog\details\spdlog_impl.h
 | 
				
			||||||
		..\include\spdlog\details\thread_pool.h = ..\include\spdlog\details\thread_pool.h
 | 
							..\include\spdlog\details\thread_pool.h = ..\include\spdlog\details\thread_pool.h
 | 
				
			||||||
@ -101,16 +102,4 @@ Global
 | 
				
			|||||||
	GlobalSection(ExtensibilityGlobals) = postSolution
 | 
						GlobalSection(ExtensibilityGlobals) = postSolution
 | 
				
			||||||
		SolutionGuid = {1BF53532-C5DC-4236-B195-9E17CBE40A48}
 | 
							SolutionGuid = {1BF53532-C5DC-4236-B195-9E17CBE40A48}
 | 
				
			||||||
	EndGlobalSection
 | 
						EndGlobalSection
 | 
				
			||||||
	GlobalSection(Performance) = preSolution
 | 
					 | 
				
			||||||
		HasPerformanceSessions = true
 | 
					 | 
				
			||||||
	EndGlobalSection
 | 
					 | 
				
			||||||
	GlobalSection(Performance) = preSolution
 | 
					 | 
				
			||||||
		HasPerformanceSessions = true
 | 
					 | 
				
			||||||
	EndGlobalSection
 | 
					 | 
				
			||||||
	GlobalSection(Performance) = preSolution
 | 
					 | 
				
			||||||
		HasPerformanceSessions = true
 | 
					 | 
				
			||||||
	EndGlobalSection
 | 
					 | 
				
			||||||
	GlobalSection(Performance) = preSolution
 | 
					 | 
				
			||||||
		HasPerformanceSessions = true
 | 
					 | 
				
			||||||
	EndGlobalSection
 | 
					 | 
				
			||||||
EndGlobal
 | 
					EndGlobal
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@
 | 
				
			|||||||
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
 | 
					  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
 | 
				
			||||||
    <ConfigurationType>Application</ConfigurationType>
 | 
					    <ConfigurationType>Application</ConfigurationType>
 | 
				
			||||||
    <UseDebugLibraries>true</UseDebugLibraries>
 | 
					    <UseDebugLibraries>true</UseDebugLibraries>
 | 
				
			||||||
    <PlatformToolset>v141</PlatformToolset>
 | 
					    <PlatformToolset>v120</PlatformToolset>
 | 
				
			||||||
    <CharacterSet>Unicode</CharacterSet>
 | 
					    <CharacterSet>Unicode</CharacterSet>
 | 
				
			||||||
  </PropertyGroup>
 | 
					  </PropertyGroup>
 | 
				
			||||||
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
 | 
					  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
 | 
				
			||||||
@ -43,7 +43,7 @@
 | 
				
			|||||||
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
 | 
					  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
 | 
				
			||||||
    <ConfigurationType>Application</ConfigurationType>
 | 
					    <ConfigurationType>Application</ConfigurationType>
 | 
				
			||||||
    <UseDebugLibraries>false</UseDebugLibraries>
 | 
					    <UseDebugLibraries>false</UseDebugLibraries>
 | 
				
			||||||
    <PlatformToolset>v141</PlatformToolset>
 | 
					    <PlatformToolset>v120</PlatformToolset>
 | 
				
			||||||
    <WholeProgramOptimization>true</WholeProgramOptimization>
 | 
					    <WholeProgramOptimization>true</WholeProgramOptimization>
 | 
				
			||||||
    <CharacterSet>Unicode</CharacterSet>
 | 
					    <CharacterSet>Unicode</CharacterSet>
 | 
				
			||||||
  </PropertyGroup>
 | 
					  </PropertyGroup>
 | 
				
			||||||
@ -86,7 +86,7 @@
 | 
				
			|||||||
    <ClCompile>
 | 
					    <ClCompile>
 | 
				
			||||||
      <PrecompiledHeader>
 | 
					      <PrecompiledHeader>
 | 
				
			||||||
      </PrecompiledHeader>
 | 
					      </PrecompiledHeader>
 | 
				
			||||||
      <WarningLevel>Level3</WarningLevel>
 | 
					      <WarningLevel>Level4</WarningLevel>
 | 
				
			||||||
      <Optimization>Disabled</Optimization>
 | 
					      <Optimization>Disabled</Optimization>
 | 
				
			||||||
      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
 | 
					      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
 | 
				
			||||||
      <AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
 | 
					      <AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
 | 
				
			||||||
 | 
				
			|||||||
@ -19,8 +19,12 @@
 | 
				
			|||||||
#include "spdlog/details/thread_pool.h"
 | 
					#include "spdlog/details/thread_pool.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace spdlog {
 | 
					namespace spdlog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace details {
 | 
				
			||||||
 | 
					static const size_t default_async_q_size = 8192;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// async logger factory - creates async loggers backed with thread pool.
 | 
					// async logger factory - creates async loggers backed with thread pool.
 | 
				
			||||||
// if a global thread pool doesn't already exist, create it with default queue size of 8192 items and single thread.
 | 
					// if a global thread pool doesn't already exist, create it with default queue size of 8192 items and single thread.
 | 
				
			||||||
@ -32,11 +36,11 @@ struct async_factory_impl
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        using details::registry;
 | 
					        using details::registry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::lock_guard<registry::MutexT> lock(registry::instance().tp_mutex());
 | 
					        std::lock_guard<std::recursive_mutex> lock(registry::instance().tp_mutex());
 | 
				
			||||||
        auto tp = registry::instance().get_thread_pool();
 | 
					        auto tp = registry::instance().get_thread_pool();
 | 
				
			||||||
        if (tp == nullptr)
 | 
					        if (tp == nullptr)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            tp = std::make_shared<details::thread_pool>(8192, 1);
 | 
					            tp = std::make_shared<details::thread_pool>(details::default_async_q_size, 1);
 | 
				
			||||||
            registry::instance().set_thread_pool(tp);
 | 
					            registry::instance().set_thread_pool(tp);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -62,7 +66,7 @@ inline std::shared_ptr<spdlog::logger> create_async_nb(const std::string &logger
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    return async_factory_nonblock::create<Sink>(logger_name, std::forward<SinkArgs>(sink_args)...);
 | 
					    return async_factory_nonblock::create<Sink>(logger_name, std::forward<SinkArgs>(sink_args)...);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// set global thread pool.
 | 
					// 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)
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "spdlog/common.h"
 | 
					#include "spdlog/common.h"
 | 
				
			||||||
#include "spdlog/logger.h"
 | 
					#include "spdlog/logger.h"
 | 
				
			||||||
 | 
					#include "spdlog/details/periodic_worker.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <chrono>
 | 
					#include <chrono>
 | 
				
			||||||
#include <functional>
 | 
					#include <functional>
 | 
				
			||||||
@ -34,7 +35,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void register_logger(std::shared_ptr<logger> new_logger)
 | 
					    void register_logger(std::shared_ptr<logger> new_logger)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<Mutex> lock(mutex_);
 | 
					        std::lock_guard<Mutex> lock(loggers_mutex_);
 | 
				
			||||||
        auto logger_name = new_logger->name();
 | 
					        auto logger_name = new_logger->name();
 | 
				
			||||||
        throw_if_exists_(logger_name);
 | 
					        throw_if_exists_(logger_name);
 | 
				
			||||||
        loggers_[logger_name] = new_logger;
 | 
					        loggers_[logger_name] = new_logger;
 | 
				
			||||||
@ -42,7 +43,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void register_and_init(std::shared_ptr<logger> new_logger)
 | 
					    void register_and_init(std::shared_ptr<logger> new_logger)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<Mutex> lock(mutex_);
 | 
					        std::lock_guard<Mutex> lock(loggers_mutex_);
 | 
				
			||||||
        auto logger_name = new_logger->name();
 | 
					        auto logger_name = new_logger->name();
 | 
				
			||||||
        throw_if_exists_(logger_name);
 | 
					        throw_if_exists_(logger_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -63,26 +64,26 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    std::shared_ptr<logger> get(const std::string &logger_name)
 | 
					    std::shared_ptr<logger> get(const std::string &logger_name)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<Mutex> lock(mutex_);
 | 
					        std::lock_guard<Mutex> lock(loggers_mutex_);
 | 
				
			||||||
        auto found = loggers_.find(logger_name);
 | 
					        auto found = loggers_.find(logger_name);
 | 
				
			||||||
        return found == loggers_.end() ? nullptr : found->second;
 | 
					        return found == loggers_.end() ? nullptr : found->second;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void set_thread_pool(std::shared_ptr<thread_pool> tp)
 | 
					    void set_thread_pool(std::shared_ptr<thread_pool> tp)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<Mutex> lock(mutex_);
 | 
					        std::lock_guard<decltype(tp_mutex_)> lock(tp_mutex_);
 | 
				
			||||||
        tp_ = std::move(tp);
 | 
					        tp_ = std::move(tp);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::shared_ptr<thread_pool> get_thread_pool()
 | 
					    std::shared_ptr<thread_pool> get_thread_pool()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<Mutex> lock(mutex_);
 | 
					        std::lock_guard<decltype(tp_mutex_)> lock(tp_mutex_);
 | 
				
			||||||
        return tp_;
 | 
					        return tp_;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void set_pattern(const std::string &pattern, pattern_time_type time_type)
 | 
					    void set_pattern(const std::string &pattern, pattern_time_type time_type)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<Mutex> lock(mutex_);
 | 
					        std::lock_guard<Mutex> lock(loggers_mutex_);
 | 
				
			||||||
        formatter_pattern_ = pattern;
 | 
					        formatter_pattern_ = pattern;
 | 
				
			||||||
        pattern_time_type_ = time_type;
 | 
					        pattern_time_type_ = time_type;
 | 
				
			||||||
        for (auto &l : loggers_)
 | 
					        for (auto &l : loggers_)
 | 
				
			||||||
@ -93,7 +94,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void set_level(level::level_enum log_level)
 | 
					    void set_level(level::level_enum log_level)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<Mutex> lock(mutex_);
 | 
					        std::lock_guard<Mutex> lock(loggers_mutex_);
 | 
				
			||||||
        for (auto &l : loggers_)
 | 
					        for (auto &l : loggers_)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            l.second->set_level(log_level);
 | 
					            l.second->set_level(log_level);
 | 
				
			||||||
@ -103,7 +104,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void flush_on(level::level_enum log_level)
 | 
					    void flush_on(level::level_enum log_level)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<Mutex> lock(mutex_);
 | 
					        std::lock_guard<Mutex> lock(loggers_mutex_);
 | 
				
			||||||
        for (auto &l : loggers_)
 | 
					        for (auto &l : loggers_)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            l.second->flush_on(log_level);
 | 
					            l.second->flush_on(log_level);
 | 
				
			||||||
@ -111,6 +112,13 @@ public:
 | 
				
			|||||||
        flush_level_ = log_level;
 | 
					        flush_level_ = log_level;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void flush_every(std::chrono::seconds interval)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::lock_guard<Mutex> lock(loggers_mutex_);
 | 
				
			||||||
 | 
					        std::function<void()> clbk(std::bind(®istry_t::flush_all, this));
 | 
				
			||||||
 | 
					        periodic_flusher_.reset(new periodic_worker(clbk, interval));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void set_error_handler(log_err_handler handler)
 | 
					    void set_error_handler(log_err_handler handler)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        for (auto &l : loggers_)
 | 
					        for (auto &l : loggers_)
 | 
				
			||||||
@ -122,7 +130,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void apply_all(std::function<void(std::shared_ptr<logger>)> fun)
 | 
					    void apply_all(std::function<void(std::shared_ptr<logger>)> fun)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<Mutex> lock(mutex_);
 | 
					        std::lock_guard<Mutex> lock(loggers_mutex_);
 | 
				
			||||||
        for (auto &l : loggers_)
 | 
					        for (auto &l : loggers_)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            fun(l.second);
 | 
					            fun(l.second);
 | 
				
			||||||
@ -131,24 +139,24 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void drop(const std::string &logger_name)
 | 
					    void drop(const std::string &logger_name)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<Mutex> lock(mutex_);
 | 
					        std::lock_guard<Mutex> lock(loggers_mutex_);
 | 
				
			||||||
        loggers_.erase(logger_name);
 | 
					        loggers_.erase(logger_name);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void drop_all()
 | 
					    void drop_all()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::lock_guard<Mutex> lock(mutex_);
 | 
					            std::lock_guard<Mutex> lock(loggers_mutex_);
 | 
				
			||||||
            loggers_.clear();
 | 
					            loggers_.clear();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::lock_guard<Mutex> lock(tp_mutex_);
 | 
					            std::lock_guard<decltype(tp_mutex_)> lock(tp_mutex_);
 | 
				
			||||||
            tp_.reset();
 | 
					            tp_.reset();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Mutex &tp_mutex()
 | 
					    std::recursive_mutex &tp_mutex()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return tp_mutex_;
 | 
					        return tp_mutex_;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -162,6 +170,11 @@ public:
 | 
				
			|||||||
private:
 | 
					private:
 | 
				
			||||||
    registry_t<Mutex>() = default;
 | 
					    registry_t<Mutex>() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ~registry_t<Mutex>()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        periodic_flusher_.reset();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void throw_if_exists_(const std::string &logger_name)
 | 
					    void throw_if_exists_(const std::string &logger_name)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (loggers_.find(logger_name) != loggers_.end())
 | 
					        if (loggers_.find(logger_name) != loggers_.end())
 | 
				
			||||||
@ -170,8 +183,17 @@ private:
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Mutex mutex_;
 | 
					    void flush_all()
 | 
				
			||||||
    Mutex tp_mutex_;
 | 
					    {
 | 
				
			||||||
 | 
					        std::lock_guard<Mutex> lock(loggers_mutex_);
 | 
				
			||||||
 | 
					        for (auto &l : loggers_)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            l.second->flush();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Mutex loggers_mutex_;
 | 
				
			||||||
 | 
					    std::recursive_mutex tp_mutex_;
 | 
				
			||||||
    std::unordered_map<std::string, std::shared_ptr<logger>> loggers_;
 | 
					    std::unordered_map<std::string, std::shared_ptr<logger>> loggers_;
 | 
				
			||||||
    std::string formatter_pattern_ = "%+";
 | 
					    std::string formatter_pattern_ = "%+";
 | 
				
			||||||
    pattern_time_type pattern_time_type_ = pattern_time_type::local;
 | 
					    pattern_time_type pattern_time_type_ = pattern_time_type::local;
 | 
				
			||||||
@ -179,6 +201,7 @@ private:
 | 
				
			|||||||
    level::level_enum flush_level_ = level::off;
 | 
					    level::level_enum flush_level_ = level::off;
 | 
				
			||||||
    log_err_handler err_handler_;
 | 
					    log_err_handler err_handler_;
 | 
				
			||||||
    std::shared_ptr<thread_pool> tp_;
 | 
					    std::shared_ptr<thread_pool> tp_;
 | 
				
			||||||
 | 
					    std::unique_ptr<periodic_worker> periodic_flusher_;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef SPDLOG_NO_REGISTRY_MUTEX
 | 
					#ifdef SPDLOG_NO_REGISTRY_MUTEX
 | 
				
			||||||
 | 
				
			|||||||
@ -71,6 +71,14 @@ inline void flush_on(level::level_enum log_level)
 | 
				
			|||||||
    details::registry::instance().flush_on(log_level);
 | 
					    details::registry::instance().flush_on(log_level);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Start/Restart a periodic flusher thread
 | 
				
			||||||
 | 
					// Warning: Use only if all your loggers are thread safe!
 | 
				
			||||||
 | 
					inline void flush_every(std::chrono::seconds interval)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    details::registry::instance().flush_every(interval);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Set global error handler
 | 
					// Set global error handler
 | 
				
			||||||
inline void set_error_handler(log_err_handler handler)
 | 
					inline void set_error_handler(log_err_handler handler)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
				
			|||||||
@ -27,34 +27,34 @@ TEST_CASE("discard policy ", "[async]")
 | 
				
			|||||||
    using namespace spdlog;
 | 
					    using namespace spdlog;
 | 
				
			||||||
    auto test_sink = std::make_shared<sinks::test_sink_mt>();
 | 
					    auto test_sink = std::make_shared<sinks::test_sink_mt>();
 | 
				
			||||||
    size_t queue_size = 2;
 | 
					    size_t queue_size = 2;
 | 
				
			||||||
    size_t messages = 1024;
 | 
					    size_t messages = 10240;
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
 | 
					 | 
				
			||||||
        auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::overrun_oldest);
 | 
					 | 
				
			||||||
        for (size_t i = 0; i < messages; i++)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            logger->info("Hello message #{}", i);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
 | 
				
			||||||
 | 
					    auto logger = std::make_shared<async_logger>("as", test_sink, tp, async_overflow_policy::overrun_oldest);
 | 
				
			||||||
 | 
					    for (size_t i = 0; i < messages; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        logger->info("Hello message");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    REQUIRE(test_sink->msg_counter() < messages);
 | 
					    REQUIRE(test_sink->msg_counter() < messages);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_CASE("discard policy using factory ", "[async]")
 | 
					TEST_CASE("discard policy using factory ", "[async]")
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    using namespace spdlog;
 | 
					    using namespace spdlog;
 | 
				
			||||||
    //auto test_sink = std::make_shared<sinks::test_sink_mt>();
 | 
					 | 
				
			||||||
    size_t queue_size = 2;
 | 
					    size_t queue_size = 2;
 | 
				
			||||||
    size_t messages = 1024;
 | 
					    size_t messages = 10240;
 | 
				
			||||||
    {        
 | 
					    spdlog::init_thread_pool(queue_size, 1);
 | 
				
			||||||
        auto logger = spdlog::create_async_nb<sinks::test_sink_mt>("as2");
 | 
					
 | 
				
			||||||
        for (size_t i = 0; i < messages; i++)
 | 
					    auto logger = spdlog::create_async_nb<sinks::test_sink_mt>("as2");
 | 
				
			||||||
        {
 | 
					    for (size_t i = 0; i < messages; i++)
 | 
				
			||||||
            logger->info("Hello message #{}", i);
 | 
					    {
 | 
				
			||||||
        }
 | 
					        logger->info("Hello message");
 | 
				
			||||||
        auto sink = std::static_pointer_cast<sinks::test_sink_mt>(logger->sinks()[0]);
 | 
					    }
 | 
				
			||||||
		REQUIRE(sink->msg_counter() < messages);
 | 
					    auto sink = std::static_pointer_cast<sinks::test_sink_mt>(logger->sinks()[0]);
 | 
				
			||||||
    }    
 | 
					    REQUIRE(sink->msg_counter() < messages);
 | 
				
			||||||
 | 
					    spdlog::drop_all();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_CASE("flush", "[async]")
 | 
					TEST_CASE("flush", "[async]")
 | 
				
			||||||
@ -73,11 +73,27 @@ TEST_CASE("flush", "[async]")
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        logger->flush();
 | 
					        logger->flush();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    std::this_thread::sleep_for(std::chrono::milliseconds(250));
 | 
					    //std::this_thread::sleep_for(std::chrono::milliseconds(250));
 | 
				
			||||||
    REQUIRE(test_sink->msg_counter() == messages);
 | 
					    REQUIRE(test_sink->msg_counter() == messages);
 | 
				
			||||||
    REQUIRE(test_sink->flush_counter() == 1);
 | 
					    REQUIRE(test_sink->flush_counter() == 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_CASE("async periodic flush", "[async]")
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using namespace spdlog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto logger = spdlog::create_async<sinks::test_sink_mt>("as");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto test_sink = std::static_pointer_cast<sinks::test_sink_mt>(logger->sinks()[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spdlog::flush_every(std::chrono::seconds(1));
 | 
				
			||||||
 | 
					    std::this_thread::sleep_for(std::chrono::milliseconds(1100));
 | 
				
			||||||
 | 
					    REQUIRE(test_sink->flush_counter() == 1);
 | 
				
			||||||
 | 
					    spdlog::flush_every(std::chrono::seconds(0));
 | 
				
			||||||
 | 
					    spdlog::drop_all();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_CASE("tp->wait_empty() ", "[async]")
 | 
					TEST_CASE("tp->wait_empty() ", "[async]")
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    using namespace spdlog;
 | 
					    using namespace spdlog;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
#include "includes.h"
 | 
					#include "includes.h"
 | 
				
			||||||
 | 
					#include "test_sink.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<class T>
 | 
					template<class T>
 | 
				
			||||||
std::string log_info(const T &what, spdlog::level::level_enum logger_level = spdlog::level::info)
 | 
					std::string log_info(const T &what, spdlog::level::level_enum logger_level = spdlog::level::info)
 | 
				
			||||||
@ -75,3 +76,19 @@ TEST_CASE("to_level_enum", "[convert_to_level_enum]")
 | 
				
			|||||||
    REQUIRE(spdlog::level::from_str("off") == spdlog::level::off);
 | 
					    REQUIRE(spdlog::level::from_str("off") == spdlog::level::off);
 | 
				
			||||||
    REQUIRE(spdlog::level::from_str("null") == spdlog::level::off);
 | 
					    REQUIRE(spdlog::level::from_str("null") == spdlog::level::off);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_CASE("periodic flush", "[periodic_flush]")
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using namespace spdlog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto logger = spdlog::create<sinks::test_sink_mt>("periodic_flush");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto test_sink = std::static_pointer_cast<sinks::test_sink_mt>(logger->sinks()[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spdlog::flush_every(std::chrono::seconds(1));
 | 
				
			||||||
 | 
					    std::this_thread::sleep_for(std::chrono::milliseconds(1100));
 | 
				
			||||||
 | 
					    REQUIRE(test_sink->flush_counter() == 1);
 | 
				
			||||||
 | 
					    spdlog::flush_every(std::chrono::seconds(0));
 | 
				
			||||||
 | 
					    spdlog::drop_all();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -110,7 +110,7 @@
 | 
				
			|||||||
  </ItemDefinitionGroup>
 | 
					  </ItemDefinitionGroup>
 | 
				
			||||||
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
 | 
					  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
 | 
				
			||||||
    <ClCompile>
 | 
					    <ClCompile>
 | 
				
			||||||
      <WarningLevel>Level4</WarningLevel>
 | 
					      <WarningLevel>Level3</WarningLevel>
 | 
				
			||||||
      <Optimization>MaxSpeed</Optimization>
 | 
					      <Optimization>MaxSpeed</Optimization>
 | 
				
			||||||
      <FunctionLevelLinking>true</FunctionLevelLinking>
 | 
					      <FunctionLevelLinking>true</FunctionLevelLinking>
 | 
				
			||||||
      <IntrinsicFunctions>true</IntrinsicFunctions>
 | 
					      <IntrinsicFunctions>true</IntrinsicFunctions>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user