Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
S
spdlog
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
spdlog
Commits
e2e3df90
Commit
e2e3df90
authored
Apr 05, 2019
by
gabime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
static lib wip
parent
ef8773a8
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
992 additions
and
1216 deletions
+992
-1216
example.cpp
example/example.cpp
+6
-6
common.h
include/spdlog/common.h
+7
-0
async_logger_impl.h
include/spdlog/details/async_logger_impl.h
+16
-2
fmt_helper.h
include/spdlog/details/fmt_helper.h
+1
-0
log_msg.h
include/spdlog/details/log_msg.h
+3
-23
logger_impl.h
include/spdlog/details/logger_impl.h
+0
-435
os.h
include/spdlog/details/os.h
+24
-345
pattern_formatter.h
include/spdlog/details/pattern_formatter.h
+0
-1
registry.h
include/spdlog/details/registry.h
+1
-0
logger.h
include/spdlog/logger.h
+265
-381
sink.h
include/spdlog/sinks/sink.h
+15
-23
log_msg.cpp
src/log_msg.cpp
+30
-0
logger.cpp
src/logger.cpp
+187
-0
os.cpp
src/os.cpp
+406
-0
sink.cpp
src/sink.cpp
+31
-0
No files found.
example/example.cpp
View file @
e2e3df90
...
@@ -10,16 +10,15 @@
...
@@ -10,16 +10,15 @@
#include "spdlog/logger.h"
#include "spdlog/logger.h"
namespace
spdlog
{
class
logger
;
}
spdlog
::
logger
*
get_logger
();
spdlog
::
logger
*
get_logger
();
int
main
(
int
,
char
*
[])
int
main
(
int
,
char
*
[])
{
{
auto
*
l
=
get_logger
();
auto
*
l
=
get_logger
();
l
->
info
(
"HELLO"
);
l
->
info
(
"HELLO {}"
,
"World"
);
l
->
warn
(
"SOME WARNINNG"
);
l
->
error
(
"Some {}"
,
"error"
);
}
}
\ No newline at end of file
include/spdlog/common.h
View file @
e2e3df90
...
@@ -27,6 +27,13 @@
...
@@ -27,6 +27,13 @@
#include "spdlog/fmt/fmt.h"
#include "spdlog/fmt/fmt.h"
#ifdef SPDLOG_HEADER_ONLY
#define SPDLOG_INLINE inline
#else
#define SPDLOG_INLINE
#endif
// visual studio upto 2013 does not support noexcept nor constexpr
// visual studio upto 2013 does not support noexcept nor constexpr
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#define SPDLOG_NOEXCEPT throw()
#define SPDLOG_NOEXCEPT throw()
...
...
include/spdlog/details/async_logger_impl.h
View file @
e2e3df90
...
@@ -79,7 +79,14 @@ inline void spdlog::async_logger::backend_log_(const details::log_msg &incoming_
...
@@ -79,7 +79,14 @@ inline void spdlog::async_logger::backend_log_(const details::log_msg &incoming_
}
}
}
}
}
}
SPDLOG_CATCH_AND_HANDLE
catch
(
const
std
::
exception
&
ex
)
{
err_handler_
(
ex
.
what
());
}
catch
(...)
{
err_handler_
(
"Unknown exception in logger"
);
}
if
(
should_flush_
(
incoming_log_msg
))
if
(
should_flush_
(
incoming_log_msg
))
{
{
...
@@ -96,7 +103,14 @@ inline void spdlog::async_logger::backend_flush_()
...
@@ -96,7 +103,14 @@ inline void spdlog::async_logger::backend_flush_()
sink
->
flush
();
sink
->
flush
();
}
}
}
}
SPDLOG_CATCH_AND_HANDLE
catch
(
const
std
::
exception
&
ex
)
{
err_handler_
(
ex
.
what
());
}
catch
(...)
{
err_handler_
(
"Unknown exception in logger"
);
}
}
}
inline
std
::
shared_ptr
<
spdlog
::
logger
>
spdlog
::
async_logger
::
clone
(
std
::
string
new_name
)
inline
std
::
shared_ptr
<
spdlog
::
logger
>
spdlog
::
async_logger
::
clone
(
std
::
string
new_name
)
...
...
include/spdlog/details/fmt_helper.h
View file @
e2e3df90
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
#include <chrono>
#include <chrono>
#include <type_traits>
#include <type_traits>
#include "spdlog/fmt/fmt.h"
#include "spdlog/fmt/fmt.h"
#include "spdlog/common.h"
// Some fmt helpers to efficiently format and pad ints and strings
// Some fmt helpers to efficiently format and pad ints and strings
namespace
spdlog
{
namespace
spdlog
{
...
...
include/spdlog/details/log_msg.h
View file @
e2e3df90
...
@@ -6,36 +6,16 @@
...
@@ -6,36 +6,16 @@
#pragma once
#pragma once
#include "spdlog/common.h"
#include "spdlog/common.h"
#include "spdlog/details/os.h"
#include <string>
#include <string>
#include <utility>
namespace
spdlog
{
namespace
spdlog
{
namespace
details
{
namespace
details
{
struct
log_msg
struct
log_msg
{
{
log_msg
(
source_loc
loc
,
const
std
::
string
*
loggers_name
,
level
::
level_enum
lvl
,
string_view_t
view
)
log_msg
(
source_loc
loc
,
const
std
::
string
*
loggers_name
,
level
::
level_enum
lvl
,
string_view_t
view
);
:
logger_name
(
loggers_name
)
,
level
(
lvl
)
log_msg
(
const
std
::
string
*
loggers_name
,
level
::
level_enum
lvl
,
string_view_t
view
);
#ifndef SPDLOG_NO_DATETIME
,
time
(
os
::
now
())
#endif
#ifndef SPDLOG_NO_THREAD_ID
,
thread_id
(
os
::
thread_id
())
#endif
,
source
(
loc
)
,
payload
(
view
)
{
}
log_msg
(
const
std
::
string
*
loggers_name
,
level
::
level_enum
lvl
,
string_view_t
view
)
:
log_msg
(
source_loc
{},
loggers_name
,
lvl
,
view
)
{
}
log_msg
(
const
log_msg
&
other
)
=
default
;
log_msg
(
const
log_msg
&
other
)
=
default
;
const
std
::
string
*
logger_name
{
nullptr
};
const
std
::
string
*
logger_name
{
nullptr
};
...
...
include/spdlog/details/logger_impl.h
deleted
100644 → 0
View file @
ef8773a8
//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#pragma once
#include "spdlog/details/fmt_helper.h"
#include <memory>
#include <string>
//#define SPDLOG_CATCH_AND_HANDLE \
// catch (const std::exception &ex) \
// { \
// err_handler_(ex.what()); \
// } \
// catch (...) \
// { \
// err_handler_("Unknown exception in logger"); \
// }
// create logger with given name, sinks and the default pattern formatter
// all other ctors will call this one
//template<typename It>
//inline spdlog::logger::logger(std::string logger_name, It begin, It end)
// : name_(std::move(logger_name))
// , sinks_(begin, end)
//{
//}
//// ctor with sinks as init list
//inline spdlog::logger::logger(std::string logger_name, sinks_init_list sinks_list)
// : logger(std::move(logger_name), sinks_list.begin(), sinks_list.end())
//{
//}
// ctor with single sink
//inline spdlog::logger::logger(std::string logger_name, spdlog::sink_ptr single_sink)
// : logger(std::move(logger_name), {std::move(single_sink)})
//{
//}
//inline spdlog::logger::~logger() = default;
//inline void spdlog::logger::set_formatter(std::unique_ptr<spdlog::formatter> f)
//{
// for (auto &sink : sinks_)
// {
// sink->set_formatter(f->clone());
// }
//}
//inline void spdlog::logger::set_pattern(std::string pattern, pattern_time_type time_type)
//{
// auto new_formatter = details::make_unique<spdlog::pattern_formatter>(std::move(pattern), time_type);
// set_formatter(std::move(new_formatter));
//}
//template<typename... Args>
//inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const char *fmt, const Args &... args)
//{
// if (!should_log(lvl))
// {
// return;
// }
//
// try
// {
// using details::fmt_helper::to_string_view;
// fmt::memory_buffer buf;
// fmt::format_to(buf, fmt, args...);
// details::log_msg log_msg(source, &name_, lvl, to_string_view(buf));
// sink_it_(log_msg);
// }
// SPDLOG_CATCH_AND_HANDLE
//}
//template<typename... Args>
//inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Args &... args)
//{
// log(source_loc{}, lvl, fmt, args...);
//}
//inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const char *msg)
//{
// if (!should_log(lvl))
// {
// return;
// }
//
// try
// {
// details::log_msg log_msg(source, &name_, lvl, spdlog::string_view_t(msg));
// sink_it_(log_msg);
// }
// SPDLOG_CATCH_AND_HANDLE
//}
//inline void spdlog::logger::log(level::level_enum lvl, const char *msg)
//{
// log(source_loc{}, lvl, msg);
//}
//template<class T>
//inline void spdlog::logger::log(level::level_enum lvl, const T &msg)
//{
// log(source_loc{}, lvl, msg);
//}
//
//template<class T, typename std::enable_if<std::is_convertible<T, spdlog::string_view_t>::value, T>::type *>
//inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const T &msg)
//{
// if (!should_log(lvl))
// {
// return;
// }
// try
// {
// details::log_msg log_msg(source, &name_, lvl, msg);
// sink_it_(log_msg);
// }
// SPDLOG_CATCH_AND_HANDLE
//}
//template<class T, typename std::enable_if<!std::is_convertible<T, spdlog::string_view_t>::value, T>::type *>
//inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const T &msg)
//{
// if (!should_log(lvl))
// {
// return;
// }
// try
// {
// using details::fmt_helper::to_string_view;
// fmt::memory_buffer buf;
// fmt::format_to(buf, "{}", msg);
// details::log_msg log_msg(source, &name_, lvl, to_string_view(buf));
// sink_it_(log_msg);
// }
// SPDLOG_CATCH_AND_HANDLE
//}
//template<typename... Args>
//inline void spdlog::logger::trace(const char *fmt, const Args &... args)
//{
// log(level::trace, fmt, args...);
//}
//
//template<typename... Args>
//inline void spdlog::logger::debug(const char *fmt, const Args &... args)
//{
// log(level::debug, fmt, args...);
//}
//
//template<typename... Args>
//inline void spdlog::logger::info(const char *fmt, const Args &... args)
//{
// log(level::info, fmt, args...);
//}
//
//template<typename... Args>
//inline void spdlog::logger::warn(const char *fmt, const Args &... args)
//{
// log(level::warn, fmt, args...);
//}
//
//template<typename... Args>
//inline void spdlog::logger::error(const char *fmt, const Args &... args)
//{
// log(level::err, fmt, args...);
//}
//
//template<typename... Args>
//inline void spdlog::logger::critical(const char *fmt, const Args &... args)
//{
// log(level::critical, fmt, args...);
//}
//
//template<typename T>
//inline void spdlog::logger::trace(const T &msg)
//{
// log(level::trace, msg);
//}
//
//template<typename T>
//inline void spdlog::logger::debug(const T &msg)
//{
// log(level::debug, msg);
//}
//
//template<typename T>
//inline void spdlog::logger::info(const T &msg)
//{
// log(level::info, msg);
//}
//
//template<typename T>
//inline void spdlog::logger::warn(const T &msg)
//{
// log(level::warn, msg);
//}
//
//template<typename T>
//inline void spdlog::logger::error(const T &msg)
//{
// log(level::err, msg);
//}
//
//template<typename T>
//inline void spdlog::logger::critical(const T &msg)
//{
// log(level::critical, msg);
//}
//#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
//inline void wbuf_to_utf8buf(const fmt::wmemory_buffer &wbuf, fmt::memory_buffer &target)
//{
// int wbuf_size = static_cast<int>(wbuf.size());
// if (wbuf_size == 0)
// {
// return;
// }
//
// auto result_size = ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, NULL, 0, NULL, NULL);
//
// if (result_size > 0)
// {
// target.resize(result_size);
// ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, &target.data()[0], result_size, NULL, NULL);
// }
// else
// {
// throw spdlog::spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError()));
// }
//}
//template<typename... Args>
//inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const wchar_t *fmt, const Args &... args)
//{
// if (!should_log(lvl))
// {
// return;
// }
//
// try
// {
// // format to wmemory_buffer and convert to utf8
// using details::fmt_helper::to_string_view;
// fmt::wmemory_buffer wbuf;
// fmt::format_to(wbuf, fmt, args...);
// fmt::memory_buffer buf;
// wbuf_to_utf8buf(wbuf, buf);
// details::log_msg log_msg(source, &name_, lvl, to_string_view(buf));
// sink_it_(log_msg);
// }
// SPDLOG_CATCH_AND_HANDLE
//}
//template<typename... Args>
//inline void spdlog::logger::log(level::level_enum lvl, const wchar_t *fmt, const Args &... args)
//{
// log(source_loc{}, lvl, fmt, args...);
//}
//
//template<typename... Args>
//inline void spdlog::logger::trace(const wchar_t *fmt, const Args &... args)
//{
// log(level::trace, fmt, args...);
//}
//
//template<typename... Args>
//inline void spdlog::logger::debug(const wchar_t *fmt, const Args &... args)
//{
// log(level::debug, fmt, args...);
//}
//
//template<typename... Args>
//inline void spdlog::logger::info(const wchar_t *fmt, const Args &... args)
//{
// log(level::info, fmt, args...);
//}
//
//template<typename... Args>
//inline void spdlog::logger::warn(const wchar_t *fmt, const Args &... args)
//{
// log(level::warn, fmt, args...);
//}
//
//template<typename... Args>
//inline void spdlog::logger::error(const wchar_t *fmt, const Args &... args)
//{
// log(level::err, fmt, args...);
//}
//
//template<typename... Args>
//inline void spdlog::logger::critical(const wchar_t *fmt, const Args &... args)
//{
// log(level::critical, fmt, args...);
//}
//
//#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
//
// name and level
//
//inline const std::string &spdlog::logger::name() const
//{
// return name_;
//}
//inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
//{
// level_.store(log_level);
//}
//inline void spdlog::logger::set_error_handler(spdlog::log_err_handler err_handler)
//{
// err_handler_ = std::move(err_handler);
//}
//inline spdlog::log_err_handler spdlog::logger::error_handler() const
//{
// return err_handler_;
//}
//inline void spdlog::logger::flush()
//{
// try
// {
// flush_();
// }
// SPDLOG_CATCH_AND_HANDLE
//}
//inline void spdlog::logger::flush_on(level::level_enum log_level)
//{
// flush_level_.store(log_level);
//}
//
//inline spdlog::level::level_enum spdlog::logger::flush_level() const
//{
// return static_cast<spdlog::level::level_enum>(flush_level_.load(std::memory_order_relaxed));
//}
//
//inline bool spdlog::logger::should_flush_(const details::log_msg &msg)
//{
// auto flush_level = flush_level_.load(std::memory_order_relaxed);
// return (msg.level >= flush_level) && (msg.level != level::off);
//}
//inline spdlog::level::level_enum spdlog::logger::default_level()
//{
// return static_cast<spdlog::level::level_enum>(SPDLOG_ACTIVE_LEVEL);
//}
//inline spdlog::level::level_enum spdlog::logger::level() const
//{
// return static_cast<spdlog::level::level_enum>(level_.load(std::memory_order_relaxed));
//}
//inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const
//{
// return msg_level >= level_.load(std::memory_order_relaxed);
//}
//
// protected virtual called at end of each user log call (if enabled) by the
// line_logger
//
//inline void spdlog::logger::sink_it_(details::log_msg &msg)
//{
//#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
// incr_msg_counter_(msg);
//#endif
// for (auto &sink : sinks_)
// {
// if (sink->should_log(msg.level))
// {
// sink->log(msg);
// }
// }
//
// if (should_flush_(msg))
// {
// flush_();
// }
//}
//inline void spdlog::logger::flush_()
//{
// for (auto &sink : sinks_)
// {
// sink->flush();
// }
//}
//inline void spdlog::logger::default_err_handler_(const std::string &msg)
//{
// auto now = time(nullptr);
// if (now - last_err_time_ < 60)
// {
// return;
// }
// last_err_time_ = now;
// auto tm_time = details::os::localtime(now);
// char date_buf[100];
// std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time);
// fmt::print(stderr, "[*** LOG ERROR ***] [{}] [{}] {}\n", date_buf, name(), msg);
//}
//inline void spdlog::logger::incr_msg_counter_(details::log_msg &msg)
//{
// msg.msg_id = msg_counter_.fetch_add(1, std::memory_order_relaxed);
//}
//
//inline const std::vector<spdlog::sink_ptr> &spdlog::logger::sinks() const
//{
// return sinks_;
//}
//inline std::vector<spdlog::sink_ptr> &spdlog::logger::sinks()
//{
// return sinks_;
//}
//inline std::shared_ptr<spdlog::logger> spdlog::logger::clone(std::string logger_name)
//{
// auto cloned = std::make_shared<spdlog::logger>(std::move(logger_name), sinks_.begin(), sinks_.end());
// cloned->set_level(this->level());
// cloned->flush_on(this->flush_level());
// cloned->set_error_handler(this->error_handler());
// return cloned;
//}
include/spdlog/details/os.h
View file @
e2e3df90
...
@@ -18,95 +18,19 @@
...
@@ -18,95 +18,19 @@
#include <sys/types.h>
#include <sys/types.h>
#include <thread>
#include <thread>
#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX // prevent windows redefining min/max
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <io.h> // _get_osfhandle and _isatty support
#include <process.h> // _get_pid support
#include <windows.h>
#ifdef __MINGW32__
#include <share.h>
#endif
#else // unix
#include <fcntl.h>
#include <unistd.h>
#ifdef __linux__
#include <sys/syscall.h> //Use gettid() syscall under linux to get thread id
#elif __FreeBSD__
#include <sys/thr.h> //Use thr_self() syscall under FreeBSD to get thread id
#endif
#endif // unix
#ifndef __has_feature // Clang - feature checking macros.
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
#endif
namespace
spdlog
{
namespace
spdlog
{
namespace
details
{
namespace
details
{
namespace
os
{
namespace
os
{
inline
spdlog
::
log_clock
::
time_point
now
()
SPDLOG_NOEXCEPT
spdlog
::
log_clock
::
time_point
now
()
SPDLOG_NOEXCEPT
;
{
#if defined __linux__ && defined SPDLOG_CLOCK_COARSE
timespec
ts
;
::
clock_gettime
(
CLOCK_REALTIME_COARSE
,
&
ts
);
return
std
::
chrono
::
time_point
<
log_clock
,
typename
log_clock
::
duration
>
(
std
::
chrono
::
duration_cast
<
typename
log_clock
::
duration
>
(
std
::
chrono
::
seconds
(
ts
.
tv_sec
)
+
std
::
chrono
::
nanoseconds
(
ts
.
tv_nsec
)));
#else
return
log_clock
::
now
();
#endif
}
inline
std
::
tm
localtime
(
const
std
::
time_t
&
time_tt
)
SPDLOG_NOEXCEPT
{
#ifdef _WIN32
std
::
tm
tm
;
localtime_s
(
&
tm
,
&
time_tt
);
#else
std
::
tm
tm
;
localtime_r
(
&
time_tt
,
&
tm
);
#endif
return
tm
;
}
inline
std
::
tm
localtime
()
SPDLOG_NOEXCEPT
std
::
tm
localtime
(
const
std
::
time_t
&
time_tt
)
SPDLOG_NOEXCEPT
;
{
std
::
time_t
now_t
=
time
(
nullptr
);
return
localtime
(
now_t
);
}
inline
std
::
tm
gmtime
(
const
std
::
time_t
&
time_tt
)
SPDLOG_NOEXCEPT
std
::
tm
localtime
()
SPDLOG_NOEXCEPT
;
{
#ifdef _WIN32
std
::
tm
gmtime
(
const
std
::
time_t
&
time_tt
)
SPDLOG_NOEXCEPT
;
std
::
tm
tm
;
gmtime_s
(
&
tm
,
&
time_tt
);
#else
std
::
tm
tm
;
gmtime_r
(
&
time_tt
,
&
tm
);
#endif
return
tm
;
}
inline
std
::
tm
gmtime
()
SPDLOG_NOEXCEPT
std
::
tm
gmtime
()
SPDLOG_NOEXCEPT
;
{
std
::
time_t
now_t
=
time
(
nullptr
);
return
gmtime
(
now_t
);
}
// eol definition
// eol definition
#if !defined(SPDLOG_EOL)
#if !defined(SPDLOG_EOL)
...
@@ -121,301 +45,56 @@ SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL;
...
@@ -121,301 +45,56 @@ SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL;
// folder separator
// folder separator
#ifdef _WIN32
#ifdef _WIN32
SPDLOG_CONSTEXPR
static
const
char
folder_sep
=
'\\'
;
const
char
folder_sep
=
'\\'
;
#else
#else
SPDLOG_CONSTEXPR
static
const
char
folder_sep
=
'/'
;
SPDLOG_CONSTEXPR
static
const
char
folder_sep
=
'/'
;
#endif
#endif
inline
void
prevent_child_fd
(
FILE
*
f
)
void
prevent_child_fd
(
FILE
*
f
);
{
#ifdef _WIN32
#if !defined(__cplusplus_winrt)
auto
file_handle
=
(
HANDLE
)
_get_osfhandle
(
_fileno
(
f
));
if
(
!::
SetHandleInformation
(
file_handle
,
HANDLE_FLAG_INHERIT
,
0
))
throw
spdlog_ex
(
"SetHandleInformation failed"
,
errno
);
#endif
#else
auto
fd
=
fileno
(
f
);
if
(
fcntl
(
fd
,
F_SETFD
,
FD_CLOEXEC
)
==
-
1
)
{
throw
spdlog_ex
(
"fcntl with FD_CLOEXEC failed"
,
errno
);
}
#endif
}
// fopen_s on non windows for writing
// fopen_s on non windows for writing
inline
bool
fopen_s
(
FILE
**
fp
,
const
filename_t
&
filename
,
const
filename_t
&
mode
)
bool
fopen_s
(
FILE
**
fp
,
const
filename_t
&
filename
,
const
filename_t
&
mode
);
{
#ifdef _WIN32
#ifdef SPDLOG_WCHAR_FILENAMES
*
fp
=
_wfsopen
((
filename
.
c_str
()),
mode
.
c_str
(),
_SH_DENYNO
);
#else
*
fp
=
_fsopen
((
filename
.
c_str
()),
mode
.
c_str
(),
_SH_DENYNO
);
#endif
#else // unix
*
fp
=
fopen
((
filename
.
c_str
()),
mode
.
c_str
());
#endif
#ifdef SPDLOG_PREVENT_CHILD_FD
int
remove
(
const
filename_t
&
filename
)
SPDLOG_NOEXCEPT
;
if
(
*
fp
!=
nullptr
)
{
prevent_child_fd
(
*
fp
);
}
#endif
return
*
fp
==
nullptr
;
}
inline
int
remove
(
const
filename_t
&
filename
)
SPDLOG_NOEXCEPT
int
rename
(
const
filename_t
&
filename1
,
const
filename_t
&
filename2
)
SPDLOG_NOEXCEPT
;
{
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
return
_wremove
(
filename
.
c_str
());
#else
return
std
::
remove
(
filename
.
c_str
());
#endif
}
inline
int
rename
(
const
filename_t
&
filename1
,
const
filename_t
&
filename2
)
SPDLOG_NOEXCEPT
{
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
return
_wrename
(
filename1
.
c_str
(),
filename2
.
c_str
());
#else
return
std
::
rename
(
filename1
.
c_str
(),
filename2
.
c_str
());
#endif
}
// Return if file exists
// Return if file exists
inline
bool
file_exists
(
const
filename_t
&
filename
)
SPDLOG_NOEXCEPT
bool
file_exists
(
const
filename_t
&
filename
)
SPDLOG_NOEXCEPT
;
{
#ifdef _WIN32
#ifdef SPDLOG_WCHAR_FILENAMES
auto
attribs
=
GetFileAttributesW
(
filename
.
c_str
());
#else
auto
attribs
=
GetFileAttributesA
(
filename
.
c_str
());
#endif
return
(
attribs
!=
INVALID_FILE_ATTRIBUTES
&&
!
(
attribs
&
FILE_ATTRIBUTE_DIRECTORY
));
#else // common linux/unix all have the stat system call
struct
stat
buffer
;
return
(
stat
(
filename
.
c_str
(),
&
buffer
)
==
0
);
#endif
}
// Return file size according to open FILE* object
// Return file size according to open FILE* object
inline
size_t
filesize
(
FILE
*
f
)
size_t
filesize
(
FILE
*
f
);
{
if
(
f
==
nullptr
)
{
throw
spdlog_ex
(
"Failed getting file size. fd is null"
);
}
#if defined(_WIN32) && !defined(__CYGWIN__)
int
fd
=
_fileno
(
f
);
#if _WIN64 // 64 bits
__int64
ret
=
_filelengthi64
(
fd
);
if
(
ret
>=
0
)
{
return
static_cast
<
size_t
>
(
ret
);
}
#else // windows 32 bits
long
ret
=
_filelength
(
fd
);
if
(
ret
>=
0
)
{
return
static_cast
<
size_t
>
(
ret
);
}
#endif
#else // unix
int
fd
=
fileno
(
f
);
// 64 bits(but not in osx or cygwin, where fstat64 is deprecated)
#if !defined(__FreeBSD__) && !defined(__APPLE__) && (defined(__x86_64__) || defined(__ppc64__)) && !defined(__CYGWIN__)
struct
stat64
st
;
if
(
fstat64
(
fd
,
&
st
)
==
0
)
{
return
static_cast
<
size_t
>
(
st
.
st_size
);
}
#else // unix 32 bits or cygwin
struct
stat
st
;
if
(
fstat
(
fd
,
&
st
)
==
0
)
{
return
static_cast
<
size_t
>
(
st
.
st_size
);
}
#endif
#endif
throw
spdlog_ex
(
"Failed getting file size from fd"
,
errno
);
}
// Return utc offset in minutes or throw spdlog_ex on failure
// Return utc offset in minutes or throw spdlog_ex on failure
inline
int
utc_minutes_offset
(
const
std
::
tm
&
tm
=
details
::
os
::
localtime
())
int
utc_minutes_offset
(
const
std
::
tm
&
tm
=
details
::
os
::
localtime
());
{
#ifdef _WIN32
#if _WIN32_WINNT < _WIN32_WINNT_WS08
TIME_ZONE_INFORMATION
tzinfo
;
auto
rv
=
GetTimeZoneInformation
(
&
tzinfo
);
#else
DYNAMIC_TIME_ZONE_INFORMATION
tzinfo
;
auto
rv
=
GetDynamicTimeZoneInformation
(
&
tzinfo
);
#endif
if
(
rv
==
TIME_ZONE_ID_INVALID
)
throw
spdlog
::
spdlog_ex
(
"Failed getting timezone info. "
,
errno
);
int
offset
=
-
tzinfo
.
Bias
;
if
(
tm
.
tm_isdst
)
{
offset
-=
tzinfo
.
DaylightBias
;
}
else
{
offset
-=
tzinfo
.
StandardBias
;
}
return
offset
;
#else
#if defined(sun) || defined(__sun) || defined(_AIX)
// 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris
struct
helper
{
static
long
int
calculate_gmt_offset
(
const
std
::
tm
&
localtm
=
details
::
os
::
localtime
(),
const
std
::
tm
&
gmtm
=
details
::
os
::
gmtime
())
{
int
local_year
=
localtm
.
tm_year
+
(
1900
-
1
);
int
gmt_year
=
gmtm
.
tm_year
+
(
1900
-
1
);
long
int
days
=
(
// difference in day of year
localtm
.
tm_yday
-
gmtm
.
tm_yday
// + intervening leap days
+
((
local_year
>>
2
)
-
(
gmt_year
>>
2
))
-
(
local_year
/
100
-
gmt_year
/
100
)
+
((
local_year
/
100
>>
2
)
-
(
gmt_year
/
100
>>
2
))
// + difference in years * 365 */
+
(
long
int
)(
local_year
-
gmt_year
)
*
365
);
long
int
hours
=
(
24
*
days
)
+
(
localtm
.
tm_hour
-
gmtm
.
tm_hour
);
long
int
mins
=
(
60
*
hours
)
+
(
localtm
.
tm_min
-
gmtm
.
tm_min
);
long
int
secs
=
(
60
*
mins
)
+
(
localtm
.
tm_sec
-
gmtm
.
tm_sec
);
return
secs
;
}
};
auto
offset_seconds
=
helper
::
calculate_gmt_offset
(
tm
);
#else
auto
offset_seconds
=
tm
.
tm_gmtoff
;
#endif
return
static_cast
<
int
>
(
offset_seconds
/
60
);
#endif
}
// Return current thread id as size_t
// Return current thread id as size_t
// It exists because the std::this_thread::get_id() is much slower(especially
// It exists because the std::this_thread::get_id() is much slower(especially
// under VS 2013)
// under VS 2013)
inline
size_t
_thread_id
()
SPDLOG_NOEXCEPT
size_t
_thread_id
()
SPDLOG_NOEXCEPT
;
{
#ifdef _WIN32
return
static_cast
<
size_t
>
(
::
GetCurrentThreadId
());
#elif __linux__
#if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21)
#define SYS_gettid __NR_gettid
#endif
return
static_cast
<
size_t
>
(
syscall
(
SYS_gettid
));
#elif __FreeBSD__
long
tid
;
thr_self
(
&
tid
);
return
static_cast
<
size_t
>
(
tid
);
#elif __APPLE__
uint64_t
tid
;
pthread_threadid_np
(
nullptr
,
&
tid
);
return
static_cast
<
size_t
>
(
tid
);
#else // Default to standard C++11 (other Unix)
return
static_cast
<
size_t
>
(
std
::
hash
<
std
::
thread
::
id
>
()(
std
::
this_thread
::
get_id
()));
#endif
}
// Return current thread id as size_t (from thread local storage)
// Return current thread id as size_t (from thread local storage)
inline
size_t
thread_id
()
SPDLOG_NOEXCEPT
size_t
thread_id
()
SPDLOG_NOEXCEPT
;
{
#if defined(SPDLOG_NO_TLS)
return
_thread_id
();
#else // cache thread id in tls
static
thread_local
const
size_t
tid
=
_thread_id
();
return
tid
;
#endif
}
// This is avoid msvc issue in sleep_for that happens if the clock changes.
// This is avoid msvc issue in sleep_for that happens if the clock changes.
// See https://github.com/gabime/spdlog/issues/609
// See https://github.com/gabime/spdlog/issues/609
inline
void
sleep_for_millis
(
int
milliseconds
)
SPDLOG_NOEXCEPT
void
sleep_for_millis
(
int
milliseconds
)
SPDLOG_NOEXCEPT
;
{
#if defined(_WIN32)
::
Sleep
(
milliseconds
);
#else
std
::
this_thread
::
sleep_for
(
std
::
chrono
::
milliseconds
(
milliseconds
));
#endif
}
// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined)
std
::
string
filename_to_str
(
const
filename_t
&
filename
);
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
#define SPDLOG_FILENAME_T(s) L##s
inline
std
::
string
filename_to_str
(
const
filename_t
&
filename
)
{
std
::
wstring_convert
<
std
::
codecvt_utf8
<
wchar_t
>
,
wchar_t
>
c
;
return
c
.
to_bytes
(
filename
);
}
#else
#define SPDLOG_FILENAME_T(s) s
inline
std
::
string
filename_to_str
(
const
filename_t
&
filename
)
{
return
filename
;
}
#endif
inline
int
pid
()
{
#ifdef _WIN32
int
pid
();
return
static_cast
<
int
>
(
::
GetCurrentProcessId
());
#else
return
static_cast
<
int
>
(
::
getpid
());
#endif
}
// Determine if the terminal supports colors
// Determine if the terminal supports colors
// Source: https://github.com/agauniyal/rang/
// Source: https://github.com/agauniyal/rang/
inline
bool
is_color_terminal
()
SPDLOG_NOEXCEPT
bool
is_color_terminal
()
SPDLOG_NOEXCEPT
;
{
#ifdef _WIN32
return
true
;
#else
static
constexpr
const
char
*
Terms
[]
=
{
"ansi"
,
"color"
,
"console"
,
"cygwin"
,
"gnome"
,
"konsole"
,
"kterm"
,
"linux"
,
"msys"
,
"putty"
,
"rxvt"
,
"screen"
,
"vt100"
,
"xterm"
};
const
char
*
env_p
=
std
::
getenv
(
"TERM"
);
if
(
env_p
==
nullptr
)
{
return
false
;
}
static
const
bool
result
=
std
::
any_of
(
std
::
begin
(
Terms
),
std
::
end
(
Terms
),
[
&
](
const
char
*
term
)
{
return
std
::
strstr
(
env_p
,
term
)
!=
nullptr
;
});
return
result
;
#endif
}
// Detrmine if the terminal attached
// Detrmine if the terminal attached
// Source: https://github.com/agauniyal/rang/
// Source: https://github.com/agauniyal/rang/
inline
bool
in_terminal
(
FILE
*
file
)
SPDLOG_NOEXCEPT
bool
in_terminal
(
FILE
*
file
)
SPDLOG_NOEXCEPT
;
{
#ifdef _WIN32
return
_isatty
(
_fileno
(
file
))
!=
0
;
#else
return
isatty
(
fileno
(
file
))
!=
0
;
#endif
}
}
// namespace os
}
// namespace os
}
// namespace details
}
// namespace details
}
// namespace spdlog
}
// namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
#include "../src/os.cpp"
#endif
include/spdlog/details/pattern_formatter.h
View file @
e2e3df90
...
@@ -4,7 +4,6 @@
...
@@ -4,7 +4,6 @@
//
//
#pragma once
#pragma once
#include "spdlog/details/fmt_helper.h"
#include "spdlog/details/fmt_helper.h"
#include "spdlog/details/log_msg.h"
#include "spdlog/details/log_msg.h"
#include "spdlog/details/os.h"
#include "spdlog/details/os.h"
...
...
include/spdlog/details/registry.h
View file @
e2e3df90
...
@@ -13,6 +13,7 @@
...
@@ -13,6 +13,7 @@
#include "spdlog/common.h"
#include "spdlog/common.h"
#include "spdlog/details/periodic_worker.h"
#include "spdlog/details/periodic_worker.h"
#include "spdlog/logger.h"
#include "spdlog/logger.h"
#include "spdlog/details/pattern_formatter.h"
#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER
#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER
// support for the default stdout color logger
// support for the default stdout color logger
...
...
include/spdlog/logger.h
View file @
e2e3df90
...
@@ -15,469 +15,353 @@
...
@@ -15,469 +15,353 @@
// and send to its destination.
// and send to its destination.
//
//
// The use of private formatter per sink provides the opportunity to cache some
// The use of private formatter per sink provides the opportunity to cache some
// formatted data,
// formatted data,
and support for different format per sink.
// and support customize format per each sink.
#include "spdlog/common.h"
#include "spdlog/common.h"
#include "spdlog/formatter.h"
#include "spdlog/details/log_msg.h"
#include "spdlog/sinks/sink.h"
#include "spdlog/details/fmt_helper.h"
//#include "spdlog/formatter.h"
//#include "spdlog/sinks/sink.h"
#include <memory>
#include <memory>
#include <string>
#include <string>
#include <vector>
#include <vector>
#ifndef SPDLOG_CATCH_AND_HANDLE
namespace
spdlog
#define SPDLOG_CATCH_AND_HANDLE \
catch (const std::exception &ex) \
{ \
err_handler_(ex.what()); \
} \
catch (...) \
{ \
err_handler_("Unknown exception in logger"); \
}
#endif // ! SPDLOG_CATCH_AND_HANDLE
namespace
spdlog
{
class
logger
{
{
public
:
class
logger
{
template
<
typename
It
>
public
:
logger
(
std
::
string
name
,
It
begin
,
It
end
)
template
<
typename
It
>
:
name_
(
std
::
move
(
name
))
logger
(
std
::
string
name
,
It
begin
,
It
end
)
,
sinks_
(
begin
,
end
)
:
name_
(
std
::
move
(
name
))
{}
,
sinks_
(
begin
,
end
)
logger
(
std
::
string
name
,
sink_ptr
single_sink
)
:
logger
(
std
::
move
(
name
),
{
std
::
move
(
single_sink
)})
{}
logger
(
std
::
string
name
,
sinks_init_list
sinks
)
:
logger
(
std
::
move
(
name
),
sinks
.
begin
(),
sinks
.
end
())
{}
virtual
~
logger
()
=
default
;
logger
(
const
logger
&
)
=
delete
;
logger
&
operator
=
(
const
logger
&
)
=
delete
;
template
<
typename
...
Args
>
void
log
(
source_loc
loc
,
level
::
level_enum
lvl
,
const
char
*
fmt
,
const
Args
&
...
args
)
{
if
(
!
should_log
(
lvl
))
{
return
;
}
try
{
{
using
details
::
fmt_helper
::
to_string_view
;
fmt
::
memory_buffer
buf
;
fmt
::
format_to
(
buf
,
fmt
,
args
...);
details
::
log_msg
log_msg
(
loc
,
&
name_
,
lvl
,
to_string_view
(
buf
));
sink_it_
(
log_msg
);
}
}
SPDLOG_CATCH_AND_HANDLE
}
template
<
typename
...
Args
>
void
log
(
level
::
level_enum
lvl
,
const
char
*
fmt
,
const
Args
&
...
args
)
{
log
(
source_loc
{},
lvl
,
fmt
,
args
...);
}
logger
(
std
::
string
name
,
sink_ptr
single_sink
)
void
log
(
source_loc
loc
,
level
::
level_enum
lvl
,
const
char
*
msg
)
:
logger
(
std
::
move
(
name
),
{
std
::
move
(
single_sink
)})
{
if
(
!
should_log
(
lvl
))
{
{
return
;
}
}
logger
(
std
::
string
name
,
sinks_init_list
sinks
)
try
:
logger
(
std
::
move
(
name
),
sinks
.
begin
(),
sinks
.
end
())
{
{
details
::
log_msg
log_msg
(
loc
,
&
name_
,
lvl
,
spdlog
::
string_view_t
(
msg
));
sink_it_
(
log_msg
);
}
}
SPDLOG_CATCH_AND_HANDLE
}
void
log
(
level
::
level_enum
lvl
,
const
char
*
msg
)
virtual
~
logger
()
=
default
;
{
log
(
source_loc
{},
lvl
,
msg
);
}
logger
(
const
logger
&
)
=
delete
;
logger
&
operator
=
(
const
logger
&
)
=
delete
;
template
<
typename
...
Args
>
template
<
typename
...
Args
>
void
trace
(
const
char
*
fmt
,
const
Args
&
...
args
)
void
log
(
source_loc
loc
,
level
::
level_enum
lvl
,
const
char
*
fmt
,
const
Args
&
...
args
)
{
{
log
(
level
::
trace
,
fmt
,
args
...);
if
(
!
should_log
(
lvl
))
}
{
return
;
}
try
{
fmt
::
memory_buffer
buf
;
fmt
::
format_to
(
buf
,
fmt
,
args
...);
details
::
log_msg
log_msg
(
loc
,
&
name_
,
lvl
,
string_view_t
(
buf
.
data
(),
buf
.
size
()));
sink_it_
(
log_msg
);
}
catch
(
const
std
::
exception
&
ex
)
{
err_handler_
(
ex
.
what
());
}
catch
(...)
{
err_handler_
(
"Unknown exception in logger"
);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
void
debug
(
const
char
*
fmt
,
const
Args
&
...
args
)
void
log
(
level
::
level_enum
lvl
,
const
char
*
fmt
,
const
Args
&
...
args
)
{
{
log
(
level
::
debug
,
fmt
,
args
...);
log
(
source_loc
{},
lvl
,
fmt
,
args
...);
}
}
void
log
(
source_loc
loc
,
level
::
level_enum
lvl
,
const
char
*
msg
);
void
log
(
level
::
level_enum
lvl
,
const
char
*
msg
);
template
<
typename
...
Args
>
void
trace
(
const
char
*
fmt
,
const
Args
&
...
args
)
{
log
(
level
::
trace
,
fmt
,
args
...);
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
void
info
(
const
char
*
fmt
,
const
Args
&
...
args
)
void
debug
(
const
char
*
fmt
,
const
Args
&
...
args
)
{
{
log
(
level
::
info
,
fmt
,
args
...);
log
(
level
::
debug
,
fmt
,
args
...);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
void
warn
(
const
char
*
fmt
,
const
Args
&
...
args
)
void
info
(
const
char
*
fmt
,
const
Args
&
...
args
)
{
{
log
(
level
::
warn
,
fmt
,
args
...);
log
(
level
::
info
,
fmt
,
args
...);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
void
error
(
const
char
*
fmt
,
const
Args
&
...
args
)
void
warn
(
const
char
*
fmt
,
const
Args
&
...
args
)
{
{
log
(
level
::
err
,
fmt
,
args
...);
log
(
level
::
warn
,
fmt
,
args
...);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
void
critical
(
const
char
*
fmt
,
const
Args
&
...
args
)
void
error
(
const
char
*
fmt
,
const
Args
&
...
args
)
{
{
log
(
level
::
critical
,
fmt
,
args
...);
log
(
level
::
err
,
fmt
,
args
...);
}
}
template
<
typename
...
Args
>
void
critical
(
const
char
*
fmt
,
const
Args
&
...
args
)
{
log
(
level
::
critical
,
fmt
,
args
...);
}
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
#ifndef _WIN32
#ifndef _WIN32
#error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows
#error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows
#else
#else
inline
void
wbuf_to_utf8buf
(
const
fmt
::
wmemory_buffer
&
wbuf
,
fmt
::
memory_buffer
&
target
)
inline
void
wbuf_to_utf8buf
(
const
fmt
::
wmemory_buffer
&
wbuf
,
fmt
::
memory_buffer
&
target
)
{
int
wbuf_size
=
static_cast
<
int
>
(
wbuf
.
size
());
if
(
wbuf_size
==
0
)
{
{
return
;
int
wbuf_size
=
static_cast
<
int
>
(
wbuf
.
size
());
}
if
(
wbuf_size
==
0
)
{
return
;
}
auto
result_size
=
::
WideCharToMultiByte
(
CP_UTF8
,
0
,
wbuf
.
data
(),
wbuf_size
,
NULL
,
0
,
NULL
,
NULL
);
auto
result_size
=
::
WideCharToMultiByte
(
CP_UTF8
,
0
,
wbuf
.
data
(),
wbuf_size
,
NULL
,
0
,
NULL
,
NULL
);
if
(
result_size
>
0
)
if
(
result_size
>
0
)
{
{
target
.
resize
(
result_size
);
target
.
resize
(
result_size
);
::
WideCharToMultiByte
(
CP_UTF8
,
0
,
wbuf
.
data
(),
wbuf_size
,
&
target
.
data
()[
0
],
result_size
,
NULL
,
NULL
);
::
WideCharToMultiByte
(
CP_UTF8
,
0
,
wbuf
.
data
(),
wbuf_size
,
&
target
.
data
()[
0
],
result_size
,
NULL
,
NULL
);
}
else
{
throw
spdlog
::
spdlog_ex
(
fmt
::
format
(
"WideCharToMultiByte failed. Last error: {}"
,
::
GetLastError
()));
}
}
}
else
template
<
typename
...
Args
>
void
log
(
source_loc
source
,
level
::
level_enum
lvl
,
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
{
{
throw
spdlog
::
spdlog_ex
(
fmt
::
format
(
"WideCharToMultiByte failed. Last error: {}"
,
::
GetLastError
()));
if
(
!
should_log
(
lvl
))
{
return
;
}
try
{
// format to wmemory_buffer and convert to utf8
using
details
::
fmt_helper
::
to_string_view
;
fmt
::
wmemory_buffer
wbuf
;
fmt
::
format_to
(
wbuf
,
fmt
,
args
...);
fmt
::
memory_buffer
buf
;
wbuf_to_utf8buf
(
wbuf
,
buf
);
details
::
log_msg
log_msg
(
source
,
&
name_
,
lvl
,
to_string_view
(
buf
));
sink_it_
(
log_msg
);
}
SPDLOG_CATCH_AND_HANDLE
}
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
void
log
(
source_loc
source
,
level
::
level_enum
lvl
,
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
void
log
(
level
::
level_enum
lvl
,
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
{
if
(
!
should_log
(
lvl
))
{
{
return
;
log
(
source_loc
{},
lvl
,
fmt
,
args
...)
;
}
}
try
template
<
typename
...
Args
>
void
trace
(
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
{
{
// format to wmemory_buffer and convert to utf8
log
(
level
::
trace
,
fmt
,
args
...);
using
details
::
fmt_helper
::
to_string_view
;
fmt
::
wmemory_buffer
wbuf
;
fmt
::
format_to
(
wbuf
,
fmt
,
args
...);
fmt
::
memory_buffer
buf
;
wbuf_to_utf8buf
(
wbuf
,
buf
);
details
::
log_msg
log_msg
(
source
,
&
name_
,
lvl
,
to_string_view
(
buf
));
sink_it_
(
log_msg
);
}
}
SPDLOG_CATCH_AND_HANDLE
}
template
<
typename
...
Args
>
void
log
(
level
::
level_enum
lvl
,
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
{
log
(
source_loc
{},
lvl
,
fmt
,
args
...);
}
template
<
typename
...
Args
>
void
trace
(
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
{
log
(
level
::
trace
,
fmt
,
args
...);
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
void
debug
(
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
void
debug
(
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
{
{
log
(
level
::
debug
,
fmt
,
args
...);
log
(
level
::
debug
,
fmt
,
args
...);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
void
info
(
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
void
info
(
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
{
{
log
(
level
::
info
,
fmt
,
args
...);
log
(
level
::
info
,
fmt
,
args
...);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
void
warn
(
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
void
warn
(
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
{
{
log
(
level
::
warn
,
fmt
,
args
...);
log
(
level
::
warn
,
fmt
,
args
...);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
void
error
(
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
void
error
(
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
{
{
log
(
level
::
err
,
fmt
,
args
...);
log
(
level
::
err
,
fmt
,
args
...);
}
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
void
critical
(
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
void
critical
(
const
wchar_t
*
fmt
,
const
Args
&
...
args
)
{
{
log
(
level
::
critical
,
fmt
,
args
...);
log
(
level
::
critical
,
fmt
,
args
...);
}
}
#endif // _WIN32
#endif // _WIN32
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
template
<
typename
T
>
template
<
typename
T
>
void
log
(
level
::
level_enum
lvl
,
const
T
&
msg
)
void
log
(
level
::
level_enum
lvl
,
const
T
&
msg
)
{
log
(
source_loc
{},
lvl
,
msg
);
}
// T can be statically converted to string_view
template
<
class
T
,
typename
std
::
enable_if
<
std
::
is_convertible
<
T
,
spdlog
::
string_view_t
>::
value
,
T
>::
type
*
=
nullptr
>
void
log
(
source_loc
loc
,
level
::
level_enum
lvl
,
const
T
&
msg
)
{
if
(
!
should_log
(
lvl
))
{
{
return
;
log
(
source_loc
{},
lvl
,
msg
)
;
}
}
try
// T can be statically converted to string_view
template
<
class
T
,
typename
std
::
enable_if
<
std
::
is_convertible
<
T
,
spdlog
::
string_view_t
>::
value
,
T
>::
type
*
=
nullptr
>
void
log
(
source_loc
loc
,
level
::
level_enum
lvl
,
const
T
&
msg
)
{
{
details
::
log_msg
log_msg
(
loc
,
&
name_
,
lvl
,
msg
);
if
(
!
should_log
(
lvl
))
sink_it_
(
log_msg
);
{
return
;
}
try
{
details
::
log_msg
log_msg
(
loc
,
&
name_
,
lvl
,
msg
);
sink_it_
(
log_msg
);
}
catch
(
const
std
::
exception
&
ex
)
{
err_handler_
(
ex
.
what
());
}
catch
(...)
{
err_handler_
(
"Unknown exception in logger"
);
}
}
}
SPDLOG_CATCH_AND_HANDLE
}
// T cannot be statically converted to string_view
// T cannot be statically converted to string_view
template
<
class
T
,
typename
std
::
enable_if
<!
std
::
is_convertible
<
T
,
spdlog
::
string_view_t
>::
value
,
T
>::
type
*
=
nullptr
>
template
<
class
T
,
typename
std
::
enable_if
<!
std
::
is_convertible
<
T
,
spdlog
::
string_view_t
>::
value
,
T
>::
type
*
=
nullptr
>
void
log
(
source_loc
loc
,
level
::
level_enum
lvl
,
const
T
&
msg
)
void
log
(
source_loc
loc
,
level
::
level_enum
lvl
,
const
T
&
msg
)
{
if
(
!
should_log
(
lvl
))
{
{
return
;
if
(
!
should_log
(
lvl
))
{
return
;
}
try
{
using
details
::
fmt_helper
::
to_string_view
;
fmt
::
memory_buffer
buf
;
fmt
::
format_to
(
buf
,
"{}"
,
msg
);
details
::
log_msg
log_msg
(
loc
,
&
name_
,
lvl
,
to_string_view
(
buf
));
sink_it_
(
log_msg
);
}
catch
(
const
std
::
exception
&
ex
)
{
err_handler_
(
ex
.
what
());
}
catch
(...)
{
err_handler_
(
"Unknown exception in logger"
);
}
}
}
try
template
<
typename
T
>
void
trace
(
const
T
&
msg
)
{
{
using
details
::
fmt_helper
::
to_string_view
;
log
(
level
::
trace
,
msg
);
fmt
::
memory_buffer
buf
;
fmt
::
format_to
(
buf
,
"{}"
,
msg
);
details
::
log_msg
log_msg
(
loc
,
&
name_
,
lvl
,
to_string_view
(
buf
));
sink_it_
(
log_msg
);
}
}
SPDLOG_CATCH_AND_HANDLE
}
template
<
typename
T
>
void
trace
(
const
T
&
msg
)
{
log
(
level
::
trace
,
msg
);
}
template
<
typename
T
>
template
<
typename
T
>
void
debug
(
const
T
&
msg
)
void
debug
(
const
T
&
msg
)
{
{
log
(
level
::
debug
,
msg
);
log
(
level
::
debug
,
msg
);
}
}
template
<
typename
T
>
void
info
(
const
T
&
msg
)
{
log
(
level
::
info
,
msg
);
}
template
<
typename
T
>
void
warn
(
const
T
&
msg
)
{
log
(
level
::
warn
,
msg
);
}
template
<
typename
T
>
void
error
(
const
T
&
msg
)
{
log
(
level
::
err
,
msg
);
}
template
<
typename
T
>
template
<
typename
T
>
void
critical
(
const
T
&
msg
)
void
info
(
const
T
&
msg
)
{
{
log
(
level
::
critical
,
msg
);
log
(
level
::
info
,
msg
);
}
}
bool
should_log
(
level
::
level_enum
msg_level
)
const
template
<
typename
T
>
{
void
warn
(
const
T
&
msg
)
return
msg_level
>=
level_
.
load
(
std
::
memory_order_relaxed
);
{
}
log
(
level
::
warn
,
msg
);
}
void
set_level
(
level
::
level_enum
log_level
)
template
<
typename
T
>
{
void
error
(
const
T
&
msg
)
level_
.
store
(
log_level
);
{
}
log
(
level
::
err
,
msg
);
}
static
level
::
level_enum
default_level
()
template
<
typename
T
>
{
void
critical
(
const
T
&
msg
)
return
static_cast
<
spdlog
::
level
::
level_enum
>
(
SPDLOG_ACTIVE_LEVEL
);
{
}
log
(
level
::
critical
,
msg
);
}
level
::
level_enum
level
()
const
bool
should_log
(
level
::
level_enum
msg_level
)
const
;
{
return
static_cast
<
spdlog
::
level
::
level_enum
>
(
level_
.
load
(
std
::
memory_order_relaxed
));
}
const
std
::
string
&
name
()
const
void
set_level
(
level
::
level_enum
log_level
);
{
return
name_
;
}
// set formatting for the sinks in this logger.
static
level
::
level_enum
default_level
();
// each sink will get a seperate instance of the formatter object.
void
set_formatter
(
std
::
unique_ptr
<
formatter
>
f
)
{
for
(
auto
&
sink
:
sinks_
)
{
sink
->
set_formatter
(
f
->
clone
());
}
}
void
set_pattern
(
std
::
string
pattern
,
pattern_time_type
time_type
=
pattern_time_type
::
local
)
level
::
level_enum
level
()
const
;
{
auto
new_formatter
=
details
::
make_unique
<
spdlog
::
pattern_formatter
>
(
std
::
move
(
pattern
),
time_type
);
set_formatter
(
std
::
move
(
new_formatter
));
}
// flush functions
const
std
::
string
&
name
()
const
;
void
flush
()
{
try
{
flush_
();
}
SPDLOG_CATCH_AND_HANDLE
}
void
flush_on
(
level
::
level_enum
log_level
)
// set formatting for the sinks in this logger.
{
// each sink will get a seperate instance of the formatter object.
flush_level_
.
store
(
log_level
);
void
set_formatter
(
std
::
unique_ptr
<
formatter
>
f
);
}
level
::
level_enum
flush_level
()
const
void
set_pattern
(
std
::
string
pattern
,
pattern_time_type
time_type
=
pattern_time_type
::
local
);
{
return
static_cast
<
spdlog
::
level
::
level_enum
>
(
flush_level_
.
load
(
std
::
memory_order_relaxed
));
}
// sinks
// flush functions
const
std
::
vector
<
sink_ptr
>
&
sinks
()
const
void
flush
();
{
void
flush_on
(
level
::
level_enum
log_level
);
return
sinks_
;
level
::
level_enum
flush_level
()
const
;
}
std
::
vector
<
sink_ptr
>
&
sinks
()
// sinks
{
const
std
::
vector
<
sink_ptr
>
&
sinks
()
const
;
return
sinks_
;
}
// error handler
std
::
vector
<
sink_ptr
>
&
sinks
();
void
set_error_handler
(
log_err_handler
err_handler
)
{
err_handler_
=
std
::
move
(
err_handler
);
}
log_err_handler
error_handler
()
const
// error handler
{
void
set_error_handler
(
log_err_handler
err_handler
);
return
err_handler_
;
}
// create new logger with same sinks and configuration.
log_err_handler
error_handler
()
const
;
virtual
std
::
shared_ptr
<
logger
>
clone
(
std
::
string
logger_name
)
{
auto
cloned
=
std
::
make_shared
<
spdlog
::
logger
>
(
std
::
move
(
logger_name
),
sinks_
.
begin
(),
sinks_
.
end
());
cloned
->
set_level
(
this
->
level
());
cloned
->
flush_on
(
this
->
flush_level
());
cloned
->
set_error_handler
(
this
->
error_handler
());
return
cloned
;
}
// create new logger with same sinks and configuration.
virtual
std
::
shared_ptr
<
logger
>
clone
(
std
::
string
logger_name
);
protected
:
protected
:
virtual
void
sink_it_
(
details
::
log_msg
&
msg
)
virtual
void
sink_it_
(
details
::
log_msg
&
msg
);
{
#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
incr_msg_counter_
(
msg
);
#endif
for
(
auto
&
sink
:
sinks_
)
{
if
(
sink
->
should_log
(
msg
.
level
))
{
sink
->
log
(
msg
);
}
}
if
(
should_flush_
(
msg
))
virtual
void
flush_
();
{
bool
should_flush_
(
const
details
::
log_msg
&
msg
);
flush_
();
}
}
virtual
void
flush_
()
// default error handler.
{
// print the error to stderr with the max rate of 1 message/minute.
for
(
auto
&
sink
:
sinks_
)
void
default_err_handler_
(
const
std
::
string
&
msg
);
{
sink
->
flush
();
}
}
bool
should_flush_
(
const
details
::
log_msg
&
msg
)
// increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER))
{
void
incr_msg_counter_
(
details
::
log_msg
&
msg
);
auto
flush_level
=
flush_level_
.
load
(
std
::
memory_order_relaxed
);
return
(
msg
.
level
>=
flush_level
)
&&
(
msg
.
level
!=
level
::
off
);
}
// default error handler.
const
std
::
string
name_
;
// print the error to stderr with the max rate of 1 message/minute.
std
::
vector
<
sink_ptr
>
sinks_
;
void
default_err_handler_
(
const
std
::
string
&
msg
)
spdlog
::
level_t
level_
{
spdlog
::
logger
::
default_level
()};
{
spdlog
::
level_t
flush_level_
{
level
::
off
};
auto
now
=
time
(
nullptr
);
log_err_handler
err_handler_
{[
this
](
const
std
::
string
&
msg
)
{
this
->
default_err_handler_
(
msg
);
}};
if
(
now
-
last_err_time_
<
60
)
std
::
atomic
<
time_t
>
last_err_time_
{
0
};
{
std
::
atomic
<
size_t
>
msg_counter_
{
1
};
return
;
};
}
last_err_time_
=
now
;
auto
tm_time
=
details
::
os
::
localtime
(
now
);
char
date_buf
[
100
];
std
::
strftime
(
date_buf
,
sizeof
(
date_buf
),
"%Y-%m-%d %H:%M:%S"
,
&
tm_time
);
fmt
::
print
(
stderr
,
"[*** LOG ERROR ***] [{}] [{}] {}
\n
"
,
date_buf
,
name
(),
msg
);
}
// increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER))
void
incr_msg_counter_
(
details
::
log_msg
&
msg
)
{
msg
.
msg_id
=
msg_counter_
.
fetch_add
(
1
,
std
::
memory_order_relaxed
);
}
const
std
::
string
name_
;
std
::
vector
<
sink_ptr
>
sinks_
;
spdlog
::
level_t
level_
{
spdlog
::
logger
::
default_level
()};
spdlog
::
level_t
flush_level_
{
level
::
off
};
log_err_handler
err_handler_
{[
this
](
const
std
::
string
&
msg
)
{
this
->
default_err_handler_
(
msg
);
}};
std
::
atomic
<
time_t
>
last_err_time_
{
0
};
std
::
atomic
<
size_t
>
msg_counter_
{
1
};
};
}
// namespace spdlog
}
// namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
#include "../src/logger.cpp"
#endif // SPDLOG_HEADER_ONLY
include/spdlog/sinks/sink.h
View file @
e2e3df90
...
@@ -6,49 +6,41 @@
...
@@ -6,49 +6,41 @@
#pragma once
#pragma once
#include "spdlog/details/log_msg.h"
#include "spdlog/details/log_msg.h"
#include "spdlog/details/pattern_formatter.h"
//
#include "spdlog/details/pattern_formatter.h"
#include "spdlog/formatter.h"
#include "spdlog/formatter.h"
namespace
spdlog
{
namespace
spdlog
{
namespace
sinks
{
namespace
sinks
{
class
sink
class
sink
{
{
public
:
public
:
sink
()
=
default
;
sink
();
explicit
sink
(
std
::
unique_ptr
<
spdlog
::
formatter
>
formatter
)
:
formatter_
{
std
::
move
(
formatter
)}
{
}
explicit
sink
(
std
::
unique_ptr
<
spdlog
::
formatter
>
formatter
);
virtual
~
sink
()
=
default
;
virtual
~
sink
()
=
default
;
virtual
void
log
(
const
details
::
log_msg
&
msg
)
=
0
;
virtual
void
log
(
const
details
::
log_msg
&
msg
)
=
0
;
virtual
void
flush
()
=
0
;
virtual
void
flush
()
=
0
;
virtual
void
set_pattern
(
const
std
::
string
&
pattern
)
=
0
;
virtual
void
set_pattern
(
const
std
::
string
&
pattern
)
=
0
;
virtual
void
set_formatter
(
std
::
unique_ptr
<
spdlog
::
formatter
>
sink_formatter
)
=
0
;
virtual
void
set_formatter
(
std
::
unique_ptr
<
spdlog
::
formatter
>
sink_formatter
)
=
0
;
bool
should_log
(
level
::
level_enum
msg_level
)
const
bool
should_log
(
level
::
level_enum
msg_level
)
const
;
{
return
msg_level
>=
level_
.
load
(
std
::
memory_order_relaxed
);
void
set_level
(
level
::
level_enum
log_level
);
}
level
::
level_enum
level
()
const
;
void
set_level
(
level
::
level_enum
log_level
)
{
level_
.
store
(
log_level
);
}
level
::
level_enum
level
()
const
{
return
static_cast
<
spdlog
::
level
::
level_enum
>
(
level_
.
load
(
std
::
memory_order_relaxed
));
}
protected
:
protected
:
// sink log level - default is all
// sink log level - default is all
level_t
level_
{
level
::
trace
};
level_t
level_
{
level
::
trace
};
// sink formatter
- default is full format
// sink formatter
std
::
unique_ptr
<
spdlog
::
formatter
>
formatter_
{
details
::
make_unique
<
spdlog
::
pattern_formatter
>
()}
;
std
::
unique_ptr
<
spdlog
::
formatter
>
formatter_
;
};
};
}
// namespace sinks
}
// namespace sinks
}
// namespace spdlog
}
// namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
#include "../src/sink.cpp"
#endif // SPDLOG_HEADER_ONLY
src/log_msg.cpp
0 → 100644
View file @
e2e3df90
#include "spdlog/details/os.h"
#include "spdlog/sinks/sink.h"
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/details/log_msg.h"
#endif
SPDLOG_INLINE
spdlog
::
details
::
log_msg
::
log_msg
(
spdlog
::
source_loc
loc
,
const
std
::
string
*
loggers_name
,
spdlog
::
level
::
level_enum
lvl
,
spdlog
::
string_view_t
view
)
:
logger_name
(
loggers_name
)
,
level
(
lvl
)
#ifndef SPDLOG_NO_DATETIME
,
time
(
os
::
now
())
#endif
#ifndef SPDLOG_NO_THREAD_ID
,
thread_id
(
os
::
thread_id
())
#endif
,
source
(
loc
)
,
payload
(
view
)
{
}
SPDLOG_INLINE
spdlog
::
details
::
log_msg
::
log_msg
(
const
std
::
string
*
loggers_name
,
spdlog
::
level
::
level_enum
lvl
,
spdlog
::
string_view_t
view
)
:
log_msg
(
source_loc
{},
loggers_name
,
lvl
,
view
)
{
}
\ No newline at end of file
src/logger.cpp
0 → 100644
View file @
e2e3df90
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/logger.h"
#endif
#include "spdlog/sinks/sink.h"
#include "spdlog/details/pattern_formatter.h"
// public methods
SPDLOG_INLINE
void
spdlog
::
logger
::
log
(
spdlog
::
source_loc
loc
,
spdlog
::
level
::
level_enum
lvl
,
const
char
*
msg
)
{
if
(
!
should_log
(
lvl
))
{
return
;
}
try
{
details
::
log_msg
log_msg
(
loc
,
&
name_
,
lvl
,
spdlog
::
string_view_t
(
msg
));
sink_it_
(
log_msg
);
}
catch
(
const
std
::
exception
&
ex
)
{
err_handler_
(
ex
.
what
());
}
catch
(...)
{
err_handler_
(
"Unknown exception in logger"
);
}
}
SPDLOG_INLINE
void
spdlog
::
logger
::
log
(
level
::
level_enum
lvl
,
const
char
*
msg
)
{
log
(
source_loc
{},
lvl
,
msg
);
}
SPDLOG_INLINE
bool
spdlog
::
logger
::
should_log
(
spdlog
::
level
::
level_enum
msg_level
)
const
{
return
msg_level
>=
level_
.
load
(
std
::
memory_order_relaxed
);
}
SPDLOG_INLINE
void
spdlog
::
logger
::
set_level
(
spdlog
::
level
::
level_enum
log_level
)
{
level_
.
store
(
log_level
);
}
SPDLOG_INLINE
spdlog
::
level
::
level_enum
spdlog
::
logger
::
default_level
()
{
return
static_cast
<
spdlog
::
level
::
level_enum
>
(
SPDLOG_ACTIVE_LEVEL
);
}
SPDLOG_INLINE
spdlog
::
level
::
level_enum
spdlog
::
logger
::
level
()
const
{
return
static_cast
<
spdlog
::
level
::
level_enum
>
(
level_
.
load
(
std
::
memory_order_relaxed
));
}
SPDLOG_INLINE
const
std
::
string
&
spdlog
::
logger
::
name
()
const
{
return
name_
;
}
// set formatting for the sinks in this logger.
// each sink will get a seperate instance of the formatter object.
SPDLOG_INLINE
void
spdlog
::
logger
::
set_formatter
(
std
::
unique_ptr
<
spdlog
::
formatter
>
f
)
{
for
(
auto
&
sink
:
sinks_
)
{
sink
->
set_formatter
(
f
->
clone
());
}
}
SPDLOG_INLINE
void
spdlog
::
logger
::
set_pattern
(
std
::
string
pattern
,
spdlog
::
pattern_time_type
time_type
)
{
auto
new_formatter
=
details
::
make_unique
<
spdlog
::
pattern_formatter
>
(
std
::
move
(
pattern
),
time_type
);
set_formatter
(
std
::
move
(
new_formatter
));
}
// flush functions
SPDLOG_INLINE
void
spdlog
::
logger
::
flush
()
{
try
{
flush_
();
}
catch
(
const
std
::
exception
&
ex
)
{
err_handler_
(
ex
.
what
());
}
catch
(...)
{
err_handler_
(
"Unknown exception in logger"
);
}
}
SPDLOG_INLINE
void
spdlog
::
logger
::
flush_on
(
level
::
level_enum
log_level
)
{
flush_level_
.
store
(
log_level
);
}
SPDLOG_INLINE
spdlog
::
level
::
level_enum
spdlog
::
logger
::
flush_level
()
const
{
return
static_cast
<
spdlog
::
level
::
level_enum
>
(
flush_level_
.
load
(
std
::
memory_order_relaxed
));
}
// sinks
SPDLOG_INLINE
const
std
::
vector
<
spdlog
::
sink_ptr
>
&
spdlog
::
logger
::
sinks
()
const
{
return
sinks_
;
}
SPDLOG_INLINE
std
::
vector
<
spdlog
::
sink_ptr
>
&
spdlog
::
logger
::
sinks
()
{
return
sinks_
;
}
// error handler
SPDLOG_INLINE
void
spdlog
::
logger
::
set_error_handler
(
spdlog
::
log_err_handler
err_handler
)
{
err_handler_
=
std
::
move
(
err_handler
);
}
SPDLOG_INLINE
spdlog
::
log_err_handler
spdlog
::
logger
::
error_handler
()
const
{
return
err_handler_
;
}
// create new logger with same sinks and configuration.
SPDLOG_INLINE
std
::
shared_ptr
<
spdlog
::
logger
>
spdlog
::
logger
::
clone
(
std
::
string
logger_name
)
{
auto
cloned
=
std
::
make_shared
<
spdlog
::
logger
>
(
std
::
move
(
logger_name
),
sinks_
.
begin
(),
sinks_
.
end
());
cloned
->
set_level
(
this
->
level
());
cloned
->
flush_on
(
this
->
flush_level
());
cloned
->
set_error_handler
(
this
->
error_handler
());
return
cloned
;
}
// protected methods
SPDLOG_INLINE
void
spdlog
::
logger
::
sink_it_
(
spdlog
::
details
::
log_msg
&
msg
)
{
#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
incr_msg_counter_
(
msg
);
#endif
for
(
auto
&
sink
:
sinks_
)
{
if
(
sink
->
should_log
(
msg
.
level
))
{
sink
->
log
(
msg
);
}
}
if
(
should_flush_
(
msg
))
{
flush_
();
}
}
SPDLOG_INLINE
void
spdlog
::
logger
::
flush_
()
{
for
(
auto
&
sink
:
sinks_
)
{
sink
->
flush
();
}
}
SPDLOG_INLINE
bool
spdlog
::
logger
::
should_flush_
(
const
spdlog
::
details
::
log_msg
&
msg
)
{
auto
flush_level
=
flush_level_
.
load
(
std
::
memory_order_relaxed
);
return
(
msg
.
level
>=
flush_level
)
&&
(
msg
.
level
!=
level
::
off
);
}
SPDLOG_INLINE
void
spdlog
::
logger
::
default_err_handler_
(
const
std
::
string
&
msg
)
{
auto
now
=
time
(
nullptr
);
if
(
now
-
last_err_time_
<
60
)
{
return
;
}
last_err_time_
=
now
;
auto
tm_time
=
details
::
os
::
localtime
(
now
);
char
date_buf
[
100
];
std
::
strftime
(
date_buf
,
sizeof
(
date_buf
),
"%Y-%m-%d %H:%M:%S"
,
&
tm_time
);
fmt
::
print
(
stderr
,
"[*** LOG ERROR ***] [{}] [{}] {}
\n
"
,
date_buf
,
name
(),
msg
);
}
SPDLOG_INLINE
void
spdlog
::
logger
::
incr_msg_counter_
(
spdlog
::
details
::
log_msg
&
msg
)
{
msg
.
msg_id
=
msg_counter_
.
fetch_add
(
1
,
std
::
memory_order_relaxed
);
}
src/os.cpp
0 → 100644
View file @
e2e3df90
//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/details/os.h"
#include "spdlog/common.h"
#endif
#include <algorithm>
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <functional>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <thread>
#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX // prevent windows redefining min/max
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <io.h> // _get_osfhandle and _isatty support
#include <process.h> // _get_pid support
#include <windows.h>
#ifdef __MINGW32__
#include <share.h>
#endif
#else // unix
#include <fcntl.h>
#include <unistd.h>
#ifdef __linux__
#include <sys/syscall.h> //Use gettid() syscall under linux to get thread id
#elif __FreeBSD__
#include <sys/thr.h> //Use thr_self() syscall under FreeBSD to get thread id
#endif
#endif // unix
#ifndef __has_feature // Clang - feature checking macros.
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
#endif
namespace
spdlog
{
namespace
details
{
namespace
os
{
SPDLOG_INLINE
spdlog
::
log_clock
::
time_point
now
()
SPDLOG_NOEXCEPT
{
#if defined __linux__ && defined SPDLOG_CLOCK_COARSE
timespec
ts
;
::
clock_gettime
(
CLOCK_REALTIME_COARSE
,
&
ts
);
return
std
::
chrono
::
time_point
<
log_clock
,
typename
log_clock
::
duration
>
(
std
::
chrono
::
duration_cast
<
typename
log_clock
::
duration
>
(
std
::
chrono
::
seconds
(
ts
.
tv_sec
)
+
std
::
chrono
::
nanoseconds
(
ts
.
tv_nsec
)));
#else
return
log_clock
::
now
();
#endif
}
SPDLOG_INLINE
std
::
tm
localtime
(
const
std
::
time_t
&
time_tt
)
SPDLOG_NOEXCEPT
{
#ifdef _WIN32
std
::
tm
tm
;
localtime_s
(
&
tm
,
&
time_tt
);
#else
std
::
tm
tm
;
localtime_r
(
&
time_tt
,
&
tm
);
#endif
return
tm
;
}
SPDLOG_INLINE
std
::
tm
localtime
()
SPDLOG_NOEXCEPT
{
std
::
time_t
now_t
=
time
(
nullptr
);
return
localtime
(
now_t
);
}
SPDLOG_INLINE
std
::
tm
gmtime
(
const
std
::
time_t
&
time_tt
)
SPDLOG_NOEXCEPT
{
#ifdef _WIN32
std
::
tm
tm
;
gmtime_s
(
&
tm
,
&
time_tt
);
#else
std
::
tm
tm
;
gmtime_r
(
&
time_tt
,
&
tm
);
#endif
return
tm
;
}
SPDLOG_INLINE
std
::
tm
gmtime
()
SPDLOG_NOEXCEPT
{
std
::
time_t
now_t
=
time
(
nullptr
);
return
gmtime
(
now_t
);
}
SPDLOG_INLINE
void
prevent_child_fd
(
FILE
*
f
)
{
#ifdef _WIN32
#if !defined(__cplusplus_winrt)
auto
file_handle
=
(
HANDLE
)
_get_osfhandle
(
_fileno
(
f
));
if
(
!::
SetHandleInformation
(
file_handle
,
HANDLE_FLAG_INHERIT
,
0
))
throw
spdlog_ex
(
"SetHandleInformation failed"
,
errno
);
#endif
#else
auto
fd
=
fileno
(
f
);
if
(
fcntl
(
fd
,
F_SETFD
,
FD_CLOEXEC
)
==
-
1
)
{
throw
spdlog_ex
(
"fcntl with FD_CLOEXEC failed"
,
errno
);
}
#endif
}
// fopen_s on non windows for writing
SPDLOG_INLINE
bool
fopen_s
(
FILE
**
fp
,
const
filename_t
&
filename
,
const
filename_t
&
mode
)
{
#ifdef _WIN32
#ifdef SPDLOG_WCHAR_FILENAMES
*
fp
=
_wfsopen
((
filename
.
c_str
()),
mode
.
c_str
(),
_SH_DENYNO
);
#else
*
fp
=
_fsopen
((
filename
.
c_str
()),
mode
.
c_str
(),
_SH_DENYNO
);
#endif
#else // unix
*
fp
=
fopen
((
filename
.
c_str
()),
mode
.
c_str
());
#endif
#ifdef SPDLOG_PREVENT_CHILD_FD
if
(
*
fp
!=
nullptr
)
{
prevent_child_fd
(
*
fp
);
}
#endif
return
*
fp
==
nullptr
;
}
SPDLOG_INLINE
int
remove
(
const
filename_t
&
filename
)
SPDLOG_NOEXCEPT
{
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
return
_wremove
(
filename
.
c_str
());
#else
return
std
::
remove
(
filename
.
c_str
());
#endif
}
SPDLOG_INLINE
int
rename
(
const
filename_t
&
filename1
,
const
filename_t
&
filename2
)
SPDLOG_NOEXCEPT
{
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
return
_wrename
(
filename1
.
c_str
(),
filename2
.
c_str
());
#else
return
std
::
rename
(
filename1
.
c_str
(),
filename2
.
c_str
());
#endif
}
// Return if file exists
SPDLOG_INLINE
bool
file_exists
(
const
filename_t
&
filename
)
SPDLOG_NOEXCEPT
{
#ifdef _WIN32
#ifdef SPDLOG_WCHAR_FILENAMES
auto
attribs
=
GetFileAttributesW
(
filename
.
c_str
());
#else
auto
attribs
=
GetFileAttributesA
(
filename
.
c_str
());
#endif
return
(
attribs
!=
INVALID_FILE_ATTRIBUTES
&&
!
(
attribs
&
FILE_ATTRIBUTE_DIRECTORY
));
#else // common linux/unix all have the stat system call
struct
stat
buffer
;
return
(
stat
(
filename
.
c_str
(),
&
buffer
)
==
0
);
#endif
}
// Return file size according to open FILE* object
SPDLOG_INLINE
size_t
filesize
(
FILE
*
f
)
{
if
(
f
==
nullptr
)
{
throw
spdlog_ex
(
"Failed getting file size. fd is null"
);
}
#if defined(_WIN32) && !defined(__CYGWIN__)
int
fd
=
_fileno
(
f
);
#if _WIN64 // 64 bits
__int64
ret
=
_filelengthi64
(
fd
);
if
(
ret
>=
0
)
{
return
static_cast
<
size_t
>
(
ret
);
}
#else // windows 32 bits
long
ret
=
_filelength
(
fd
);
if
(
ret
>=
0
)
{
return
static_cast
<
size_t
>
(
ret
);
}
#endif
#else // unix
int
fd
=
fileno
(
f
);
// 64 bits(but not in osx or cygwin, where fstat64 is deprecated)
#if !defined(__FreeBSD__) && !defined(__APPLE__) && (defined(__x86_64__) || defined(__ppc64__)) && !defined(__CYGWIN__)
struct
stat64
st
;
if
(
fstat64
(
fd
,
&
st
)
==
0
)
{
return
static_cast
<
size_t
>
(
st
.
st_size
);
}
#else // unix 32 bits or cygwin
struct
stat
st
;
if
(
fstat
(
fd
,
&
st
)
==
0
)
{
return
static_cast
<
size_t
>
(
st
.
st_size
);
}
#endif
#endif
throw
spdlog_ex
(
"Failed getting file size from fd"
,
errno
);
}
// Return utc offset in minutes or throw spdlog_ex on failure
SPDLOG_INLINE
int
utc_minutes_offset
(
const
std
::
tm
&
tm
)
{
#ifdef _WIN32
#if _WIN32_WINNT < _WIN32_WINNT_WS08
TIME_ZONE_INFORMATION
tzinfo
;
auto
rv
=
GetTimeZoneInformation
(
&
tzinfo
);
#else
DYNAMIC_TIME_ZONE_INFORMATION
tzinfo
;
auto
rv
=
GetDynamicTimeZoneInformation
(
&
tzinfo
);
#endif
if
(
rv
==
TIME_ZONE_ID_INVALID
)
throw
spdlog
::
spdlog_ex
(
"Failed getting timezone info. "
,
errno
);
int
offset
=
-
tzinfo
.
Bias
;
if
(
tm
.
tm_isdst
)
{
offset
-=
tzinfo
.
DaylightBias
;
}
else
{
offset
-=
tzinfo
.
StandardBias
;
}
return
offset
;
#else
#if defined(sun) || defined(__sun) || defined(_AIX)
// 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris
struct
helper
{
static
long
int
calculate_gmt_offset
(
const
std
::
tm
&
localtm
=
details
::
os
::
localtime
(),
const
std
::
tm
&
gmtm
=
details
::
os
::
gmtime
())
{
int
local_year
=
localtm
.
tm_year
+
(
1900
-
1
);
int
gmt_year
=
gmtm
.
tm_year
+
(
1900
-
1
);
long
int
days
=
(
// difference in day of year
localtm
.
tm_yday
-
gmtm
.
tm_yday
// + intervening leap days
+
((
local_year
>>
2
)
-
(
gmt_year
>>
2
))
-
(
local_year
/
100
-
gmt_year
/
100
)
+
((
local_year
/
100
>>
2
)
-
(
gmt_year
/
100
>>
2
))
// + difference in years * 365 */
+
(
long
int
)(
local_year
-
gmt_year
)
*
365
);
long
int
hours
=
(
24
*
days
)
+
(
localtm
.
tm_hour
-
gmtm
.
tm_hour
);
long
int
mins
=
(
60
*
hours
)
+
(
localtm
.
tm_min
-
gmtm
.
tm_min
);
long
int
secs
=
(
60
*
mins
)
+
(
localtm
.
tm_sec
-
gmtm
.
tm_sec
);
return
secs
;
}
};
auto
offset_seconds
=
helper
::
calculate_gmt_offset
(
tm
);
#else
auto
offset_seconds
=
tm
.
tm_gmtoff
;
#endif
return
static_cast
<
int
>
(
offset_seconds
/
60
);
#endif
}
// Return current thread id as size_t
// It exists because the std::this_thread::get_id() is much slower(especially
// under VS 2013)
SPDLOG_INLINE
size_t
_thread_id
()
SPDLOG_NOEXCEPT
{
#ifdef _WIN32
return
static_cast
<
size_t
>
(
::
GetCurrentThreadId
());
#elif __linux__
#if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21)
#define SYS_gettid __NR_gettid
#endif
return
static_cast
<
size_t
>
(
syscall
(
SYS_gettid
));
#elif __FreeBSD__
long
tid
;
thr_self
(
&
tid
);
return
static_cast
<
size_t
>
(
tid
);
#elif __APPLE__
uint64_t
tid
;
pthread_threadid_np
(
nullptr
,
&
tid
);
return
static_cast
<
size_t
>
(
tid
);
#else // Default to standard C++11 (other Unix)
return
static_cast
<
size_t
>
(
std
::
hash
<
std
::
thread
::
id
>
()(
std
::
this_thread
::
get_id
()));
#endif
}
// Return current thread id as size_t (from thread local storage)
SPDLOG_INLINE
size_t
thread_id
()
SPDLOG_NOEXCEPT
{
#if defined(SPDLOG_NO_TLS)
return
_thread_id
();
#else // cache thread id in tls
static
thread_local
const
size_t
tid
=
_thread_id
();
return
tid
;
#endif
}
// This is avoid msvc issue in sleep_for that happens if the clock changes.
// See https://github.com/gabime/spdlog/issues/609
SPDLOG_INLINE
void
sleep_for_millis
(
int
milliseconds
)
SPDLOG_NOEXCEPT
{
#if defined(_WIN32)
::
Sleep
(
milliseconds
);
#else
std
::
this_thread
::
sleep_for
(
std
::
chrono
::
milliseconds
(
milliseconds
));
#endif
}
// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined)
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
#define SPDLOG_FILENAME_T(s) L##s
SPDLOG_INLINE
std
::
string
filename_to_str
(
const
filename_t
&
filename
)
{
std
::
wstring_convert
<
std
::
codecvt_utf8
<
wchar_t
>
,
wchar_t
>
c
;
return
c
.
to_bytes
(
filename
);
}
#else
#define SPDLOG_FILENAME_T(s) s
SPDLOG_INLINE
std
::
string
filename_to_str
(
const
filename_t
&
filename
)
{
return
filename
;
}
#endif
SPDLOG_INLINE
int
pid
()
{
#ifdef _WIN32
return
static_cast
<
int
>
(
::
GetCurrentProcessId
());
#else
return
static_cast
<
int
>
(
::
getpid
());
#endif
}
// Determine if the terminal supports colors
// Source: https://github.com/agauniyal/rang/
SPDLOG_INLINE
bool
is_color_terminal
()
SPDLOG_NOEXCEPT
{
#ifdef _WIN32
return
true
;
#else
static
constexpr
const
char
*
Terms
[]
=
{
"ansi"
,
"color"
,
"console"
,
"cygwin"
,
"gnome"
,
"konsole"
,
"kterm"
,
"linux"
,
"msys"
,
"putty"
,
"rxvt"
,
"screen"
,
"vt100"
,
"xterm"
};
const
char
*
env_p
=
std
::
getenv
(
"TERM"
);
if
(
env_p
==
nullptr
)
{
return
false
;
}
static
const
bool
result
=
std
::
any_of
(
std
::
begin
(
Terms
),
std
::
end
(
Terms
),
[
&
](
const
char
*
term
)
{
return
std
::
strstr
(
env_p
,
term
)
!=
nullptr
;
});
return
result
;
#endif
}
// Detrmine if the terminal attached
// Source: https://github.com/agauniyal/rang/
SPDLOG_INLINE
bool
in_terminal
(
FILE
*
file
)
SPDLOG_NOEXCEPT
{
#ifdef _WIN32
return
_isatty
(
_fileno
(
file
))
!=
0
;
#else
return
isatty
(
fileno
(
file
))
!=
0
;
#endif
}
}
// namespace os
}
// namespace details
}
// namespace spdlog
src/sink.cpp
0 → 100644
View file @
e2e3df90
#include "spdlog/common.h"
#include "spdlog/details/pattern_formatter.h"
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/sinks/sink.h"
#endif
SPDLOG_INLINE
spdlog
::
sinks
::
sink
::
sink
()
:
formatter_
{
details
::
make_unique
<
spdlog
::
pattern_formatter
>
()}
{}
SPDLOG_INLINE
spdlog
::
sinks
::
sink
::
sink
(
std
::
unique_ptr
<
spdlog
::
formatter
>
formatter
)
:
formatter_
{
std
::
move
(
formatter
)}
{}
SPDLOG_INLINE
bool
spdlog
::
sinks
::
sink
::
should_log
(
spdlog
::
level
::
level_enum
msg_level
)
const
{
return
msg_level
>=
level_
.
load
(
std
::
memory_order_relaxed
);
}
SPDLOG_INLINE
void
spdlog
::
sinks
::
sink
::
set_level
(
level
::
level_enum
log_level
)
{
level_
.
store
(
log_level
);
}
SPDLOG_INLINE
spdlog
::
level
::
level_enum
spdlog
::
sinks
::
sink
::
level
()
const
{
return
static_cast
<
spdlog
::
level
::
level_enum
>
(
level_
.
load
(
std
::
memory_order_relaxed
));
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment