Initial import
This commit is contained in:
		
						commit
						681e40ce46
					
				
							
								
								
									
										37
									
								
								ReadMe.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								ReadMe.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| ======================================================================== | ||||
|     STATIC LIBRARY : c11log Project Overview | ||||
| ======================================================================== | ||||
| 
 | ||||
| AppWizard has created this c11log library project for you. | ||||
| 
 | ||||
| This file contains a summary of what you will find in each of the files that | ||||
| make up your c11log application. | ||||
| 
 | ||||
| 
 | ||||
| c11log.vcxproj | ||||
|     This is the main project file for VC++ projects generated using an Application Wizard. | ||||
|     It contains information about the version of Visual C++ that generated the file, and | ||||
|     information about the platforms, configurations, and project features selected with the | ||||
|     Application Wizard. | ||||
| 
 | ||||
| c11log.vcxproj.filters | ||||
|     This is the filters file for VC++ projects generated using an Application Wizard.  | ||||
|     It contains information about the association between the files in your project  | ||||
|     and the filters. This association is used in the IDE to show grouping of files with | ||||
|     similar extensions under a specific node (for e.g. ".cpp" files are associated with the | ||||
|     "Source Files" filter). | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////// | ||||
| 
 | ||||
| StdAfx.h, StdAfx.cpp | ||||
|     These files are used to build a precompiled header (PCH) file | ||||
|     named c11log.pch and a precompiled types file named StdAfx.obj. | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////// | ||||
| Other notes: | ||||
| 
 | ||||
| AppWizard uses "TODO:" comments to indicate parts of the source code you | ||||
| should add to or customize. | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////// | ||||
							
								
								
									
										115
									
								
								c11log.vcxproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								c11log.vcxproj
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,115 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
|   <ItemGroup Label="ProjectConfigurations"> | ||||
|     <ProjectConfiguration Include="Debug|Win32"> | ||||
|       <Configuration>Debug</Configuration> | ||||
|       <Platform>Win32</Platform> | ||||
|     </ProjectConfiguration> | ||||
|     <ProjectConfiguration Include="Release|Win32"> | ||||
|       <Configuration>Release</Configuration> | ||||
|       <Platform>Win32</Platform> | ||||
|     </ProjectConfiguration> | ||||
|   </ItemGroup> | ||||
|   <PropertyGroup Label="Globals"> | ||||
|     <ProjectGuid>{BBFA8622-1945-4EB0-BAF4-473BE753ED24}</ProjectGuid> | ||||
|     <Keyword>Win32Proj</Keyword> | ||||
|     <RootNamespace>c11log</RootNamespace> | ||||
|   </PropertyGroup> | ||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> | ||||
|     <ConfigurationType>StaticLibrary</ConfigurationType> | ||||
|     <UseDebugLibraries>true</UseDebugLibraries> | ||||
|     <PlatformToolset>v120</PlatformToolset> | ||||
|     <CharacterSet>Unicode</CharacterSet> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> | ||||
|     <ConfigurationType>StaticLibrary</ConfigurationType> | ||||
|     <UseDebugLibraries>false</UseDebugLibraries> | ||||
|     <PlatformToolset>v120</PlatformToolset> | ||||
|     <WholeProgramOptimization>true</WholeProgramOptimization> | ||||
|     <CharacterSet>Unicode</CharacterSet> | ||||
|   </PropertyGroup> | ||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | ||||
|   <ImportGroup Label="ExtensionSettings"> | ||||
|   </ImportGroup> | ||||
|   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | ||||
|     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||||
|   </ImportGroup> | ||||
|   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | ||||
|     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||||
|   </ImportGroup> | ||||
|   <PropertyGroup Label="UserMacros" /> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | ||||
|     <OutDir>$(ProjectDir)build\</OutDir> | ||||
|     <TargetName>$(ProjectName)-debug</TargetName> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | ||||
|     <OutDir>$(ProjectDir)build\</OutDir> | ||||
|     <TargetName>$(ProjectName)</TargetName> | ||||
|   </PropertyGroup> | ||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | ||||
|     <ClCompile> | ||||
|       <PrecompiledHeader>Use</PrecompiledHeader> | ||||
|       <WarningLevel>Level3</WarningLevel> | ||||
|       <Optimization>Disabled</Optimization> | ||||
|       <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <SubSystem>Windows</SubSystem> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | ||||
|     <ClCompile> | ||||
|       <WarningLevel>Level3</WarningLevel> | ||||
|       <PrecompiledHeader>Use</PrecompiledHeader> | ||||
|       <Optimization>MaxSpeed</Optimization> | ||||
|       <FunctionLevelLinking>true</FunctionLevelLinking> | ||||
|       <IntrinsicFunctions>true</IntrinsicFunctions> | ||||
|       <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <SubSystem>Windows</SubSystem> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
|       <EnableCOMDATFolding>true</EnableCOMDATFolding> | ||||
|       <OptimizeReferences>true</OptimizeReferences> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemGroup> | ||||
|     <Text Include="ReadMe.txt" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClInclude Include="include\c11log\details\blocking_queue.h" /> | ||||
|     <ClInclude Include="include\c11log\details\factory.h" /> | ||||
|     <ClInclude Include="include\c11log\details\line_logger.h" /> | ||||
|     <ClInclude Include="include\c11log\details\message.h" /> | ||||
|     <ClInclude Include="include\c11log\details\null_mutex.h" /> | ||||
|     <ClInclude Include="include\c11log\details\os.h" /> | ||||
|     <ClInclude Include="include\c11log\details\fast_oss.h" /> | ||||
|     <ClInclude Include="include\c11log\formatters\formatters.h" /> | ||||
|     <ClInclude Include="include\c11log\level.h" /> | ||||
|     <ClInclude Include="include\c11log\logger.h" /> | ||||
|     <ClInclude Include="include\c11log\log_exception.h" /> | ||||
|     <ClInclude Include="include\c11log\sinks\async_sink.h" /> | ||||
|     <ClInclude Include="include\c11log\sinks\base_sink.h" /> | ||||
|     <ClInclude Include="include\c11log\sinks\file_sinks.h" /> | ||||
|     <ClInclude Include="include\c11log\sinks\stdout_sinks.h" /> | ||||
|     <ClInclude Include="stdafx.h" /> | ||||
|     <ClInclude Include="targetver.h" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="src\factory.cpp" /> | ||||
|     <ClCompile Include="src\formatters.cpp" /> | ||||
|     <ClCompile Include="src\line_logger.cpp" /> | ||||
|     <ClCompile Include="src\os.cpp" /> | ||||
|     <ClCompile Include="stdafx.cpp"> | ||||
|       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> | ||||
|       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | ||||
|   <ImportGroup Label="ExtensionTargets"> | ||||
|   </ImportGroup> | ||||
| </Project> | ||||
							
								
								
									
										102
									
								
								c11log.vcxproj.filters
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								c11log.vcxproj.filters
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,102 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
|   <ItemGroup> | ||||
|     <Filter Include="Source Files"> | ||||
|       <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> | ||||
|       <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> | ||||
|     </Filter> | ||||
|     <Filter Include="Header Files"> | ||||
|       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> | ||||
|       <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> | ||||
|     </Filter> | ||||
|     <Filter Include="Resource Files"> | ||||
|       <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> | ||||
|       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> | ||||
|     </Filter> | ||||
|     <Filter Include="Header Files\c11log"> | ||||
|       <UniqueIdentifier>{3f3d8a51-d799-43e2-bd6e-3638f1cd4f54}</UniqueIdentifier> | ||||
|     </Filter> | ||||
|     <Filter Include="Header Files\c11log\sinks"> | ||||
|       <UniqueIdentifier>{d087c87d-8703-46a1-aa23-4509cf253e87}</UniqueIdentifier> | ||||
|     </Filter> | ||||
|     <Filter Include="Header Files\c11log\details"> | ||||
|       <UniqueIdentifier>{5af50a0f-d174-41cd-833c-ead8ba06199a}</UniqueIdentifier> | ||||
|     </Filter> | ||||
|     <Filter Include="Header Files\c11log\formatters"> | ||||
|       <UniqueIdentifier>{64fe6898-a191-4d60-9363-25ecfd196f30}</UniqueIdentifier> | ||||
|     </Filter> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <Text Include="ReadMe.txt" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClInclude Include="stdafx.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="targetver.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\level.h"> | ||||
|       <Filter>Header Files\c11log</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\logger.h"> | ||||
|       <Filter>Header Files\c11log</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\details\line_logger.h"> | ||||
|       <Filter>Header Files\c11log\details</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\formatters\formatters.h"> | ||||
|       <Filter>Header Files\c11log\formatters</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\sinks\base_sink.h"> | ||||
|       <Filter>Header Files\c11log\sinks</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\sinks\stdout_sinks.h"> | ||||
|       <Filter>Header Files\c11log\sinks</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\sinks\file_sinks.h"> | ||||
|       <Filter>Header Files\c11log\sinks</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\log_exception.h"> | ||||
|       <Filter>Header Files\c11log</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\details\os.h"> | ||||
|       <Filter>Header Files\c11log\details</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\details\factory.h"> | ||||
|       <Filter>Header Files\c11log\details</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\details\null_mutex.h"> | ||||
|       <Filter>Header Files\c11log\details</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\details\fast_oss.h"> | ||||
|       <Filter>Header Files\c11log\details</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\details\message.h"> | ||||
|       <Filter>Header Files\c11log\details</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\sinks\async_sink.h"> | ||||
|       <Filter>Header Files\c11log\sinks</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="include\c11log\details\blocking_queue.h"> | ||||
|       <Filter>Header Files\c11log\details</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="stdafx.cpp"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="src\factory.cpp"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="src\formatters.cpp"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="src\os.cpp"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="src\line_logger.cpp"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
							
								
								
									
										64
									
								
								include/c11log/details/blocking_queue.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								include/c11log/details/blocking_queue.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,64 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <cstddef> | ||||
