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
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
793 additions
and
1017 deletions
+793
-1017
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
+2
-22
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
+69
-185
sink.h
include/spdlog/sinks/sink.h
+13
-21
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 @@
#include "spdlog/logger.h"
namespace
spdlog
{
class
logger
;
}
spdlog
::
logger
*
get_logger
();
int
main
(
int
,
char
*
[])
{
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 @@
#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
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#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_
}
}
}
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
))
{
...
...
@@ -96,7 +103,14 @@ inline void spdlog::async_logger::backend_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
)
...
...
include/spdlog/details/fmt_helper.h
View file @
e2e3df90
...
...
@@ -7,6 +7,7 @@
#include <chrono>
#include <type_traits>
#include "spdlog/fmt/fmt.h"
#include "spdlog/common.h"
// Some fmt helpers to efficiently format and pad ints and strings
namespace
spdlog
{
...
...
include/spdlog/details/log_msg.h
View file @
e2e3df90
...
...
@@ -6,36 +6,16 @@
#pragma once
#include "spdlog/common.h"
#include "spdlog/details/os.h"
#include <string>
#include <utility>
namespace
spdlog
{
namespace
details
{
struct
log_msg
{
log_msg
(
source_loc
loc
,
const
std
::
string
*
loggers_name
,
level
::
level_enum
lvl
,
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
)
{
}
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
(
source_loc
loc
,
const
std
::
string
*
loggers_name
,
level
::
level_enum
lvl
,
string_view_t
view
);
log_msg
(
const
std
::
string
*
loggers_name
,
level
::
level_enum
lvl
,
string_view_t
view
);
log_msg
(
const
log_msg
&
other
)
=
default
;
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 @@
#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
{
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
}
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
::
log_clock
::
time_point
now
()
SPDLOG_NOEXCEPT
;
inline
std
::
tm
localtime
()
SPDLOG_NOEXCEPT
{
std
::
time_t
now_t
=
time
(
nullptr
);
return
localtime
(
now_t
);
}
std
::
tm
localtime
(
const
std
::
time_t
&
time_tt
)
SPDLOG_NOEXCEPT
;
inline
std
::
tm
gmtime
(
const
std
::
time_t
&
time_tt
)
SPDLOG_NOEXCEPT
{
std
::
tm
localtime
()
SPDLOG_NOEXCEPT
;
#ifdef _WIN32
std
::
tm
tm
;
gmtime_s
(
&
tm
,
&
time_tt
);
#else
std
::
tm
tm
;
gmtime_r
(
&
time_tt
,
&
tm
);
#endif
return
tm
;
}
std
::
tm
gmtime
(
const
std
::
time_t
&
time_tt
)
SPDLOG_NOEXCEPT
;
inline
std
::
tm
gmtime
()
SPDLOG_NOEXCEPT
{
std
::
time_t
now_t
=
time
(
nullptr
);
return
gmtime
(
now_t
);
}
std
::
tm
gmtime
()
SPDLOG_NOEXCEPT
;
// eol definition
#if !defined(SPDLOG_EOL)
...
...
@@ -121,301 +45,56 @@ SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL;
// folder separator
#ifdef _WIN32
SPDLOG_CONSTEXPR
static
const
char
folder_sep
=
'\\'
;
const
char
folder_sep
=
'\\'
;
#else
SPDLOG_CONSTEXPR
static
const
char
folder_sep
=
'/'
;
#endif
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
}
void
prevent_child_fd
(
FILE
*
f
);
// fopen_s on non windows for writing
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
bool
fopen_s
(
FILE
**
fp
,
const
filename_t
&
filename
,
const
filename_t
&
mode
);
#ifdef SPDLOG_PREVENT_CHILD_FD
if
(
*
fp
!=
nullptr
)
{
prevent_child_fd
(
*
fp
);
}
#endif
return
*
fp
==
nullptr
;
}
int
remove
(
const
filename_t
&
filename
)
SPDLOG_NOEXCEPT
;
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
}
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
}
int
rename
(
const
filename_t
&
filename1
,
const
filename_t
&
filename2
)
SPDLOG_NOEXCEPT
;
// Return if file exists
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
}
bool
file_exists
(
const
filename_t
&
filename
)
SPDLOG_NOEXCEPT
;
// Return file size according to open FILE* object
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
);
}
size_t
filesize
(
FILE
*
f
);
// Return utc offset in minutes or throw spdlog_ex on failure
inline
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
}
int
utc_minutes_offset
(
const
std
::
tm
&
tm
=
details
::
os
::
localtime
());
// Return current thread id as size_t
// It exists because the std::this_thread::get_id() is much slower(especially
// under VS 2013)
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
}
size_t
_thread_id
()
SPDLOG_NOEXCEPT
;
// Return current thread id as size_t (from thread local storage)
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
}
size_t
thread_id
()
SPDLOG_NOEXCEPT
;
// This is avoid msvc issue in sleep_for that happens if the clock changes.
// See https://github.com/gabime/spdlog/issues/609
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
}
void
sleep_for_millis
(
int
milliseconds
)
SPDLOG_NOEXCEPT
;
// 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
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
()
{
std
::
string
filename_to_str
(
const
filename_t
&
filename
);
#ifdef _WIN32
return
static_cast
<
int
>
(
::
GetCurrentProcessId
());
#else
return
static_cast
<
int
>
(
::
getpid
());
#endif
}
int
pid
();
// Determine if the terminal supports colors
// Source: https://github.com/agauniyal/rang/
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
}
bool
is_color_terminal
()
SPDLOG_NOEXCEPT
;
// Detrmine if the terminal attached
// Source: https://github.com/agauniyal/rang/
inline
bool
in_terminal
(
FILE
*
file
)
SPDLOG_NOEXCEPT
{
#ifdef _WIN32
return
_isatty
(
_fileno
(
file
))
!=
0
;
#else
return
isatty
(
fileno
(
file
))
!=
0
;
#endif
}
bool
in_terminal
(
FILE
*
file
)
SPDLOG_NOEXCEPT
;
}
// namespace os
}
// namespace details
}
// namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
#include "../src/os.cpp"
#endif
include/spdlog/details/pattern_formatter.h
View file @
e2e3df90
...
...
@@ -4,7 +4,6 @@
//
#pragma once
#include "spdlog/details/fmt_helper.h"
#include "spdlog/details/log_msg.h"
#include "spdlog/details/os.h"
...
...
include/spdlog/details/registry.h
View file @
e2e3df90
...
...
@@ -13,6 +13,7 @@
#include "spdlog/common.h"
#include "spdlog/details/periodic_worker.h"
#include "spdlog/logger.h"
#include "spdlog/details/pattern_formatter.h"
#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER
// support for the default stdout color logger
...
...
include/spdlog/logger.h
View file @
e2e3df90
...
...
@@ -15,51 +15,39 @@
// and send to its destination.
//
// The use of private formatter per sink provides the opportunity to cache some
// formatted data,
// and support customize format per each sink.
// formatted data,
and support for different format per sink.
#include "spdlog/common.h"
#include "spdlog/formatter.h"
#include "spdlog/sinks/sink.h"
#include "spdlog/details/fmt_helper.h"
#include "spdlog/details/log_msg.h"
//#include "spdlog/formatter.h"
//#include "spdlog/sinks/sink.h"
#include <memory>
#include <string>
#include <vector>
#ifndef SPDLOG_CATCH_AND_HANDLE
#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
namespace
spdlog
{
public
:
class
logger
{
public
:
template
<
typename
It
>
logger
(
std
::
string
name
,
It
begin
,
It
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
())
{}
{
}
logger
(
std
::
string
name
,
sinks_init_list
sinks
)
:
logger
(
std
::
move
(
name
),
sinks
.
begin
(),
sinks
.
end
())
{
}
virtual
~
logger
()
=
default
;
...
...
@@ -76,43 +64,28 @@ public:
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
));
details
::
log_msg
log_msg
(
loc
,
&
name_
,
lvl
,
string_view_t
(
buf
.
data
(),
buf
.
size
()
));
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
...);
}
void
log
(
source_loc
loc
,
level
::
level_enum
lvl
,
const
char
*
msg
)
{
if
(
!
should_log
(
lvl
))
catch
(
const
std
::
exception
&
ex
)
{
return
;
err_handler_
(
ex
.
what
())
;
}
try
catch
(...)
{
details
::
log_msg
log_msg
(
loc
,
&
name_
,
lvl
,
spdlog
::
string_view_t
(
msg
));
sink_it_
(
log_msg
);
err_handler_
(
"Unknown exception in logger"
);
}
SPDLOG_CATCH_AND_HANDLE
}
void
log
(
level
::
level_enum
lvl
,
const
char
*
msg
)
template
<
typename
...
Args
>
void
log
(
level
::
level_enum
lvl
,
const
char
*
fmt
,
const
Args
&
...
args
)
{
log
(
source_loc
{},
lvl
,
msg
);
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
)
...
...
@@ -120,14 +93,12 @@ public:
log
(
level
::
trace
,
fmt
,
args
...);
}
template
<
typename
...
Args
>
void
debug
(
const
char
*
fmt
,
const
Args
&
...
args
)
{
log
(
level
::
debug
,
fmt
,
args
...);
}
template
<
typename
...
Args
>
void
info
(
const
char
*
fmt
,
const
Args
&
...
args
)
{
...
...
@@ -152,7 +123,6 @@ public:
log
(
level
::
critical
,
fmt
,
args
...);
}
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
#ifndef _WIN32
#error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows
...
...
@@ -263,7 +233,14 @@ public:
details
::
log_msg
log_msg
(
loc
,
&
name_
,
lvl
,
msg
);
sink_it_
(
log_msg
);
}
SPDLOG_CATCH_AND_HANDLE
catch
(
const
std
::
exception
&
ex
)
{
err_handler_
(
ex
.
what
());
}
catch
(...)
{
err_handler_
(
"Unknown exception in logger"
);
}
}
// T cannot be statically converted to string_view
...
...
@@ -282,7 +259,14 @@ public:
details
::
log_msg
log_msg
(
loc
,
&
name_
,
lvl
,
to_string_view
(
buf
));
sink_it_
(
log_msg
);
}
SPDLOG_CATCH_AND_HANDLE
catch
(
const
std
::
exception
&
ex
)
{
err_handler_
(
ex
.
what
());
}
catch
(...)
{
err_handler_
(
"Unknown exception in logger"
);
}
}
template
<
typename
T
>
...
...
@@ -321,155 +305,52 @@ public:
log
(
level
::
critical
,
msg
);
}
bool
should_log
(
level
::
level_enum
msg_level
)
const
{
return
msg_level
>=
level_
.
load
(
std
::
memory_order_relaxed
);
}
bool
should_log
(
level
::
level_enum
msg_level
)
const
;
void
set_level
(
level
::
level_enum
log_level
)
{
level_
.
store
(
log_level
);
}
void
set_level
(
level
::
level_enum
log_level
);
static
level
::
level_enum
default_level
()
{
return
static_cast
<
spdlog
::
level
::
level_enum
>
(
SPDLOG_ACTIVE_LEVEL
);
}
static
level
::
level_enum
default_level
();
level
::
level_enum
level
()
const
{
return
static_cast
<
spdlog
::
level
::
level_enum
>
(
level_
.
load
(
std
::
memory_order_relaxed
));
}
level
::
level_enum
level
()
const
;
const
std
::
string
&
name
()
const
{
return
name_
;
}
const
std
::
string
&
name
()
const
;
// set formatting for the sinks in this logger.
// 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_formatter
(
std
::
unique_ptr
<
formatter
>
f
);
void
set_pattern
(
std
::
string
pattern
,
pattern_time_type
time_type
=
pattern_time_type
::
local
)
{
auto
new_formatter
=
details
::
make_unique
<
spdlog
::
pattern_formatter
>
(
std
::
move
(
pattern
),
time_type
);
set_formatter
(
std
::
move
(
new_formatter
));
}
void
set_pattern
(
std
::
string
pattern
,
pattern_time_type
time_type
=
pattern_time_type
::
local
);
// flush functions
void
flush
()
{
try
{
flush_
();
}
SPDLOG_CATCH_AND_HANDLE
}
void
flush_on
(
level
::
level_enum
log_level
)
{
flush_level_
.
store
(
log_level
);
}
level
::
level_enum
flush_level
()
const
{
return
static_cast
<
spdlog
::
level
::
level_enum
>
(
flush_level_
.
load
(
std
::
memory_order_relaxed
));
}
void
flush
();
void
flush_on
(
level
::
level_enum
log_level
);
level
::
level_enum
flush_level
()
const
;
// sinks
const
std
::
vector
<
sink_ptr
>
&
sinks
()
const
{
return
sinks_
;
}
const
std
::
vector
<
sink_ptr
>
&
sinks
()
const
;
std
::
vector
<
sink_ptr
>
&
sinks
()
{
return
sinks_
;
}
std
::
vector
<
sink_ptr
>
&
sinks
();
// error handler
void
set_error_handler
(
log_err_handler
err_handler
)
{
err_handler_
=
std
::
move
(
err_handler
);
}
void
set_error_handler
(
log_err_handler
err_handler
);
log_err_handler
error_handler
()
const
{
return
err_handler_
;
}
log_err_handler
error_handler
()
const
;
// create new logger with same sinks and configuration.
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
;
}
virtual
std
::
shared_ptr
<
logger
>
clone
(
std
::
string
logger_name
);
protected
:
virtual
void
sink_it_
(
details
::
log_msg
&
msg
);
protected
:
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
))
{
flush_
();
}
}
virtual
void
flush_
()
{
for
(
auto
&
sink
:
sinks_
)
{
sink
->
flush
();
}
}
bool
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
);
}
virtual
void
flush_
();
bool
should_flush_
(
const
details
::
log_msg
&
msg
);
// default error handler.
// print the error to stderr with the max rate of 1 message/minute.
void
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
);
}
void
default_err_handler_
(
const
std
::
string
&
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
);
}
void
incr_msg_counter_
(
details
::
log_msg
&
msg
);
const
std
::
string
name_
;
std
::
vector
<
sink_ptr
>
sinks_
;
...
...
@@ -478,6 +359,9 @@ protected:
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
#ifdef SPDLOG_HEADER_ONLY
#include "../src/logger.cpp"
#endif // SPDLOG_HEADER_ONLY
include/spdlog/sinks/sink.h
View file @
e2e3df90
...
...
@@ -6,49 +6,41 @@
#pragma once
#include "spdlog/details/log_msg.h"
#include "spdlog/details/pattern_formatter.h"
//
#include "spdlog/details/pattern_formatter.h"
#include "spdlog/formatter.h"
namespace
spdlog
{
namespace
sinks
{
class
sink
{
public
:
sink
()
=
default
;
explicit
sink
(
std
::
unique_ptr
<
spdlog
::
formatter
>
formatter
)
:
formatter_
{
std
::
move
(
formatter
)}
{
}
sink
();
explicit
sink
(
std
::
unique_ptr
<
spdlog
::
formatter
>
formatter
);
virtual
~
sink
()
=
default
;
virtual
void
log
(
const
details
::
log_msg
&
msg
)
=
0
;
virtual
void
flush
()
=
0
;
virtual
void
set_pattern
(
const
std
::
string
&
pattern
)
=
0
;
virtual
void
set_formatter
(
std
::
unique_ptr
<
spdlog
::
formatter
>
sink_formatter
)
=
0
;
bool
should_log
(
level
::
level_enum
msg_level
)
const
{
return
msg_level
>=
level_
.
load
(
std
::
memory_order_relaxed
);
}
bool
should_log
(
level
::
level_enum
msg_level
)
const
;
void
set_level
(
level
::
level_enum
log_level
)
{
level_
.
store
(
log_level
);
}
void
set_level
(
level
::
level_enum
log_level
);
level
::
level_enum
level
()
const
{
return
static_cast
<
spdlog
::
level
::
level_enum
>
(
level_
.
load
(
std
::
memory_order_relaxed
));
}
level
::
level_enum
level
()
const
;
protected
:
// sink log level - default is all
level_t
level_
{
level
::
trace
};
// sink formatter
- default is full format
std
::
unique_ptr
<
spdlog
::
formatter
>
formatter_
{
details
::
make_unique
<
spdlog
::
pattern_formatter
>
()}
;
// sink formatter
std
::
unique_ptr
<
spdlog
::
formatter
>
formatter_
;
};
}
// namespace sinks
}
// 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