mirror of
https://github.com/gabime/spdlog.git
synced 2024-11-15 16:35:45 +08:00
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…
Reference in New Issue
Block a user