| #include <chrono> | ||||
| #include <memory> | ||||
| #include <queue> | ||||
| #include <mutex> | ||||
| #include <condition_variable> | ||||
| 
 | ||||
| namespace c11log { | ||||
| namespace details { | ||||
| 
 | ||||
| template<typename T> | ||||
| class blocking_queue { | ||||
| public: | ||||
|     explicit blocking_queue(std::size_t max_size) :_max_size(max_size), _q() | ||||
|     {} | ||||
|     blocking_queue(const blocking_queue&) = delete; | ||||
|     blocking_queue& operator=(const blocking_queue&) = delete; | ||||
|     ~blocking_queue() = default; | ||||
| 
 | ||||
|     std::size_t size() | ||||
|     { | ||||
|         std::lock_guard<std::mutex> lock(_mutex); | ||||
|         return _q.size(); | ||||
|     } | ||||
|     bool push(const T& item, const std::chrono::milliseconds& timeout) | ||||
|     { | ||||
|         std::unique_lock<std::mutex> ul(_mutex); | ||||
|         if (_q.size() >= _max_size) { | ||||
|             if (_item_popped_cond.wait_for(ul, timeout) == std::cv_status::timeout || _q.size() >= _max_size) | ||||
|                 return false; | ||||
|         } | ||||
| 
 | ||||
|         _q.push(item); | ||||
|         if (_q.size() <= 1) | ||||
|             _item_pushed_cond.notify_all(); | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
|     bool pop(T& item, const std::chrono::milliseconds& timeout) | ||||
|     { | ||||
|         std::unique_lock<std::mutex> ul(_mutex); | ||||
|         if (_q.empty()) { | ||||
|             if (_item_pushed_cond.wait_for(ul, timeout) == std::cv_status::timeout || _q.empty()) | ||||
|                 return false; | ||||
|         } | ||||
|         item = _q.front(); | ||||
|         _q.pop(); | ||||
|         if (_q.size() >= _max_size - 1) | ||||
|             _item_popped_cond.notify_all(); | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
| private: | ||||
|     std::size_t _max_size; | ||||
|     std::queue<T> _q; | ||||
|     std::mutex _mutex; | ||||
|     std::condition_variable _item_pushed_cond; | ||||
|     std::condition_variable _item_popped_cond; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
| } | ||||
							
								
								
									
										22
									
								
								include/c11log/details/factory.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								include/c11log/details/factory.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <unordered_map> | ||||
| #include <string> | ||||
| #include <memory> | ||||
| #include <mutex> | ||||
| 
 | ||||
| namespace c11log { | ||||
| class logger; | ||||
| namespace details { | ||||
| class factory { | ||||
| public: | ||||
|     typedef std::shared_ptr<c11log::logger>  logger_ptr; | ||||
|     typedef std::unordered_map<std::string, logger_ptr> logger_map; | ||||
|     logger_ptr get_logger(const std::string &name); | ||||
|     static c11log::details::factory& instance(); | ||||
| private: | ||||
|     logger_map _loggers; | ||||
|     std::mutex _loggers_mutex; | ||||
| }; | ||||
| } | ||||
| } | ||||
							
								
								
									
										76
									
								
								include/c11log/details/fast_oss.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								include/c11log/details/fast_oss.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include<streambuf> | ||||
| #include<string> | ||||
| namespace c11log { | ||||
| namespace details { | ||||
| 
 | ||||
| class str_devicebuf:public std::streambuf { | ||||
| public: | ||||
|     str_devicebuf() | ||||
|     { | ||||
|         _str.reserve(128); | ||||
|     } | ||||
| 
 | ||||
|     const std::string& str_ref() | ||||
|     { | ||||
|         return _str; | ||||
|     } | ||||
| 
 | ||||
|     void clear() | ||||
|     { | ||||
|         _str.clear(); | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
|     virtual int sync() override | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     virtual std::streamsize xsputn(const char_type* s, std::streamsize count) override | ||||
|     { | ||||
|         _str.append(s, static_cast<unsigned int>(count)); | ||||
|         return count; | ||||
|     } | ||||
| 
 | ||||
|     virtual int_type overflow(int_type ch) override | ||||
|     { | ||||
|         if (ch != traits_type::eof()) | ||||
|             _str.append((char*)&ch, 1); | ||||
|         return 1; | ||||
|     } | ||||
| private: | ||||
|     std::string _str; | ||||
| }; | ||||
| 
 | ||||
| class fast_oss:public std::ostream { | ||||
| public: | ||||
|     fast_oss():std::ostream(&_dev) | ||||
|     {} | ||||
|     ~fast_oss() | ||||
|     {} | ||||
| 
 | ||||
|     const std::string& str_ref() const | ||||
|     { | ||||
|         auto mydevice = static_cast<str_devicebuf*>(rdbuf()); | ||||
|         return mydevice->str_ref(); | ||||
|     } | ||||
| 
 | ||||
|     const std::string str() const | ||||
|     { | ||||
|         auto mydevice = static_cast<str_devicebuf*>(rdbuf()); | ||||
|         return mydevice->str_ref(); | ||||
|     } | ||||
| 
 | ||||
|     void clear() | ||||
|     { | ||||
|         auto mydevice = static_cast<str_devicebuf*>(rdbuf()); | ||||
|         mydevice->clear(); | ||||
|     } | ||||
| private: | ||||
|     str_devicebuf _dev; | ||||
| 
 | ||||
| }; | ||||
| } | ||||
| } | ||||
							
								
								
									
										30
									
								
								include/c11log/details/line_logger.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								include/c11log/details/line_logger.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "../level.h" | ||||
| #include "fast_oss.h" | ||||
| 
 | ||||
| namespace c11log { | ||||
| class logger; | ||||
| namespace details { | ||||
| 
 | ||||
| class line_logger { | ||||
| public: | ||||
|     c11log::details::line_logger::line_logger(logger* callback_logger, level::level_enum msg_level); | ||||
|     c11log::details::line_logger::line_logger(logger* callback_logger):_callback_logger(nullptr) {}; | ||||
|     ~line_logger(); | ||||
| 
 | ||||
|     template<typename T> | ||||
|     line_logger& operator<<(const T& msg) | ||||
|     { | ||||
|         if (_callback_logger) | ||||
|             _oss << msg; | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     logger* _callback_logger; | ||||
|     details::fast_oss _oss; | ||||
| 
 | ||||
| }; | ||||
| } //Namespace details
 | ||||
| } // Namespace c11log
 | ||||
							
								
								
									
										31
									
								
								include/c11log/details/message.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								include/c11log/details/message.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <chrono> | ||||
| #include <string> | ||||
| #include "../level.h" | ||||
| 
 | ||||
| namespace c11log { | ||||
| namespace details { | ||||
| struct message { | ||||
|     message(const std::string& logger_name, | ||||
|             level::level_enum log_level, | ||||
|             const std::chrono::system_clock::time_point time_p | ||||
|             , const std::string& msg) : | ||||
|         logger_name(logger_name), | ||||
|         log_level(log_level), | ||||
|         time_p(time_p), | ||||
|         msg(msg) {} | ||||
| 
 | ||||
|     ~message() = default; | ||||
|     message(const message& other) = default; | ||||
|     message& operator=(const message& rhs) = default; | ||||
| 
 | ||||
| 
 | ||||
|     std::string logger_name; | ||||
|     level::level_enum log_level; | ||||
|     std::chrono::system_clock::time_point time_p; | ||||
|     std::string msg; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
| } | ||||
							
								
								
									
										17
									
								
								include/c11log/details/null_mutex.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								include/c11log/details/null_mutex.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| namespace c11log{ | ||||
| 	namespace details{ | ||||
| 		struct null_mutex | ||||
| 		{ | ||||
| 			void lock() | ||||
| 			{} | ||||
| 			void unlock() | ||||
| 			{} | ||||
| 			bool try_lock() | ||||
| 			{ | ||||
| 				return true; | ||||
| 			} | ||||
| 		}; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										17
									
								
								include/c11log/details/os.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								include/c11log/details/os.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| #pragma once | ||||
| #include<string> | ||||
| #include<cstdio> | ||||
| #include<ctime> | ||||
| 
 | ||||
| namespace c11log | ||||
| { | ||||
| 	namespace details | ||||
| 	{ | ||||
| 		namespace os | ||||
| 		{			 | ||||
| 			std::tm localtime(const std::time_t &time_t);			 | ||||
| 			std::tm localtime(); | ||||
| 			 | ||||
| 		}		 | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										38
									
								
								include/c11log/formatters/formatters.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								include/c11log/formatters/formatters.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include<string> | ||||
| #include<chrono> | ||||
| #include<functional> | ||||
| #include <sstream> | ||||
| 
 | ||||
| #include "../level.h" | ||||
| #include "../details/os.h" | ||||
| 
 | ||||
| namespace c11log { | ||||
| namespace formatters { | ||||
| typedef std::chrono::system_clock::time_point timepoint; | ||||
| typedef std::function<std::string(const std::string& logger_name, const std::string&, level::level_enum, const timepoint&)> format_fn; | ||||
| void format_time(const timepoint& tp, std::ostream &dest); | ||||
| void format_time(std::ostream &dest); | ||||
| std::string to_hex(const unsigned char* buf, std::size_t size); | ||||
| 
 | ||||
| class formatter { | ||||
| public: | ||||
|     formatter() {} | ||||
|     virtual ~formatter() {} | ||||
|     virtual void format_header(const std::string& logger_name, level::level_enum level, const timepoint& tp, std::ostream& dest) = 0; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| class default_formatter: public formatter { | ||||
| public: | ||||
|     // Format: [2013-12-29 01:04:42.900] [logger_name:Info] Message body
 | ||||
|     void format_header(const std::string& logger_name, level::level_enum level, const timepoint& tp, std::ostream& dest) override | ||||
|     { | ||||
|         format_time(tp, dest); | ||||
|         dest << " [" <<  logger_name << ":" << c11log::level::to_str(level) << "] "; | ||||
|     } | ||||
| 
 | ||||
| }; | ||||
| } //namespace formatter
 | ||||
| } //namespace c11log
 | ||||
							
								
								
									
										24
									
								
								include/c11log/level.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								include/c11log/level.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| namespace c11log | ||||
| { | ||||
| 	namespace level | ||||
| 	{ | ||||
| 		typedef enum | ||||
| 		{ | ||||
| 			DEBUG, | ||||
| 			INFO, | ||||
| 			WARNING, | ||||
| 			ERROR, | ||||
| 			FATAL, | ||||
| 			NONE = 99 | ||||
| 		} level_enum; | ||||
| 		const char* to_str(level_enum l);				 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static const char* level_names[] { "Debug", "Info", "Warning", "Error", "Fatal" }; | ||||
| inline const char* c11log::level::to_str(c11log::level::level_enum l) | ||||
| { | ||||
| 	return level_names[l]; | ||||
| } | ||||
							
								
								
									
										46
									
								
								include/c11log/log_exception.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								include/c11log/log_exception.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | ||||
| #pragma once | ||||
| #include <sstream> | ||||
| #include <iostream> | ||||
| 
 | ||||
| namespace c11log | ||||
| { | ||||
| 	class log_exception :public std::exception | ||||
| 	{ | ||||
| 	public: | ||||
| 		log_exception() : _oss(), _msg() | ||||
| 		{} | ||||
| 
 | ||||
| 		virtual ~log_exception() | ||||
| 		{} | ||||
| 
 | ||||
| 		explicit log_exception(const std::string& msg) :_oss(msg, std::ostringstream::ate), _msg(msg) | ||||
| 		{} | ||||
| 
 | ||||
| 		log_exception(const log_exception &other) :_oss(other._oss.str()), _msg(other._msg) | ||||
| 		{} | ||||
| 
 | ||||
| 		log_exception& operator=(const log_exception& other) | ||||
| 		{ | ||||
| 			_oss.str(other._oss.str()); | ||||
| 			_msg = other._msg; | ||||
| 			return *this; | ||||
| 		} | ||||
| 
 | ||||
| 		virtual const char* what() const throw () override | ||||
| 		{ | ||||
| 			return _msg.c_str(); | ||||
| 		} | ||||
| 
 | ||||
| 		template<typename T> | ||||
| 		log_exception& operator<<(const T& what) | ||||
| 		{ | ||||
| 			_oss << what; | ||||
| 			_msg = _oss.str(); | ||||
| 			return *this; | ||||
| 		} | ||||
| 
 | ||||
| 	private: | ||||
| 		std::ostringstream _oss; | ||||
| 		std::string _msg; | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										161
									
								
								include/c11log/logger.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								include/c11log/logger.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,161 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include<vector> | ||||
| #include<memory> | ||||
| #include<mutex> | ||||
| #include<atomic> | ||||
| #include <algorithm> | ||||
| 
 | ||||
| #include "level.h" | ||||
| #include "sinks/base_sink.h" | ||||
| #include "details/line_logger.h" | ||||
| #include "details/factory.h" | ||||
| 
 | ||||
| 
 | ||||
| namespace c11log { | ||||
| 
 | ||||
| class logger { | ||||
| public: | ||||
| 
 | ||||
|     typedef std::shared_ptr<sinks::base_sink>  sink_ptr_t; | ||||
|     typedef std::vector<sink_ptr_t> sinks_vector_t; | ||||
| 
 | ||||
|     explicit logger(const std::string& name) : _logger_name(name), | ||||
|         _formatter(std::make_unique<formatters::default_formatter>()) | ||||
|     { | ||||
|         _atomic_level.store(level::INFO); | ||||
|     } | ||||
| 
 | ||||
|     ~logger() | ||||
|     { | ||||
|     }; | ||||
| 
 | ||||
|     logger(const logger&) = delete; | ||||
|     logger& operator=(const logger&) = delete; | ||||
| 
 | ||||
|     void set_name(const std::string& name); | ||||
|     const std::string& get_name(); | ||||
|     void add_sink(sink_ptr_t sink_ptr); | ||||
|     void remove_sink(sink_ptr_t sink_ptr); | ||||
|     void set_formatter(std::unique_ptr<formatters::formatter> formatter); | ||||
|     void set_level(c11log::level::level_enum level); | ||||
|     c11log::level::level_enum get_level() const; | ||||
|     bool should_log(c11log::level::level_enum level) const; | ||||
| 
 | ||||
|     details::line_logger log(level::level_enum level); | ||||
|     details::line_logger debug(); | ||||
|     details::line_logger info(); | ||||
|     details::line_logger warn(); | ||||
|     details::line_logger error(); | ||||
|     details::line_logger fatal(); | ||||
| 
 | ||||
| private: | ||||
|     friend details::line_logger; | ||||
| 
 | ||||
| 
 | ||||
|     std::string _logger_name = ""; | ||||
|     std::unique_ptr<c11log::formatters::formatter> _formatter; | ||||
|     sinks_vector_t _sinks; | ||||
|     std::mutex _mutex; | ||||
|     std::atomic_int _atomic_level; | ||||
| 
 | ||||
|     void _log_it(const std::string& msg); | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| logger& get_logger(const std::string& name); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| Logger inline impl | ||||
| */ | ||||
| 
 | ||||
| inline c11log::details::line_logger c11log::logger::log(c11log::level::level_enum msg_level) | ||||
| { | ||||
| 
 | ||||
|     if (msg_level >= _atomic_level.load()) { | ||||
|         std::lock_guard<std::mutex> lock(_mutex); | ||||
|         return details::line_logger(this, msg_level); | ||||
|     } else { | ||||
|         return details::line_logger(nullptr); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| inline c11log::details::line_logger c11log::logger::debug() | ||||
| { | ||||
|     return log(c11log::level::DEBUG); | ||||
| } | ||||
| inline c11log::details::line_logger c11log::logger::info() | ||||
| { | ||||
|     return log(c11log::level::INFO); | ||||
| } | ||||
| inline c11log::details::line_logger c11log::logger::warn() | ||||
| { | ||||
|     return log(c11log::level::WARNING); | ||||
| } | ||||
| inline c11log::details::line_logger c11log::logger::error() | ||||
| { | ||||
|     return log(level::ERROR); | ||||
| } | ||||
| inline c11log::details::line_logger c11log::logger::fatal() | ||||
| { | ||||
|     return log(c11log::level::FATAL); | ||||
| } | ||||
| 
 | ||||
| inline void c11log::logger::set_name(const std::string& name) | ||||
| { | ||||
|     std::lock_guard<std::mutex> lock(_mutex); | ||||
|     _logger_name = name; | ||||
| } | ||||
| 
 | ||||
| inline const std::string& c11log::logger::get_name() | ||||
| { | ||||
|     std::lock_guard<std::mutex> lock(_mutex); | ||||
|     return _logger_name; | ||||
| } | ||||
| 
 | ||||
| inline void c11log::logger::add_sink(sink_ptr_t sink_ptr) | ||||
| { | ||||
|     std::lock_guard<std::mutex> lock(_mutex); | ||||
|     _sinks.push_back(sink_ptr); | ||||
| } | ||||
| 
 | ||||
| inline void c11log::logger::remove_sink(sink_ptr_t sink_ptr) | ||||
| { | ||||
|     std::lock_guard<std::mutex> lock(_mutex); | ||||
|     _sinks.erase(std::remove(_sinks.begin(), _sinks.end(), sink_ptr), _sinks.end()); | ||||
| } | ||||
| 
 | ||||
| inline void c11log::logger::set_formatter(std::unique_ptr<formatters::formatter> formatter) | ||||
| { | ||||
|     std::lock_guard<std::mutex> lock(_mutex); | ||||
|     _formatter = std::move(formatter); | ||||
| } | ||||
| 
 | ||||
| inline void c11log::logger::set_level(c11log::level::level_enum level) | ||||
| { | ||||
|     _atomic_level.store(level); | ||||
| } | ||||
| 
 | ||||
| inline c11log::level::level_enum c11log::logger::get_level() const | ||||
| { | ||||
|     return static_cast<c11log::level::level_enum>(_atomic_level.load()); | ||||
| } | ||||
| 
 | ||||
| inline bool c11log::logger::should_log(c11log::level::level_enum level) const | ||||
| { | ||||
|     return level >= _atomic_level.load(); | ||||
| } | ||||
| inline void c11log::logger::_log_it(const std::string& msg) | ||||
| { | ||||
|     level::level_enum level = static_cast<level::level_enum>(_atomic_level.load()); | ||||
|     std::lock_guard<std::mutex> lock(_mutex); | ||||
|     for (auto &sink : _sinks) | ||||
|         sink->log(msg, level); | ||||
| } | ||||
| 
 | ||||
| inline c11log::logger& c11log::get_logger(const std::string& name) | ||||
| { | ||||
|     return *(c11log::details::factory::instance().get_logger(name)); | ||||
| } | ||||
							
								
								
									
										55
									
								
								include/c11log/sinks/async_sink.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								include/c11log/sinks/async_sink.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| #pragma once | ||||
| #include <mutex> | ||||
| #include <queue> | ||||
| #include <thread> | ||||
| #include <iostream> | ||||
| 
 | ||||
| #include "../logger.h" | ||||
| #include "base_sink.h" | ||||
| namespace c11log { | ||||
| namespace sinks { | ||||
| class async_sink : base_sink { | ||||
|     enum class fullq_policy { | ||||
|         BLOCK=0, | ||||
|         DROP_MSG | ||||
|     }; | ||||
| public: | ||||
|     async_sink(std::size_t max_queue_size, fullq_policy q_policy) :_fullq_policy(q_policy), _back_thread(&_thread_loop) | ||||
|     { | ||||
| 
 | ||||
|     } | ||||
| protected: | ||||
|     void _sink_it(const std::string& msg) override | ||||
|     { | ||||
|         _msgs_mutex.unlock(); | ||||
|         _msgs.push(msg); | ||||
|     } | ||||
|     void _thread_loop() | ||||
|     { | ||||
|         while (_active) { | ||||
|             _msgs_mutex.lock(); | ||||
|             std::string &msg = _msgs.front(); | ||||
|             _msgs.pop(); | ||||
|             _msgs_mutex.unlock(); | ||||
|             std::cout << "Popped: " << msg << std::endl; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     c11log::logger::sinks_vector_t _sinks; | ||||
|     fullq_policy _fullq_policy; | ||||
|     std::queue<std::string> _msgs; | ||||
|     std::thread _back_thread; | ||||
|     bool _active = true; | ||||
|     std::mutex _msgs_mutex; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| }; | ||||
| } | ||||
| } | ||||
| 
 | ||||
| void c11log::sinks::async_sink::_sink_it(const std::string& msg) | ||||
| { | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										50
									
								
								include/c11log/sinks/base_sink.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								include/c11log/sinks/base_sink.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | ||||
| #pragma once | ||||
| #include<string> | ||||
| #include<memory> | ||||
| #include<mutex> | ||||
| 
 | ||||
| #include "../formatters/formatters.h" | ||||
| #include "../level.h" | ||||
| 
 | ||||
| namespace c11log { | ||||
| namespace sinks { | ||||
| class base_sink { | ||||
| public: | ||||
|     base_sink() | ||||
|     {} | ||||
|     base_sink(level::level_enum l):_level(l) | ||||
|     {}; | ||||
|     virtual ~base_sink() | ||||
|     {}; | ||||
| 
 | ||||
|     base_sink(const base_sink&) = delete; | ||||
|     base_sink& operator=(const base_sink&) = delete; | ||||
| 
 | ||||
|     void log(const std::string &msg, level::level_enum level) | ||||
|     { | ||||
|         if (level >= _level) { | ||||
|             std::lock_guard<std::mutex> lock(_mutex); | ||||
|             if (level >= _level) | ||||
|                 _sink_it(msg); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     void set_level(level::level_enum level) | ||||
|     { | ||||
|         std::lock_guard<std::mutex> lock(_mutex); | ||||
|         _level = level; | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
|     virtual void _sink_it(const std::string& msg) = 0; | ||||
|     level::level_enum _level = level::INFO; | ||||
|     std::mutex _mutex; | ||||
| }; | ||||
| 
 | ||||
| class null_sink:public base_sink { | ||||
| protected: | ||||
|     void _sink_it(const std::string& msg) override | ||||
|     {} | ||||
| }; | ||||
| } | ||||
| } | ||||
							
								
								
									
										174
									
								
								include/c11log/sinks/file_sinks.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								include/c11log/sinks/file_sinks.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,174 @@ | ||||
| #pragma once | ||||
| #include <fstream> | ||||
| #include  <iomanip> | ||||
| 
 | ||||
| #include "../logger.h" | ||||
| #include "../log_exception.h" | ||||
| #include "../details/os.h" | ||||
| 
 | ||||
| #include "base_sink.h" | ||||
| 
 | ||||
| namespace c11log { | ||||
| namespace sinks { | ||||
| /*
 | ||||
| * Trivial file sink with single file as target | ||||
| */ | ||||
| class simple_file_sink:base_sink { | ||||
| public: | ||||
|     simple_file_sink(const std::string &filename, const std::string& extension = "txt") | ||||
|     { | ||||
|         std::ostringstream oss; | ||||
|         oss << filename << "." << extension; | ||||
|         _ofstream.open(oss.str(), std::ofstream::app); | ||||
|     } | ||||
| protected: | ||||
|     void _sink_it(const std::string& msg) override | ||||
|     { | ||||
|         _ofstream << msg; | ||||
|         _ofstream.flush(); | ||||
|     } | ||||
| 
 | ||||
|     std::ofstream _ofstream; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Rotating file sinks. Close and open new file at some point | ||||
|  */ | ||||
| namespace details { | ||||
| class rotating_file_sink_base:public base_sink { | ||||
| public: | ||||
|     rotating_file_sink_base() | ||||
|     {} | ||||
|     virtual ~rotating_file_sink_base() | ||||
|     {} | ||||
| protected: | ||||
|     virtual void _sink_it(const std::string& msg) override | ||||
|     { | ||||
|         if (_should_rotate()) | ||||
|             _rotate(); | ||||
|         _ofstream << msg; | ||||
|         _ofstream.flush(); | ||||
|     } | ||||
|     virtual bool _should_rotate() const = 0; | ||||
|     virtual void _rotate() = 0; | ||||
|     std::ofstream _ofstream; | ||||
| }; | ||||
| } | ||||
| class rotating_file_sink:public details::rotating_file_sink_base { | ||||
| public: | ||||
|     rotating_file_sink(const std::string &base_filename, const std::string &extension, size_t max_size, size_t max_files): | ||||
|         _base_filename(base_filename), | ||||
|         _extension(extension), | ||||
|         _max_size(max_size), | ||||
|         _max_files(max_files), | ||||
|         _current_size(0), | ||||
|         _index(0) | ||||
|     { | ||||
|         _ofstream.open(_calc_filename(_base_filename, 0, _extension)); | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
|     virtual void _sink_it(const std::string& msg) override | ||||
|     { | ||||
|         _current_size += msg.length(); | ||||
|         rotating_file_sink_base::_sink_it(msg); | ||||
|     } | ||||
| 
 | ||||
|     bool _should_rotate() const override | ||||
|     { | ||||
|         return _current_size >= _max_size; | ||||
|     } | ||||
| 
 | ||||
|     // Rotate old files:
 | ||||
|     // log.n-1.txt -> log.n.txt
 | ||||
|     // log n-2.txt -> log.n-1.txt
 | ||||
|     // ...
 | ||||
|     // log.txt -> log.1.txt
 | ||||
|     void _rotate() override | ||||
|     { | ||||
|         _ofstream.close(); | ||||
|         _current_size = 0; | ||||
|         //Remove oldest file
 | ||||
|         for (auto i = _max_files; i > 0; --i) { | ||||
|             auto src = _calc_filename(_base_filename, i - 1, _extension); | ||||
|             auto target = _calc_filename(_base_filename, i, _extension); | ||||
|             if (i == _max_files) | ||||
|                 std::remove(target.c_str()); | ||||
|             std::rename(src.c_str(), target.c_str()); | ||||
|         } | ||||
| 
 | ||||
|         _ofstream.open(_calc_filename(_base_filename, 0, _extension)); | ||||
|     } | ||||
| private: | ||||
|     static std::string _calc_filename(const std::string& filename, std::size_t index, const std::string& extension) | ||||
|     { | ||||
|         std::ostringstream oss; | ||||
|         if (index) | ||||
|             oss << filename << "." << index << "." << extension; | ||||
|         else | ||||
|             oss << filename << "." << extension; | ||||
|         return oss.str(); | ||||
|     } | ||||
|     std::string _base_filename; | ||||
|     std::string _extension; | ||||
|     std::size_t _max_size; | ||||
|     std::size_t _max_files; | ||||
|     std::size_t _current_size; | ||||
|     std::size_t _index; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * File sink that closes the log file at midnight and opens new one | ||||
|  */ | ||||
| class midnight_file_sink:public details::rotating_file_sink_base { | ||||
| public: | ||||
|     midnight_file_sink(const std::string& base_filename, const std::string& extension): | ||||
|         _base_filename(base_filename), | ||||
|         _extension(extension), | ||||
|         _midnight_tp { _calc_midnight_tp() } | ||||
| 
 | ||||
|     { | ||||
|         _ofstream.open(_calc_filename(_base_filename, _extension)); | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
|     bool _should_rotate() const override | ||||
|     { | ||||
|         return std::chrono::system_clock::now() >= _midnight_tp; | ||||
|     } | ||||
|     void _rotate() override | ||||
|     { | ||||
|         _midnight_tp = _calc_midnight_tp(); | ||||
|         _ofstream.close(); | ||||
|         _ofstream.open(_calc_filename(_base_filename, _extension)); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     // Return next midnight's time_point
 | ||||
|     static std::chrono::system_clock::time_point _calc_midnight_tp() | ||||
|     { | ||||
|         using namespace std::chrono; | ||||
|         auto now = system_clock::now(); | ||||
|         time_t tnow = std::chrono::system_clock::to_time_t(now); | ||||
|         tm date = c11log::details::os::localtime(tnow); | ||||
|         date.tm_hour = date.tm_min = date.tm_sec = 0; | ||||
|         auto midnight = std::chrono::system_clock::from_time_t(std::mktime(&date)); | ||||
|         return system_clock::time_point(midnight + hours(24)); | ||||
|     } | ||||
| 
 | ||||
|     static std::string _calc_filename(const std::string& basename, const std::string& extension) | ||||
|     { | ||||
|         std::ostringstream oss; | ||||
|         std::tm now_tm = c11log::details::os::localtime(); | ||||
|         oss << basename << std::put_time(&now_tm, ".%Y-%m-%d.") << extension; | ||||
|         return oss.str(); | ||||
|     } | ||||
|     std::string _base_filename; | ||||
|     std::string _extension; | ||||
|     std::chrono::system_clock::time_point _midnight_tp; | ||||
| }; | ||||
| } | ||||
| } | ||||
							
								
								
									
										41
									
								
								include/c11log/sinks/stdout_sinks.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								include/c11log/sinks/stdout_sinks.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include "base_sink.h" | ||||
| 
 | ||||
| namespace c11log | ||||
| { | ||||
| 	namespace sinks | ||||
| 	{ | ||||
| 		class ostream_sink:public base_sink | ||||
| 		{ | ||||
| 		public: | ||||
| 			ostream_sink(std::ostream& os):_ostream(os) | ||||
| 			{} | ||||
| 
 | ||||
| 			virtual ~ostream_sink() | ||||
| 			{} | ||||
| 
 | ||||
| 		protected: | ||||
| 			virtual void _sink_it(const std::string& msg) | ||||
| 			{ | ||||
| 				_ostream << msg; | ||||
| 			} | ||||
| 			std::ostream& _ostream; | ||||
| 
 | ||||
| 		}; | ||||
| 
 | ||||
| 		class stdout_sink:public ostream_sink | ||||
| 		{ | ||||
| 		public: | ||||
| 			stdout_sink():ostream_sink(std::cout) | ||||
| 			{} | ||||
| 		}; | ||||
| 
 | ||||
| 		class stderr_sink:public ostream_sink | ||||
| 		{ | ||||
| 		public: | ||||
| 			stderr_sink():ostream_sink(std::cerr) | ||||
| 			{} | ||||
| 		}; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										23
									
								
								src/factory.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/factory.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| #include "stdafx.h" | ||||
| #include "c11log/details/factory.h" | ||||
| #include "c11log/logger.h" | ||||
| 
 | ||||
| c11log::details::factory::logger_ptr c11log::details::factory::get_logger(const std::string &name) | ||||
| { | ||||
| 	std::lock_guard<std::mutex> lock(_loggers_mutex); | ||||
| 	auto found = _loggers.find(name); | ||||
| 	if (found == _loggers.end()) { | ||||
| 		auto new_logger_ptr = std::make_shared<c11log::logger>(name); | ||||
| 		_loggers.insert(std::make_pair(name, new_logger_ptr)); | ||||
| 		return new_logger_ptr; | ||||
| 	} | ||||
| 	else {		 | ||||
| 		return found->second; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| c11log::details::factory & c11log::details::factory::instance() | ||||
| { | ||||
| 	static c11log::details::factory instance; | ||||
| 	return instance; | ||||
| } | ||||
							
								
								
									
										36
									
								
								src/formatters.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/formatters.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| #include "stdafx.h" | ||||
| #include "c11log/formatters/formatters.h" | ||||
| #include "c11log/level.h" | ||||
| 
 | ||||
| void c11log::formatters::format_time(const c11log::formatters::timepoint& tp, std::ostream &dest) | ||||
| { | ||||
|     std::tm tm = details::os::localtime(std::chrono::system_clock::to_time_t(tp)); | ||||
|     //get ms
 | ||||
|     auto duration = tp.time_since_epoch(); | ||||
|     int millis = static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000); | ||||
|     //std::put_time(&tm, "[ %Y-%m-%d %H:%M:%S ]") - seems too slow
 | ||||
|     char buf[64]; | ||||
|     sprintf(buf, "[%d-%02d-%02d %02d:%02d:%02d.%03d]", | ||||
|             tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | ||||
|             tm.tm_hour, tm.tm_min, tm.tm_sec, millis); | ||||
|     dest << buf; | ||||
| } | ||||
| 
 | ||||
| void c11log::formatters::format_time(std::ostream& dest) | ||||
| { | ||||
|     return format_time(std::chrono::system_clock::now(), dest); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static const char _hex_chars[17] = "0123456789ABCDEF"; | ||||
| 
 | ||||
| std::string c11log::formatters::to_hex(const unsigned char* buf, std::size_t size) | ||||
| { | ||||
|     std::ostringstream oss; | ||||
| 
 | ||||
|     for (std::size_t i = 0; i < size; i++) { | ||||
|         oss << _hex_chars[buf[i] >> 4]; | ||||
|         oss << _hex_chars[buf[i] & 0x0F]; | ||||
|     } | ||||
|     return oss.str(); | ||||
| } | ||||
							
								
								
									
										21
									
								
								src/line_logger.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/line_logger.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| #include "stdafx.h" | ||||
| #include "c11log/logger.h" | ||||
| 
 | ||||
| c11log::details::line_logger::line_logger(logger* callback_logger, level::level_enum msg_level) : | ||||
|     _callback_logger(callback_logger) | ||||
| { | ||||
|     if (callback_logger) { | ||||
|         callback_logger->_formatter->format_header(callback_logger->_logger_name, | ||||
|                 msg_level, | ||||
|                 c11log::formatters::timepoint::clock::now(), | ||||
|                 _oss); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| c11log::details::line_logger::~line_logger() | ||||
| { | ||||
|     if (_callback_logger) { | ||||
|         _oss << '\n'; | ||||
|         _callback_logger->_log_it(_oss.str_ref()); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										51
									
								
								src/logger.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/logger.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| #include "stdafx.h" | ||||
| #include <algorithm> | ||||
| 
 | ||||
| #include "c11log/logger.h" | ||||
| 
 | ||||
| void c11log::logger::set_name(const std::string& name) | ||||
| { | ||||
|     std::lock_guard<std::mutex> lock(_mutex); | ||||
|     _logger_name = name; | ||||
| } | ||||
| 
 | ||||
| const std::string& c11log::logger::get_name() | ||||
| { | ||||
|     std::lock_guard<std::mutex> lock(_mutex); | ||||
|     return _logger_name; | ||||
| } | ||||
| 
 | ||||
| void c11log::logger::add_sink(sink_ptr_t sink_ptr) | ||||
| { | ||||
|     std::lock_guard<std::mutex> lock(_mutex); | ||||
|     _sinks.push_back(sink_ptr); | ||||
| } | ||||
| 
 | ||||
| void c11log::logger::remove_sink(sink_ptr_t sink_ptr) | ||||
| { | ||||
|     std::lock_guard<std::mutex> lock(_mutex); | ||||
|     _sinks.erase(std::remove(_sinks.begin(), _sinks.end(), sink_ptr), _sinks.end()); | ||||
| } | ||||
| 
 | ||||
| void c11log::logger::set_formatter(std::unique_ptr<formatters::formatter> formatter) | ||||
| { | ||||
|     std::lock_guard<std::mutex> lock(_mutex); | ||||
|     _formatter = std::move(formatter); | ||||
| } | ||||
| 
 | ||||
| void c11log::logger::set_level(c11log::level::level_enum level) | ||||
| { | ||||
|     std::lock_guard<std::mutex> lock(_mutex); | ||||
|     _level = level; | ||||
| } | ||||
| 
 | ||||
| bool c11log::logger::should_log(c11log::level::level_enum level) | ||||
| { | ||||
|     std::lock_guard<std::mutex> lock(_mutex); | ||||
|     return level >= _level; | ||||
| } | ||||
| 
 | ||||
| c11log::logger& c11log::get_logger(const std::string& name) | ||||
| { | ||||
|     return *(c11log::details::factory::instance().get_logger(name)); | ||||
| } | ||||
							
								
								
									
										24
									
								
								src/os.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/os.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| #include "stdafx.h" | ||||
| 
 | ||||
| #include "c11log/details/os.h" | ||||
| 
 | ||||
| namespace c11log { | ||||
| namespace details { | ||||
| namespace os { | ||||
| std::tm localtime(const std::time_t &time_t) | ||||
| { | ||||
| #ifdef _MSC_VER | ||||
|     std::tm tm; | ||||
|     localtime_s(&tm, &time_t); | ||||
|     return tm; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| std::tm localtime() | ||||
| { | ||||
|     std::time_t now_t = time(0); | ||||
|     return localtime(now_t); | ||||
| } | ||||
| } | ||||
| } | ||||
| } | ||||
							
								
								
									
										8
									
								
								stdafx.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								stdafx.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| // stdafx.cpp : source file that includes just the standard includes
 | ||||
| // c11log.pch will be the pre-compiled header
 | ||||
| // stdafx.obj will contain the pre-compiled type information
 | ||||
| 
 | ||||
| #include "stdafx.h" | ||||
| 
 | ||||
| // TODO: reference any additional headers you need in STDAFX.H
 | ||||
| // and not in this file
 | ||||
							
								
								
									
										16
									
								
								stdafx.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								stdafx.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| // stdafx.h : include file for standard system include files,
 | ||||
| // or project specific include files that are used frequently, but
 | ||||
| // are changed infrequently
 | ||||
| //
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "targetver.h" | ||||
| 
 | ||||
| #define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
 | ||||
| 
 | ||||
| #include <string> | ||||
| #include <chrono> | ||||
| #include <ctime> | ||||
| #include <memory> | ||||
| #include <iostream> | ||||
							
								
								
									
										8
									
								
								targetver.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								targetver.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| // Including SDKDDKVer.h defines the highest available Windows platform.
 | ||||
| 
 | ||||
| // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
 | ||||
| // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
 | ||||
| 
 | ||||
| #include <SDKDDKVer.h> | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user