Commit 451aadec authored by Gabi Melman's avatar Gabi Melman Committed by GitHub

Merge pull request #236 from gabime/no-streams

No streams
parents 34bb86b2 7ddfb2b8
#~/bin/bash
#execute each bench 3 times and print the timing
exec 2>&1
#execute and time given exe 3 times
bench_exe ()
{
echo "**************** $1 ****************"
for i in {1..3}; do
time ./$1 $2;
rm -f logs/*
sleep 3
done;
}
#execute given async tests 3 times (timing is already builtin)
bench_async ()
{
echo "**************** $1 ****************"
for i in {1..3}; do
./$1 $2;
echo
rm -f logs/*
sleep 3
done;
}
echo "----------------------------------------------------------"
echo "Single threaded benchmarks.. (1 thread, 1,000,000 lines)"
echo "----------------------------------------------------------"
for exe in boost-bench glog-bench easylogging-bench zf_log-bench spdlog-bench;
do
bench_exe $exe 1
done;
echo "----------------------------------------------------------"
echo "Multi threaded benchmarks.. (10 threads, 1,000,000 lines)"
echo "----------------------------------------------------------"
for exe in boost-bench-mt glog-bench-mt easylogging-bench-mt zf_log-bench-mt spdlog-bench-mt;
do
bench_exe $exe 10
done;
echo "----------------------------------------------------------"
echo "Multi threaded benchmarks.. (100 threads, 1,000,000 lines)"
echo "----------------------------------------------------------"
for exe in boost-bench-mt glog-bench-mt easylogging-bench-mt zf_log-bench-mt spdlog-bench-mt;
do
bench_exe $exe 100
done;
echo "---------------------------------------------------------------"
echo "Async, single threaded benchmark.. (1 thread, 1,000,000 lines)"
echo "---------------------------------------------------------------"
for exe in spdlog-async g2log-async
do
bench_async $exe 1
done;
echo "---------------------------------------------------------------"
echo "Async, multi threaded benchmark.. (10 threads, 1,000,000 lines)"
echo "---------------------------------------------------------------"
for exe in spdlog-async g2log-async
do
bench_async $exe 10
done;
echo "---------------------------------------------------------------"
echo "Async, multi threaded benchmark.. (100 threads, 1,000,000 lines)"
echo "---------------------------------------------------------------"
for exe in spdlog-async g2log-async
do
bench_async $exe 100
done;
...@@ -22,11 +22,11 @@ int main(int, char*[]) ...@@ -22,11 +22,11 @@ int main(int, char*[])
// Multithreaded color console // Multithreaded color console
auto console = spd::stdout_logger_mt("console", true); auto console = spd::stdout_logger_mt("console", true);
console->info("Welcome to spdlog!"); console->info("Welcome to spdlog!");
console->info("An info message example {}..", 1); console->error("An info message example {}..", 1);
// Formatting examples // Formatting examples
console->info("Easy padding in numbers like {:08d}", 12); console->warn("Easy padding in numbers like {:08d}", 12);
console->info("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42); console->critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
console->info("Support for floats {:03.2f}", 1.23456); console->info("Support for floats {:03.2f}", 1.23456);
console->info("Positional args are {1} {0}..", "too", "supported"); console->info("Positional args are {1} {0}..", "too", "supported");
...@@ -106,4 +106,3 @@ void syslog_example() ...@@ -106,4 +106,3 @@ void syslog_example()
#endif #endif
} }
...@@ -11,8 +11,43 @@ ...@@ -11,8 +11,43 @@
</ProjectConfiguration> </ProjectConfiguration>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\include\spdlog\details\format.cc">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="example.cpp" /> <ClCompile Include="example.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\spdlog\async_logger.h" />
<ClInclude Include="..\include\spdlog\common.h" />
<ClInclude Include="..\include\spdlog\details\async_logger_impl.h" />
<ClInclude Include="..\include\spdlog\details\async_log_helper.h" />
<ClInclude Include="..\include\spdlog\details\file_helper.h" />
<ClInclude Include="..\include\spdlog\details\format.h" />
<ClInclude Include="..\include\spdlog\details\logger_impl.h" />
<ClInclude Include="..\include\spdlog\details\log_msg.h" />
<ClInclude Include="..\include\spdlog\details\mpmc_bounded_q.h" />
<ClInclude Include="..\include\spdlog\details\null_mutex.h" />
<ClInclude Include="..\include\spdlog\details\os.h" />
<ClInclude Include="..\include\spdlog\details\pattern_formatter_impl.h" />
<ClInclude Include="..\include\spdlog\details\registry.h" />
<ClInclude Include="..\include\spdlog\details\spdlog_impl.h" />
<ClInclude Include="..\include\spdlog\formatter.h" />
<ClInclude Include="..\include\spdlog\logger.h" />
<ClInclude Include="..\include\spdlog\sinks\android_sink.h" />
<ClInclude Include="..\include\spdlog\sinks\ansicolor_sink.h" />
<ClInclude Include="..\include\spdlog\sinks\base_sink.h" />
<ClInclude Include="..\include\spdlog\sinks\dist_sink.h" />
<ClInclude Include="..\include\spdlog\sinks\file_sinks.h" />
<ClInclude Include="..\include\spdlog\sinks\msvc_sink.h" />
<ClInclude Include="..\include\spdlog\sinks\null_sink.h" />
<ClInclude Include="..\include\spdlog\sinks\ostream_sink.h" />
<ClInclude Include="..\include\spdlog\sinks\sink.h" />
<ClInclude Include="..\include\spdlog\sinks\stdout_sinks.h" />
<ClInclude Include="..\include\spdlog\sinks\syslog_sink.h" />
<ClInclude Include="..\include\spdlog\spdlog.h" />
<ClInclude Include="..\include\spdlog\tweakme.h" />
</ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{9E5AB93A-0CCE-4BAC-9FCB-0FC9CB5EB8D2}</ProjectGuid> <ProjectGuid>{9E5AB93A-0CCE-4BAC-9FCB-0FC9CB5EB8D2}</ProjectGuid>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
......
...@@ -63,7 +63,7 @@ public: ...@@ -63,7 +63,7 @@ public:
void flush() override; void flush() override;
protected: protected:
void _log_msg(details::log_msg& msg) override; void _sink_it(details::log_msg& msg) override;
void _set_formatter(spdlog::formatter_ptr msg_formatter) override; void _set_formatter(spdlog::formatter_ptr msg_formatter) override;
void _set_pattern(const std::string& pattern) override; void _set_pattern(const std::string& pattern) override;
......
...@@ -56,26 +56,32 @@ using level_t = details::null_atomic_int; ...@@ -56,26 +56,32 @@ using level_t = details::null_atomic_int;
using level_t = std::atomic_int; using level_t = std::atomic_int;
#endif #endif
#define SPDLOG_LEVEL_TRACE 0
#define SPDLOG_LEVEL_DEBUG 1
#define SPDLOG_LEVEL_INFO 2
#define SPDLOG_LEVEL_WARN 3
#define SPDLOG_LEVEL_ERR 4
#define SPDLOG_LEVEL_CRIT 5
#define SPDLOG_LEVEL_OFF 6
//Log level enum //Log level enum
namespace level namespace level
{ {
typedef enum typedef enum
{ {
trace = 0, trace = SPDLOG_LEVEL_TRACE,
debug = 1, debug = SPDLOG_LEVEL_DEBUG,
info = 2, info = SPDLOG_LEVEL_INFO,
notice = 3, warn = SPDLOG_LEVEL_WARN,
warn = 4, err = SPDLOG_LEVEL_ERR,
err = 5, critical = SPDLOG_LEVEL_CRIT,
critical = 6, off = SPDLOG_LEVEL_OFF
alert = 7,
emerg = 8,
off = 9
} level_enum; } level_enum;
static const char* level_names[] { "trace", "debug", "info", "notice", "warning", "error", "critical", "alert", "emerg", "off"}; static const char* level_names[] { "trace", "debug", "info", "warning", "error", "critical", "off"};
static const char* short_level_names[] { "T", "D", "I", "N", "W", "E", "C", "A", "M", "O"}; static const char* short_level_names[] { "T", "D", "I", "W", "E", "C", "O"};
inline const char* to_str(spdlog::level::level_enum l) inline const char* to_str(spdlog::level::level_enum l)
{ {
...@@ -124,5 +130,7 @@ using filename_t = std::wstring; ...@@ -124,5 +130,7 @@ using filename_t = std::wstring;
using filename_t = std::string; using filename_t = std::string;
#endif #endif
#define SDLOG_STR_HELPER(x) #x
#define SPDLOG_STR(x) SDLOG_STR_HELPER(x)
} //spdlog } //spdlog
...@@ -86,21 +86,22 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT: ...@@ -86,21 +86,22 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
// construct from log_msg // construct from log_msg
async_msg(const details::log_msg& m) : async_msg(const details::log_msg& m) :
logger_name(m.logger_name),
level(m.level), level(m.level),
time(m.time), time(m.time),
thread_id(m.thread_id), thread_id(m.thread_id),
txt(m.raw.data(), m.raw.size()), txt(m.raw.data(), m.raw.size()),
msg_type(async_msg_type::log) msg_type(async_msg_type::log)
{} {
#ifndef SPDLOG_NO_NAME
logger_name = *m.logger_name;
#endif
}
// copy into log_msg // copy into log_msg
void fill_log_msg(log_msg &msg) void fill_log_msg(log_msg &msg)
{ {
msg.clear(); msg.logger_name = &logger_name;
msg.logger_name = logger_name;
msg.level = level; msg.level = level;
msg.time = time; msg.time = time;
msg.thread_id = thread_id; msg.thread_id = thread_id;
...@@ -278,7 +279,7 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_ ...@@ -278,7 +279,7 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_
{ {
async_msg incoming_async_msg; async_msg incoming_async_msg;
log_msg incoming_log_msg;
if (_q.dequeue(incoming_async_msg)) if (_q.dequeue(incoming_async_msg))
{ {
...@@ -295,6 +296,7 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_ ...@@ -295,6 +296,7 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_
break; break;
default: default:
log_msg incoming_log_msg;
incoming_async_msg.fill_log_msg(incoming_log_msg); incoming_async_msg.fill_log_msg(incoming_log_msg);
_formatter->format(incoming_log_msg); _formatter->format(incoming_log_msg);
for (auto &s : _sinks) for (auto &s : _sinks)
......
...@@ -71,7 +71,7 @@ inline void spdlog::async_logger::_set_pattern(const std::string& pattern) ...@@ -71,7 +71,7 @@ inline void spdlog::async_logger::_set_pattern(const std::string& pattern)
} }
inline void spdlog::async_logger::_log_msg(details::log_msg& msg) inline void spdlog::async_logger::_sink_it(details::log_msg& msg)
{ {
_async_log_helper->log(msg); _async_log_helper->log(msg);
} }
//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#pragma once
#include <spdlog/common.h>
#include <spdlog/details/log_msg.h>
#include <string>
// Line logger class - aggregates operator<< calls to fast ostream
// and logs upon destruction
namespace spdlog
{
// Forward declaration
class logger;
namespace details
{
class line_logger
{
public:
line_logger(logger* callback_logger, level::level_enum msg_level, bool enabled);
// No copy intended. Only move
line_logger(const line_logger& other) = delete;
line_logger& operator=(const line_logger&) = delete;
line_logger& operator=(line_logger&&) = delete;
line_logger(line_logger&& other);
//Log the log message using the callback logger
~line_logger();
//
// Support for format string with variadic args
//
void write(const char* what);
template <typename... Args>
void write(const char* fmt, const Args&... args);
//
// Support for operator<<
//
DEPRECATED line_logger& operator<<(const char* what);
DEPRECATED line_logger& operator<<(const std::string& what);
DEPRECATED line_logger& operator<<(int what);
DEPRECATED line_logger& operator<<(unsigned int what);
DEPRECATED line_logger& operator<<(long what);
DEPRECATED line_logger& operator<<(unsigned long what);
DEPRECATED line_logger& operator<<(long long what);
DEPRECATED line_logger& operator<<(unsigned long long what);
DEPRECATED line_logger& operator<<(double what);
DEPRECATED line_logger& operator<<(long double what);
DEPRECATED line_logger& operator<<(float what);
DEPRECATED line_logger& operator<<(char what);
//Support user types which implements operator<<
template<typename T>
DEPRECATED line_logger& operator<<(const T& what);
void disable();
bool is_enabled() const;
private:
logger* _callback_logger;
log_msg _log_msg;
bool _enabled;
};
} //Namespace details
} // Namespace spdlog
//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#pragma once
#include <type_traits>
#include <spdlog/details/line_logger_fwd.h>
#include <spdlog/common.h>
#include <spdlog/logger.h>
#include <string>
#include <utility>
// Line logger class - aggregates operator<< calls to fast ostream
// and logs upon destruction
inline spdlog::details::line_logger::line_logger(logger* callback_logger, level::level_enum msg_level, bool enabled):
_callback_logger(callback_logger),
_log_msg(msg_level),
_enabled(enabled)
{}
inline spdlog::details::line_logger::line_logger(line_logger&& other) :
_callback_logger(other._callback_logger),
_log_msg(std::move(other._log_msg)),
_enabled(other._enabled)
{
other.disable();
}
//Log the log message using the callback logger
inline spdlog::details::line_logger::~line_logger()
{
if (_enabled)
{
#ifndef SPDLOG_NO_NAME
_log_msg.logger_name = _callback_logger->name();
#endif
#ifndef SPDLOG_NO_DATETIME
_log_msg.time = os::now();
#endif
#ifndef SPDLOG_NO_THREAD_ID
_log_msg.thread_id = os::thread_id();
#endif
_callback_logger->_log_msg(_log_msg);
}
}
//
// Support for format string with variadic args
//
inline void spdlog::details::line_logger::write(const char* what)
{
if (_enabled)
_log_msg.raw << what;
}
template <typename... Args>
inline void spdlog::details::line_logger::write(const char* fmt, const Args&... args)
{
if (!_enabled)
return;
try
{
_log_msg.raw.write(fmt, args...);
}
catch (const fmt::FormatError& e)
{
throw spdlog_ex(fmt::format("formatting error while processing format string '{}': {}", fmt, e.what()));
}
}
//
// Support for operator<<
//
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(const char* what)
{
if (_enabled)
_log_msg.raw << what;
return *this;
}
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(const std::string& what)
{
if (_enabled)
_log_msg.raw << what;
return *this;
}
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(int what)
{
if (_enabled)
_log_msg.raw << what;
return *this;
}
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(unsigned int what)
{
if (_enabled)
_log_msg.raw << what;
return *this;
}
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(long what)
{
if (_enabled)
_log_msg.raw << what;
return *this;
}
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(unsigned long what)
{
if (_enabled)
_log_msg.raw << what;
return *this;
}
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(long long what)
{
if (_enabled)
_log_msg.raw << what;
return *this;
}
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(unsigned long long what)
{
if (_enabled)
_log_msg.raw << what;
return *this;
}
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(double what)
{
if (_enabled)
_log_msg.raw << what;
return *this;
}
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(long double what)
{
if (_enabled)
_log_msg.raw << what;
return *this;
}
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(float what)
{
if (_enabled)
_log_msg.raw << what;
return *this;
}
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(char what)
{
if (_enabled)
_log_msg.raw << what;
return *this;
}
//Support user types which implements operator<<
template<typename T>
inline spdlog::details::line_logger& spdlog::details::line_logger::operator<<(const T& what)
{
if (_enabled)
_log_msg.raw.write("{}", what);
return *this;
}
inline void spdlog::details::line_logger::disable()
{
_enabled = false;
}
inline bool spdlog::details::line_logger::is_enabled() const
{
return _enabled;
}
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <spdlog/common.h> #include <spdlog/common.h>
#include <spdlog/details/format.h> #include <spdlog/details/format.h>
#include <spdlog/details/os.h>
#include <string> #include <string>
#include <utility> #include <utility>
...@@ -18,59 +19,23 @@ namespace details ...@@ -18,59 +19,23 @@ namespace details
struct log_msg struct log_msg
{ {
log_msg() = default; log_msg() = default;
log_msg(level::level_enum l): log_msg(const std::string *loggers_name, level::level_enum lvl) : logger_name(loggers_name), level(lvl)
logger_name(),
level(l),
raw(),
formatted() {}
log_msg(const log_msg& other) :
logger_name(other.logger_name),
level(other.level),
time(other.time),
thread_id(other.thread_id)
{ {
if (other.raw.size()) #ifndef SPDLOG_NO_DATETIME
raw << fmt::BasicStringRef<char>(other.raw.data(), other.raw.size()); time = os::now();
if (other.formatted.size()) #endif
formatted << fmt::BasicStringRef<char>(other.formatted.data(), other.formatted.size());
}
log_msg(log_msg&& other) : #ifndef SPDLOG_NO_THREAD_ID
logger_name(std::move(other.logger_name)), thread_id = os::thread_id();
level(other.level), #endif
time(std::move(other.time)),
thread_id(other.thread_id),
raw(std::move(other.raw)),
formatted(std::move(other.formatted))
{
other.clear();
} }
log_msg& operator=(log_msg&& other) log_msg(const log_msg& other) = delete;
{ log_msg& operator=(log_msg&& other) = delete;
if (this == &other) log_msg(log_msg&& other) = delete;
return *this;
logger_name = std::move(other.logger_name);
level = other.level;
time = std::move(other.time);
thread_id = other.thread_id;
raw = std::move(other.raw);
formatted = std::move(other.formatted);
other.clear();
return *this;
}
void clear()
{
level = level::off;
raw.clear();
formatted.clear();
}
std::string logger_name; const std::string *logger_name;
level::level_enum level; level::level_enum level;
log_clock::time_point time; log_clock::time_point time;
size_t thread_id; size_t thread_id;
......
...@@ -31,8 +31,7 @@ inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list si ...@@ -31,8 +31,7 @@ inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list si
// ctor with single sink // ctor with single sink
inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink) : inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink) :
logger(logger_name, logger(logger_name, {
{
single_sink single_sink
}) {} }) {}
...@@ -50,210 +49,131 @@ inline void spdlog::logger::set_pattern(const std::string& pattern) ...@@ -50,210 +49,131 @@ inline void spdlog::logger::set_pattern(const std::string& pattern)
_set_pattern(pattern); _set_pattern(pattern);
} }
//
// log only if given level>=logger's log level
//
template <typename... Args> template <typename... Args>
inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl, const char* fmt, const Args&... args) inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Args&... args)
{ {
bool msg_enabled = should_log(lvl); if (!should_log(lvl)) return;
details::line_logger l(this, lvl, msg_enabled);
l.write(fmt, args...);
return l;
}
inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl) details::log_msg log_msg(&_name, lvl);
{ try
return details::line_logger(this, lvl, should_log(lvl)); {
} log_msg.raw.write(fmt, args...);
}
catch (fmt::FormatError &ex)
{
throw spdlog::spdlog_ex(std::string("format error in \"") + fmt + "\": " + ex.what());
}
template<typename T> _formatter->format(log_msg);
inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl, const T& msg) _sink_it(log_msg);
{
bool msg_enabled = should_log(lvl);
details::line_logger l(this, lvl, msg_enabled);
l.write("{}", msg);
return l;
}
//
// logger.info(cppformat_string, arg1, arg2, arg3, ...) call style
//
template <typename... Args>
inline spdlog::details::line_logger spdlog::logger::trace(const char* fmt, const Args&... args)
{
return _log_if_enabled(level::trace, fmt, args...);
} }
template <typename... Args> template <typename... Args>
inline spdlog::details::line_logger spdlog::logger::debug(const char* fmt, const Args&... args) inline void spdlog::logger::log(level::level_enum lvl, const char* msg)
{ {
return _log_if_enabled(level::debug, fmt, args...); if (!should_log(lvl)) return;
details::log_msg log_msg(&_name, lvl);
log_msg.raw << msg;
_formatter->format(log_msg);
_sink_it(log_msg);
} }
template <typename... Args> template<typename T>
inline spdlog::details::line_logger spdlog::logger::info(const char* fmt, const Args&... args) inline void spdlog::logger::log(level::level_enum lvl, const T& msg)
{ {
return _log_if_enabled(level::info, fmt, args...); if (!should_log(lvl)) return;
details::log_msg log_msg(&_name, lvl);
log_msg.raw << msg;
_formatter->format(log_msg);
_sink_it(log_msg);
} }
template <typename... Args> template <typename... Args>
inline spdlog::details::line_logger spdlog::logger::notice(const char* fmt, const Args&... args) inline void spdlog::logger::trace(const char* fmt, const Args&... args)
{ {
return _log_if_enabled(level::notice, fmt, args...); log(level::trace, fmt, args...);
} }
template <typename... Args> template <typename... Args>
inline spdlog::details::line_logger spdlog::logger::warn(const char* fmt, const Args&... args) inline void spdlog::logger::debug(const char* fmt, const Args&... args)
{ {
return _log_if_enabled(level::warn, fmt, args...); log(level::debug, fmt, args...);
} }
template <typename... Args> template <typename... Args>
inline spdlog::details::line_logger spdlog::logger::error(const char* fmt, const Args&... args) inline void spdlog::logger::info(const char* fmt, const Args&... args)
{ {
return _log_if_enabled(level::err, fmt, args...); log(level::info, fmt, args...);
} }
template <typename... Args> template <typename... Args>
inline spdlog::details::line_logger spdlog::logger::critical(const char* fmt, const Args&... args) inline void spdlog::logger::warn(const char* fmt, const Args&... args)
{ {
return _log_if_enabled(level::critical, fmt, args...); log(level::warn, fmt, args...);
} }
template <typename... Args> template <typename... Args>
inline spdlog::details::line_logger spdlog::logger::alert(const char* fmt, const Args&... args) inline void spdlog::logger::error(const char* fmt, const Args&... args)
{ {
return _log_if_enabled(level::alert, fmt, args...); log(level::err, fmt, args...);
} }
template <typename... Args> template <typename... Args>
inline spdlog::details::line_logger spdlog::logger::emerg(const char* fmt, const Args&... args) inline void spdlog::logger::critical(const char* fmt, const Args&... args)
{ {
return _log_if_enabled(level::emerg, fmt, args...); log(level::critical, fmt, args...);
} }
//
// logger.info(msg) << ".." call style
//
template<typename T>
inline spdlog::details::line_logger spdlog::logger::trace(const T& msg)
{
return _log_if_enabled(level::trace, msg);
}
template<typename T> template<typename T>
inline spdlog::details::line_logger spdlog::logger::debug(const T& msg) inline void spdlog::logger::trace(const T& msg)
{ {
return _log_if_enabled(level::debug, msg); log(level::trace, msg);
} }
template<typename T> template<typename T>
inline spdlog::details::line_logger spdlog::logger::info(const T& msg) inline void spdlog::logger::debug(const T& msg)
{ {
return _log_if_enabled(level::info, msg); log(level::debug, msg);
} }
template<typename T>
inline spdlog::details::line_logger spdlog::logger::notice(const T& msg)
{
return _log_if_enabled(level::notice, msg);
}
template<typename T> template<typename T>
inline spdlog::details::line_logger spdlog::logger::warn(const T& msg) inline void spdlog::logger::info(const T& msg)
{ {
return _log_if_enabled(level::warn, msg); log(level::info, msg);
} }
template<typename T>
inline spdlog::details::line_logger spdlog::logger::error(const T& msg)
{
return _log_if_enabled(level::err, msg);
}
template<typename T> template<typename T>
inline spdlog::details::line_logger spdlog::logger::critical(const T& msg) inline void spdlog::logger::warn(const T& msg)
{ {
return _log_if_enabled(level::critical, msg); log(level::warn, msg);
} }
template<typename T> template<typename T>
inline spdlog::details::line_logger spdlog::logger::alert(const T& msg) inline void spdlog::logger::error(const T& msg)
{ {
return _log_if_enabled(level::alert, msg); log(level::err, msg);
} }
template<typename T> template<typename T>
inline spdlog::details::line_logger spdlog::logger::emerg(const T& msg) inline void spdlog::logger::critical(const T& msg)
{ {
return _log_if_enabled(level::emerg, msg); log(level::critical, msg);
} }
//
// logger.info() << ".." call style
//
inline spdlog::details::line_logger spdlog::logger::trace()
{
return _log_if_enabled(level::trace);
}
inline spdlog::details::line_logger spdlog::logger::debug()
{
return _log_if_enabled(level::debug);
}
inline spdlog::details::line_logger spdlog::logger::info()
{
return _log_if_enabled(level::info);
}
inline spdlog::details::line_logger spdlog::logger::notice()
{
return _log_if_enabled(level::notice);
}
inline spdlog::details::line_logger spdlog::logger::warn()
{
return _log_if_enabled(level::warn);
}
inline spdlog::details::line_logger spdlog::logger::error()
{
return _log_if_enabled(level::err);
}
inline spdlog::details::line_logger spdlog::logger::critical()
{
return _log_if_enabled(level::critical);
}
inline spdlog::details::line_logger spdlog::logger::alert()
{
return _log_if_enabled(level::alert);
}
inline spdlog::details::line_logger spdlog::logger::emerg()
{
return _log_if_enabled(level::emerg);
}
// always log, no matter what is the actual logger's log level
template <typename... Args>
inline spdlog::details::line_logger spdlog::logger::force_log(level::level_enum lvl, const char* fmt, const Args&... args)
{
details::line_logger l(this, lvl, true);
l.write(fmt, args...);
return l;
}
// //
// name and level // name and level
// //
...@@ -285,9 +205,8 @@ inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) cons ...@@ -285,9 +205,8 @@ inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) cons
// //
// protected virtual called at end of each user log call (if enabled) by the line_logger // protected virtual called at end of each user log call (if enabled) by the line_logger
// //
inline void spdlog::logger::_log_msg(details::log_msg& msg) inline void spdlog::logger::_sink_it(details::log_msg& msg)
{ {
_formatter->format(msg);
for (auto &sink : _sinks) for (auto &sink : _sinks)
sink->log(msg); sink->log(msg);
......
...@@ -39,7 +39,7 @@ class name_formatter :public flag_formatter ...@@ -39,7 +39,7 @@ class name_formatter :public flag_formatter
{ {
void format(details::log_msg& msg, const std::tm&) override void format(details::log_msg& msg, const std::tm&) override
{ {
msg.formatted << msg.logger_name; msg.formatted << *msg.logger_name;
} }
}; };
} }
...@@ -435,7 +435,7 @@ class full_formatter :public flag_formatter ...@@ -435,7 +435,7 @@ class full_formatter :public flag_formatter
#endif #endif
#ifndef SPDLOG_NO_NAME #ifndef SPDLOG_NO_NAME
msg.formatted << '[' << msg.logger_name << "] "; msg.formatted << '[' << *msg.logger_name << "] ";
#endif #endif
msg.formatted << '[' << level::to_str(msg.level) << "] "; msg.formatted << '[' << level::to_str(msg.level) << "] ";
...@@ -613,7 +613,11 @@ inline void spdlog::pattern_formatter::format(details::log_msg& msg) ...@@ -613,7 +613,11 @@ inline void spdlog::pattern_formatter::format(details::log_msg& msg)
{ {
try try
{ {
#ifndef SPDLOG_NO_DATETIME
auto tm_time = details::os::localtime(log_clock::to_time_t(msg.time)); auto tm_time = details::os::localtime(log_clock::to_time_t(msg.time));
#else
std::tm tm_time;
#endif
for (auto &f : _formatters) for (auto &f : _formatters)
{ {
f->format(msg, tm_time); f->format(msg, tm_time);
......
...@@ -14,12 +14,12 @@ ...@@ -14,12 +14,12 @@
#include <spdlog/sinks/base_sink.h> #include <spdlog/sinks/base_sink.h>
#include <spdlog/common.h> #include <spdlog/common.h>
#include <spdlog/details/line_logger_fwd.h>
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <string> #include <string>
namespace spdlog namespace spdlog
{ {
...@@ -35,75 +35,42 @@ public: ...@@ -35,75 +35,42 @@ public:
logger(const logger&) = delete; logger(const logger&) = delete;
logger& operator=(const logger&) = delete; logger& operator=(const logger&) = delete;
void set_level(level::level_enum);
level::level_enum level() const;
const std::string& name() const; template <typename... Args> void log(level::level_enum lvl, const char* fmt, const Args&... args);
bool should_log(level::level_enum) const; template <typename... Args> void log(level::level_enum lvl, const char* msg);
template <typename... Args> void trace(const char* fmt, const Args&... args);
template <typename... Args> void debug(const char* fmt, const Args&... args);
template <typename... Args> void info(const char* fmt, const Args&... args);
template <typename... Args> void warn(const char* fmt, const Args&... args);
template <typename... Args> void error(const char* fmt, const Args&... args);
template <typename... Args> void critical(const char* fmt, const Args&... args);
template <typename T> void log(level::level_enum lvl, const T&);
template <typename T> void trace(const T&);
template <typename T> void debug(const T&);
template <typename T> void info(const T&);
template <typename T> void warn(const T&);
template <typename T> void error(const T&);
template <typename T> void critical(const T&);
// automatically call flush() after a message of level log_level or higher is emitted
void flush_on(level::level_enum log_level);
// logger.info(cppformat_string, arg1, arg2, arg3, ...) call style bool should_log(level::level_enum) const;
template <typename... Args> details::line_logger trace(const char* fmt, const Args&... args); void set_level(level::level_enum);
template <typename... Args> details::line_logger debug(const char* fmt, const Args&... args); level::level_enum level() const;
template <typename... Args> details::line_logger info(const char* fmt, const Args&... args); const std::string& name() const;
template <typename... Args> details::line_logger notice(const char* fmt, const Args&... args);
template <typename... Args> details::line_logger warn(const char* fmt, const Args&... args);
template <typename... Args> details::line_logger error(const char* fmt, const Args&... args);
template <typename... Args> details::line_logger critical(const char* fmt, const Args&... args);
template <typename... Args> details::line_logger alert(const char* fmt, const Args&... args);
template <typename... Args> details::line_logger emerg(const char* fmt, const Args&... args);
// logger.info(msg) << ".." call style
template <typename T> details::line_logger trace(const T&);
template <typename T> details::line_logger debug(const T&);
template <typename T> details::line_logger info(const T&);
template <typename T> details::line_logger notice(const T&);
template <typename T> details::line_logger warn(const T&);
template <typename T> details::line_logger error(const T&);
template <typename T> details::line_logger critical(const T&);
template <typename T> details::line_logger alert(const T&);
template <typename T> details::line_logger emerg(const T&);
// logger.info() << ".." call style
details::line_logger trace();
details::line_logger debug();
details::line_logger info();
details::line_logger notice();
details::line_logger warn();
details::line_logger error();
details::line_logger critical();
details::line_logger alert();
details::line_logger emerg();
// Create log message with the given level, no matter what is the actual logger's level
template <typename... Args>
details::line_logger force_log(level::level_enum lvl, const char* fmt, const Args&... args);
// Set the format of the log messages from this logger
void set_pattern(const std::string&); void set_pattern(const std::string&);
void set_formatter(formatter_ptr); void set_formatter(formatter_ptr);
// automatically call flush() if message level >= log_level
void flush_on(level::level_enum log_level);
virtual void flush(); virtual void flush();
protected: protected:
virtual void _log_msg(details::log_msg&); virtual void _sink_it(details::log_msg&);
virtual void _set_pattern(const std::string&); virtual void _set_pattern(const std::string&);
virtual void _set_formatter(formatter_ptr); virtual void _set_formatter(formatter_ptr);
details::line_logger _log_if_enabled(level::level_enum lvl);
template <typename... Args>
details::line_logger _log_if_enabled(level::level_enum lvl, const char* fmt, const Args&... args);
template<typename T>
inline details::line_logger _log_if_enabled(level::level_enum lvl, const T& msg);
friend details::line_logger; const std::string _name;
std::string _name;
std::vector<sink_ptr> _sinks; std::vector<sink_ptr> _sinks;
formatter_ptr _formatter; formatter_ptr _formatter;
spdlog::level_t _level; spdlog::level_t _level;
...@@ -112,5 +79,5 @@ protected: ...@@ -112,5 +79,5 @@ protected:
} }
#include <spdlog/details/logger_impl.h> #include <spdlog/details/logger_impl.h>
#include <spdlog/details/line_logger_impl.h>
...@@ -74,13 +74,10 @@ inline ansicolor_sink::ansicolor_sink(sink_ptr wrapped_sink) : sink_(wrapped_sin ...@@ -74,13 +74,10 @@ inline ansicolor_sink::ansicolor_sink(sink_ptr wrapped_sink) : sink_(wrapped_sin
{ {
colors_[level::trace] = cyan; colors_[level::trace] = cyan;
colors_[level::debug] = cyan; colors_[level::debug] = cyan;
colors_[level::info] = white; colors_[level::info] = bold;
colors_[level::notice] = bold + white; colors_[level::warn] = yellow + bold;
colors_[level::warn] = bold + yellow; colors_[level::err] = red + bold;
colors_[level::err] = red; colors_[level::critical] = bold + on_red;
colors_[level::critical] = bold + red;
colors_[level::alert] = bold + white + on_red;
colors_[level::emerg] = bold + yellow + on_red;
colors_[level::off] = reset; colors_[level::off] = reset;
} }
...@@ -91,6 +88,10 @@ inline void ansicolor_sink::log(const details::log_msg& msg) ...@@ -91,6 +88,10 @@ inline void ansicolor_sink::log(const details::log_msg& msg)
const std::string& s = msg.formatted.str(); const std::string& s = msg.formatted.str();
const std::string& suffix = reset; const std::string& suffix = reset;
details::log_msg m; details::log_msg m;
m.level = msg.level;
m.logger_name = msg.logger_name;
m.time = msg.time;
m.thread_id = msg.thread_id;
m.formatted << prefix << s << suffix; m.formatted << prefix << s << suffix;
sink_->log(m); sink_->log(m);
} }
......
...@@ -35,12 +35,9 @@ public: ...@@ -35,12 +35,9 @@ public:
_priorities[static_cast<int>(level::trace)] = LOG_DEBUG; _priorities[static_cast<int>(level::trace)] = LOG_DEBUG;
_priorities[static_cast<int>(level::debug)] = LOG_DEBUG; _priorities[static_cast<int>(level::debug)] = LOG_DEBUG;
_priorities[static_cast<int>(level::info)] = LOG_INFO; _priorities[static_cast<int>(level::info)] = LOG_INFO;
_priorities[static_cast<int>(level::notice)] = LOG_NOTICE;
_priorities[static_cast<int>(level::warn)] = LOG_WARNING; _priorities[static_cast<int>(level::warn)] = LOG_WARNING;
_priorities[static_cast<int>(level::err)] = LOG_ERR; _priorities[static_cast<int>(level::err)] = LOG_ERR;
_priorities[static_cast<int>(level::critical)] = LOG_CRIT; _priorities[static_cast<int>(level::critical)] = LOG_CRIT;
_priorities[static_cast<int>(level::alert)] = LOG_ALERT;
_priorities[static_cast<int>(level::emerg)] = LOG_EMERG;
_priorities[static_cast<int>(level::off)] = LOG_INFO; _priorities[static_cast<int>(level::off)] = LOG_INFO;
//set ident to be program name if empty //set ident to be program name if empty
...@@ -65,7 +62,7 @@ public: ...@@ -65,7 +62,7 @@ public:
private: private:
std::array<int, 10> _priorities; std::array<int, 7> _priorities;
//must store the ident because the man says openlog might use the pointer as is and not a string copy //must store the ident because the man says openlog might use the pointer as is and not a string copy
const std::string _ident; const std::string _ident;
......
...@@ -134,14 +134,15 @@ void drop_all(); ...@@ -134,14 +134,15 @@ void drop_all();
// SPDLOG_DEBUG(my_logger, "Some debug message {} {}", 1, 3.2); // SPDLOG_DEBUG(my_logger, "Some debug message {} {}", 1, 3.2);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef SPDLOG_TRACE_ON #ifdef SPDLOG_TRACE_ON
#define SPDLOG_TRACE(logger, ...) logger->trace(__VA_ARGS__) << " (" << __FILE__ << " #" << __LINE__ <<")"; #define SPDLOG_TRACE(logger, ...) logger->trace(__FILE__ ## " line " ## SPDLOG_STR(__LINE__) ## ": " ## __VA_ARGS__);
#else #else
#define SPDLOG_TRACE(logger, ...) #define SPDLOG_TRACE(logger, ...)
#endif #endif
#ifdef SPDLOG_DEBUG_ON #ifdef SPDLOG_DEBUG_ON
#define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__) << " (" << __FILE__ << " #" << __LINE__ <<")"; #define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__)
#else #else
#define SPDLOG_DEBUG(logger, ...) #define SPDLOG_DEBUG(logger, ...)
#endif #endif
......
...@@ -5,21 +5,28 @@ ...@@ -5,21 +5,28 @@
#pragma once #pragma once
///////////////////////////////////////////////////////////////////////////////
// //
// Edit this file to squeeze every last drop of performance out of spdlog. // Edit this file to squeeze every last drop of performance out of spdlog.
// //
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Under Linux, the much faster CLOCK_REALTIME_COARSE clock can be used. // Under Linux, the much faster CLOCK_REALTIME_COARSE clock can be used.
// This clock is less accurate - can be off by dozens of millis - depending on the kernel HZ. // This clock is less accurate - can be off by dozens of millis - depending on the kernel HZ.
// Uncomment to use it instead of the regular (but slower) clock. // Uncomment to use it instead of the regular clock.
//
// #define SPDLOG_CLOCK_COARSE // #define SPDLOG_CLOCK_COARSE
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Uncomment if date/time logging is not needed. // Uncomment if date/time logging is not needed and never appear in the log pattern.
// This will prevent spdlog from quering the clock on each log call. // This will prevent spdlog from quering the clock on each log call.
//
// WARNING: If the log pattern contains any date/time while this flag is on, the result is undefined.
// You must set new pattern(spdlog::set_pattern(..") without any date/time in it
//
// #define SPDLOG_NO_DATETIME // #define SPDLOG_NO_DATETIME
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -27,6 +34,9 @@ ...@@ -27,6 +34,9 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Uncomment if thread id logging is not needed (i.e. no %t in the log pattern). // Uncomment if thread id logging is not needed (i.e. no %t in the log pattern).
// This will prevent spdlog from quering the thread id on each log call. // This will prevent spdlog from quering the thread id on each log call.
//
// WARNING: If the log pattern contains thread id (i.e, %t) while this flag is on, the result is undefined.
//
// #define SPDLOG_NO_THREAD_ID // #define SPDLOG_NO_THREAD_ID
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -34,12 +44,14 @@ ...@@ -34,12 +44,14 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Uncomment if logger name logging is not needed. // Uncomment if logger name logging is not needed.
// This will prevent spdlog from copying the logger name on each log call. // This will prevent spdlog from copying the logger name on each log call.
//
// #define SPDLOG_NO_NAME // #define SPDLOG_NO_NAME
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Uncomment to enable the SPDLOG_DEBUG/SPDLOG_TRACE macros. // Uncomment to enable the SPDLOG_DEBUG/SPDLOG_TRACE macros.
//
// #define SPDLOG_DEBUG_ON // #define SPDLOG_DEBUG_ON
// #define SPDLOG_TRACE_ON // #define SPDLOG_TRACE_ON
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -49,18 +61,21 @@ ...@@ -49,18 +61,21 @@
// Uncomment to avoid locking in the registry operations (spdlog::get(), spdlog::drop() spdlog::register()). // Uncomment to avoid locking in the registry operations (spdlog::get(), spdlog::drop() spdlog::register()).
// Use only if your code never modifes concurrently the registry. // Use only if your code never modifes concurrently the registry.
// Note that upon creating a logger the registry is modified by spdlog.. // Note that upon creating a logger the registry is modified by spdlog..
//
// #define SPDLOG_NO_REGISTRY_MUTEX // #define SPDLOG_NO_REGISTRY_MUTEX
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Uncomment to avoid spdlog's usage of atomic log levels // Uncomment to avoid spdlog's usage of atomic log levels
// Use only if your code never modifies a logger's log levels concurrently. // Use only if your code never modifies a logger's log levels concurrently by different threads.
//
// #define SPDLOG_NO_ATOMIC_LEVELS // #define SPDLOG_NO_ATOMIC_LEVELS
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Uncomment to enable usage of wchar_t for file names on Windows. // Uncomment to enable usage of wchar_t for file names on Windows.
//
// #define SPDLOG_WCHAR_FILENAMES // #define SPDLOG_WCHAR_FILENAMES
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment