Merge pull request #3 from gabime/v1.x

update 20190522
pull/1084/head
CodingTrader 6 years ago committed by GitHub
commit c9c3373ba9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,7 +4,7 @@
#
cmake_minimum_required(VERSION 3.1)
project(spdlog VERSION 1.3.0 LANGUAGES CXX)
project(spdlog VERSION 1.3.1 LANGUAGES CXX)
include(CMakeDependentOption)
include(GNUInstallDirs)
@ -30,7 +30,6 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCH
add_compile_options("-Wconversion")
add_compile_options("-pedantic")
add_compile_options("-Wfatal-errors")
endif()
#---------------------------------------------------------------------------------------
@ -47,17 +46,15 @@ add_library(spdlog::spdlog ALIAS spdlog)
# Check if spdlog is being used directly or via add_subdirectory
set(SPDLOG_MASTER_PROJECT OFF)
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(SPDLOG_MASTER_PROJECT ON)
set(SPDLOG_MASTER_PROJECT ON)
endif()
option(SPDLOG_BUILD_EXAMPLES "Build examples" ${SPDLOG_MASTER_PROJECT})
option(SPDLOG_BUILD_BENCH "Build benchmarks" ${SPDLOG_MASTER_PROJECT})
option(SPDLOG_BUILD_BENCH "Build benchmarks (Requires https://github.com/google/benchmark.git to be installed)" OFF)
option(SPDLOG_BUILD_TESTS "Build tests" ${SPDLOG_MASTER_PROJECT})
option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" OFF)
if(SPDLOG_FMT_EXTERNAL)
find_package(fmt REQUIRED CONFIG)
endif()
option(SPDLOG_FMT_HEADER_ONLY "Use header-only variant of external fmt library" ON)
option(SPDLOG_INSTALL "Generate the install target." ${SPDLOG_MASTER_PROJECT})
target_include_directories(
spdlog
@ -68,7 +65,16 @@ target_include_directories(
if(SPDLOG_FMT_EXTERNAL)
target_compile_definitions(spdlog INTERFACE SPDLOG_FMT_EXTERNAL)
target_link_libraries(spdlog INTERFACE fmt::fmt)
if(NOT TARGET fmt::fmt)
find_package(fmt REQUIRED CONFIG)
endif()
if(SPDLOG_FMT_HEADER_ONLY)
target_link_libraries(spdlog INTERFACE fmt::fmt-header-only)
else()
target_link_libraries(spdlog INTERFACE fmt::fmt)
endif()
endif()
set(HEADER_BASE "${CMAKE_CURRENT_SOURCE_DIR}/include")
@ -89,59 +95,60 @@ endif()
#---------------------------------------------------------------------------------------
# Install/export targets and files
#---------------------------------------------------------------------------------------
# set files and directories
set(config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
set(include_install_dir "${CMAKE_INSTALL_INCLUDEDIR}")
set(pkgconfig_install_dir "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
set(version_config "${CMAKE_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(project_config "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake")
set(targets_config "${PROJECT_NAME}Targets.cmake")
set(pkg_config "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc")
set(targets_export_name "${PROJECT_NAME}Targets")
set(namespace "${PROJECT_NAME}::")
# generate package version file
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${version_config}" COMPATIBILITY SameMajorVersion
)
# configure pkg config file
configure_file("cmake/spdlog.pc.in" "${pkg_config}" @ONLY)
# configure spdlogConfig.cmake file
configure_file("cmake/Config.cmake.in" "${project_config}" @ONLY)
# install targets
install(
TARGETS spdlog
EXPORT "${targets_export_name}"
)
# install headers
install(
DIRECTORY "${HEADER_BASE}/${PROJECT_NAME}"
DESTINATION "${include_install_dir}"
)
# install project config and version file
install(
FILES "${project_config}" "${version_config}"
DESTINATION "${config_install_dir}"
)
# install pkg config file
install(
FILES "${pkg_config}"
DESTINATION "${pkgconfig_install_dir}"
)
# install targets config file
install(
EXPORT "${targets_export_name}"
NAMESPACE "${namespace}"
DESTINATION "${config_install_dir}"
FILE ${targets_config}
)
if(SPDLOG_INSTALL)
# set files and directories
set(config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
set(include_install_dir "${CMAKE_INSTALL_INCLUDEDIR}")
set(pkgconfig_install_dir "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
set(version_config "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(project_config "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake")
set(targets_config "${PROJECT_NAME}Targets.cmake")
set(pkg_config "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc")
set(targets_export_name "${PROJECT_NAME}Targets")
set(namespace "${PROJECT_NAME}::")
# generate package version file
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${version_config}" COMPATIBILITY SameMajorVersion
)
# configure pkg config file
configure_file("cmake/spdlog.pc.in" "${pkg_config}" @ONLY)
# configure spdlogConfig.cmake file
configure_file("cmake/Config.cmake.in" "${project_config}" @ONLY)
# install targets
install(
TARGETS spdlog
EXPORT "${targets_export_name}"
)
# install headers
install(
DIRECTORY "${HEADER_BASE}/${PROJECT_NAME}"
DESTINATION "${include_install_dir}"
)
# install project config and version file
install(
FILES "${project_config}" "${version_config}"
DESTINATION "${config_install_dir}"
)
# install pkg config file
install(
FILES "${pkg_config}"
DESTINATION "${pkgconfig_install_dir}"
)
# install targets config file
install(
EXPORT "${targets_export_name}"
NAMESPACE "${namespace}"
DESTINATION "${config_install_dir}"
FILE ${targets_config}
)
# export build directory targets file
export(
@ -153,5 +160,7 @@ export(
# register project in CMake user registry
export(PACKAGE ${PROJECT_NAME})
endif()
file(GLOB_RECURSE spdlog_include_SRCS "${HEADER_BASE}/*.h")
add_custom_target(spdlog_headers_for_ide SOURCES ${spdlog_include_SRCS})

@ -11,7 +11,6 @@ Very fast, header only, C++ logging library. [![Build Status](https://travis-ci.
#### Or use your favorite package manager:
* Ubuntu: `apt-get install libspdlog-dev`
* Homebrew: `brew install spdlog`
* FreeBSD: `cd /usr/ports/devel/spdlog/ && make install clean`
* Fedora: `yum install spdlog`
@ -80,6 +79,8 @@ async... Elapsed: 0.349851 2,858,358/sec
#### Basic usage
```c++
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"
int main()
{
spdlog::info("Welcome to spdlog!");
@ -101,7 +102,10 @@ int main()
// define SPDLOG_ACTIVE_LEVEL to desired level
SPDLOG_TRACE("Some trace message with param {}", {});
SPDLOG_DEBUG("Some debug message");
// Set the default logger to file logger
auto file_logger = spdlog::basic_logger_mt("basic_logger", "logs/basic.txt");
spdlog::set_default_logger(file_logger);
}
```
#### create stdout/stderr logger object
@ -310,7 +314,7 @@ void syslog_example()
void android_example()
{
std::string tag = "spdlog-android";
auto android_logger = spdlog::android_logger("android", tag);
auto android_logger = spdlog::android_logger_mt("android", tag);
android_logger->critical("Use \"adb shell logcat\" to view this message.");
}
```

@ -125,9 +125,12 @@ enum level_enum
"trace", "debug", "info", "warning", "error", "critical", "off" \
}
#endif
static string_view_t level_string_views[] SPDLOG_LEVEL_NAMES;
static const char *short_level_names[]{"T", "D", "I", "W", "E", "C", "O"};
#if !defined(SPDLOG_SHORT_LEVEL_NAMES)
#define SPDLOG_SHORT_LEVEL_NAMES {"T", "D", "I", "W", "E", "C", "O"}
#endif
static const char *short_level_names[] SPDLOG_SHORT_LEVEL_NAMES;
inline string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT
{
@ -156,6 +159,16 @@ inline spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCE
using level_hasher = std::hash<int>;
} // namespace level
//
// Color mode used by sinks with color support.
//
enum class color_mode
{
always,
automatic,
never
};
//
// Pattern time - specific time getting to use for pattern_formatter.
// local time by default
@ -210,10 +223,10 @@ struct source_loc
, funcname{""}
{
}
SPDLOG_CONSTEXPR source_loc(const char *filename, int line, const char *funcname)
: filename{filename}
, line{static_cast<uint32_t>(line)}
, funcname{funcname}
SPDLOG_CONSTEXPR source_loc(const char *filename_in, int line_in, const char *funcname_in)
: filename{filename_in}
, line{static_cast<uint32_t>(line_in)}
, funcname{funcname_in}
{
}

@ -102,6 +102,12 @@ 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)
{
@ -117,12 +123,6 @@ inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const
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(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)
{
@ -141,12 +141,6 @@ inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const
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(level::level_enum lvl, const T &msg)
{
log(source_loc{}, lvl, msg);
}
template<typename... Args>
inline void spdlog::logger::trace(const char *fmt, const Args &... args)
{

@ -196,7 +196,7 @@ inline bool file_exists(const filename_t &filename) SPDLOG_NOEXCEPT
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);
return (::stat(filename.c_str(), &buffer) == 0);
#endif
}
@ -229,14 +229,14 @@ inline size_t filesize(FILE *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)
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)
if (::fstat(fd, &st) == 0)
{
return static_cast<size_t>(st.st_size);
}

@ -352,7 +352,7 @@ class Y_formatter final : public flag_formatter
{
public:
explicit Y_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
{
@ -418,7 +418,7 @@ class I_formatter final : public flag_formatter
{
public:
explicit I_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
{
@ -433,7 +433,7 @@ class M_formatter final : public flag_formatter
{
public:
explicit M_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
{
@ -448,7 +448,7 @@ class S_formatter final : public flag_formatter
{
public:
explicit S_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
{
@ -463,7 +463,7 @@ class e_formatter final : public flag_formatter
{
public:
explicit e_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
{
@ -486,7 +486,7 @@ class f_formatter final : public flag_formatter
{
public:
explicit f_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
{
@ -509,7 +509,7 @@ class F_formatter final : public flag_formatter
{
public:
explicit F_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
{
@ -532,7 +532,7 @@ class E_formatter final : public flag_formatter
{
public:
explicit E_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
{
@ -549,7 +549,7 @@ class p_formatter final : public flag_formatter
{
public:
explicit p_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
{
@ -564,7 +564,7 @@ class r_formatter final : public flag_formatter
{
public:
explicit r_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
{
@ -586,7 +586,7 @@ class R_formatter final : public flag_formatter
{
public:
explicit R_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
{
@ -604,7 +604,7 @@ class T_formatter final : public flag_formatter
{
public:
explicit T_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
{
@ -624,7 +624,7 @@ class z_formatter final : public flag_formatter
{
public:
explicit z_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
const std::chrono::seconds cache_refresh = std::chrono::seconds(5);
@ -683,7 +683,7 @@ class t_formatter final : public flag_formatter
{
public:
explicit t_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
{
@ -705,7 +705,7 @@ class pid_formatter final : public flag_formatter
{
public:
explicit pid_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &, const std::tm &, fmt::memory_buffer &dest) override
{
@ -728,7 +728,7 @@ class i_formatter final : public flag_formatter
{
public:
explicit i_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
{
@ -742,7 +742,7 @@ class v_formatter final : public flag_formatter
{
public:
explicit v_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
{
@ -829,7 +829,7 @@ class source_location_formatter final : public flag_formatter
{
public:
explicit source_location_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
{
@ -858,7 +858,7 @@ class source_filename_formatter final : public flag_formatter
{
public:
explicit source_filename_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
{
@ -875,7 +875,7 @@ class source_linenum_formatter final : public flag_formatter
{
public:
explicit source_linenum_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
{
@ -900,7 +900,7 @@ class source_funcname_formatter final : public flag_formatter
{
public:
explicit source_funcname_formatter(padding_info padinfo)
: flag_formatter(padinfo){};
: flag_formatter(padinfo){}
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
{

@ -100,18 +100,13 @@ public:
#endif // _WIN32
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
// 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>
template<class T>
void log(level::level_enum lvl, const T &);
// 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 &);
// 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>
void log(level::level_enum lvl, const T &);
// 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>
void log(source_loc loc, level::level_enum lvl, const T &);

@ -33,12 +33,12 @@ class ansicolor_sink final : public sink
{
public:
using mutex_t = typename ConsoleMutex::mutex_t;
ansicolor_sink()
ansicolor_sink(color_mode mode = color_mode::automatic)
: target_file_(TargetStream::stream())
, mutex_(ConsoleMutex::mutex())
{
should_do_colors_ = details::os::in_terminal(target_file_) && details::os::is_color_terminal();
set_color_mode_(mode);
colors_[level::trace] = white;
colors_[level::debug] = cyan;
colors_[level::info] = green;
@ -133,7 +133,35 @@ public:
formatter_ = std::move(sink_formatter);
}
bool should_color()
{
std::lock_guard<mutex_t> lock(mutex_);
return should_do_colors_;
}
void set_color_mode(color_mode mode)
{
std::lock_guard<mutex_t> lock(mutex_);
set_color_mode_(mode);
}
private:
void set_color_mode_(color_mode mode)
{
switch (mode)
{
case color_mode::always:
should_do_colors_ = true;
break;
case color_mode::automatic:
should_do_colors_ = details::os::in_terminal(target_file_) && details::os::is_color_terminal();
break;
case color_mode::never:
should_do_colors_ = false;
break;
}
}
void print_ccode_(const std::string &color_code)
{
fwrite(color_code.data(), sizeof(char), color_code.size(), target_file_);

@ -30,6 +30,11 @@ public:
file_helper_.open(filename, truncate);
}
const filename_t &filename() const
{
return file_helper_.filename();
}
protected:
void sink_it_(const details::log_msg &msg) override
{

@ -63,6 +63,11 @@ public:
rotation_tp_ = next_rotation_tp_();
}
const filename_t &filename() const
{
return file_helper_.filename();
}
protected:
void sink_it_(const details::log_msg &msg) override
{

@ -31,13 +31,17 @@ template<typename Mutex>
class rotating_file_sink final : public base_sink<Mutex>
{
public:
rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files)
rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open=false)
: base_filename_(std::move(base_filename))
, max_size_(max_size)
, max_files_(max_files)
{
file_helper_.open(calc_filename(base_filename_, 0));
current_size_ = file_helper_.size(); // expensive. called only once
if (rotate_on_open && current_size_ > 0)
{
rotate_();
}
}
// calc filename according to index and file extension if exists.
@ -58,6 +62,11 @@ public:
return fmt::to_string(w);
}
const filename_t &filename() const
{
return file_helper_.filename();
}
protected:
void sink_it_(const details::log_msg &msg) override
{
@ -141,15 +150,15 @@ using rotating_file_sink_st = rotating_file_sink<details::null_mutex>;
template<typename Factory = default_factory>
inline std::shared_ptr<logger> rotating_logger_mt(
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files)
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files, bool rotate_on_open=false)
{
return Factory::template create<sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files);
return Factory::template create<sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files, rotate_on_open);
}
template<typename Factory = default_factory>
inline std::shared_ptr<logger> rotating_logger_st(
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files)
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files, bool rotate_on_open = false)
{
return Factory::template create<sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files);
return Factory::template create<sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files, rotate_on_open);
}
} // namespace spdlog

@ -14,15 +14,10 @@ namespace sinks {
class sink
{
public:
sink()
: level_(level::trace)
, formatter_(new pattern_formatter())
{
}
sink() = default;
explicit sink(std::unique_ptr<spdlog::pattern_formatter> formatter)
: level_(level::trace)
, formatter_(std::move(formatter))
explicit sink(std::unique_ptr<spdlog::formatter> formatter)
: formatter_{std::move(formatter)}
{
}
@ -49,10 +44,10 @@ public:
protected:
// sink log level - default is all
level_t level_;
level_t level_{level::trace};
// sink formatter - default is full format
std::unique_ptr<spdlog::formatter> formatter_;
std::unique_ptr<spdlog::formatter> formatter_{details::make_unique<spdlog::pattern_formatter>()};
};
} // namespace sinks

@ -31,26 +31,26 @@ using stderr_color_sink_st = ansicolor_stderr_sink_st;
} // namespace sinks
template<typename Factory = default_factory>
inline std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name)
inline std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic)
{
return Factory::template create<sinks::stdout_color_sink_mt>(logger_name);
return Factory::template create<sinks::stdout_color_sink_mt>(logger_name, mode);
}
template<typename Factory = default_factory>
inline std::shared_ptr<logger> stdout_color_st(const std::string &logger_name)
inline std::shared_ptr<logger> stdout_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic)
{
return Factory::template create<sinks::stdout_color_sink_st>(logger_name);
return Factory::template create<sinks::stdout_color_sink_st>(logger_name, mode);
}
template<typename Factory = default_factory>
inline std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name)
inline std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic)
{
return Factory::template create<sinks::stderr_color_sink_mt>(logger_name);
return Factory::template create<sinks::stderr_color_sink_mt>(logger_name, mode);
}
template<typename Factory = default_factory>
inline std::shared_ptr<logger> stderr_color_st(const std::string &logger_name)
inline std::shared_ptr<logger> stderr_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic)
{
return Factory::template create<sinks::stderr_color_sink_mt>(logger_name);
return Factory::template create<sinks::stderr_color_sink_st>(logger_name, mode);
}
} // namespace spdlog

@ -0,0 +1,91 @@
//
// Copyright(c) 2019 ZVYAGIN.Alexander@gmail.com
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#pragma once
#ifndef SPDLOG_H
#include "spdlog/spdlog.h"
#endif
#include "spdlog/sinks/base_sink.h"
#include <array>
#include <string>
#include <systemd/sd-journal.h>
namespace spdlog {
namespace sinks {
inline int syslog_level(level::level_enum l) {
switch(l) {
case level::off:
case level::trace:
case level::debug:
return LOG_DEBUG;
case level::info:
return LOG_INFO;
case level::warn:
return LOG_WARNING;
case level::err:
return LOG_ERR;
case level::critical:
return LOG_CRIT;
default:
throw std::invalid_argument("systemd_sink.h syslog_level()");
}
}
/**
* Sink that write to systemd using the `sd_journal_print()` library call.
*
* Locking is not needed, as `sd_journal_print()` itself is thread-safe.
*/
template<typename Mutex>
class systemd_sink : public base_sink<Mutex>
{
public:
//
explicit systemd_sink(void) {}
~systemd_sink() override {}
systemd_sink(const systemd_sink &) = delete;
systemd_sink &operator=(const systemd_sink &) = delete;
protected:
void sink_it_(const details::log_msg &msg) override
{
if( sd_journal_print(
syslog_level(msg.level),
"%.*s",
static_cast<int>(msg.payload.size()),
msg.payload.data()
)
)
throw spdlog_ex("Failed writing to systemd");
}
void flush_() override {}
};
using systemd_sink_mt = systemd_sink<std::mutex>;
using systemd_sink_st = systemd_sink<details::null_mutex>;
} // namespace sinks
// Create and register a syslog logger
template<typename Factory = default_factory>
inline std::shared_ptr<logger> systemd_logger_mt(
const std::string &logger_name)
{
return Factory::template create<sinks::systemd_sink_mt>(logger_name);
}
template<typename Factory = default_factory>
inline std::shared_ptr<logger> systemd_logger_st(
const std::string &logger_name)
{
return Factory::template create<sinks::systemd_sink_st>(logger_name);
}
} // namespace spdlog

@ -37,10 +37,11 @@ public:
const WORD WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
const WORD YELLOW = FOREGROUND_RED | FOREGROUND_GREEN;
wincolor_sink()
wincolor_sink(color_mode mode = color_mode::automatic)
: out_handle_(OutHandle::handle())
, mutex_(ConsoleMutex::mutex())
{
set_color_mode_(mode);
colors_[level::trace] = WHITE;
colors_[level::debug] = CYAN;
colors_[level::info] = GREEN;
@ -70,7 +71,7 @@ public:
std::lock_guard<mutex_t> lock(mutex_);
fmt::memory_buffer formatted;
formatter_->format(msg, formatted);
if (msg.color_range_end > msg.color_range_start)
if (should_do_colors_ && msg.color_range_end > msg.color_range_start)
{
// before color range
print_range_(formatted, 0, msg.color_range_start);
@ -83,7 +84,7 @@ public:
// after color range
print_range_(formatted, msg.color_range_end, formatted.size());
}
else // print without colors if color range is invalid
else // print without colors if color range is invalid (or color is disabled)
{
print_range_(formatted, 0, formatted.size());
}
@ -106,8 +107,29 @@ public:
formatter_ = std::move(sink_formatter);
}
void set_color_mode(color_mode mode)
{
std::lock_guard<mutex_t> lock(mutex_);
set_color_mode_(mode);
}
private:
using mutex_t = typename ConsoleMutex::mutex_t;
void set_color_mode_(color_mode mode)
{
switch (mode)
{
case color_mode::always:
case color_mode::automatic:
should_do_colors_ = true;
break;
case color_mode::never:
should_do_colors_ = false;
break;
}
}
// set color and return the orig console attributes (for resetting later)
WORD set_console_attribs(WORD attribs)
{
@ -130,6 +152,7 @@ private:
HANDLE out_handle_;
mutex_t &mutex_;
bool should_do_colors_;
std::unordered_map<level::level_enum, WORD, level::level_hasher> colors_;
};

@ -47,6 +47,21 @@ inline std::shared_ptr<spdlog::logger> create(std::string logger_name, SinkArgs
return default_factory::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(sink_args)...);
}
// Initialize and register a logger,
// formatter and flush level will be set according the global settings.
//
// NOTE:
// Use this function when creating loggers manually.
//
// Example:
// auto console_sink = std::make_shared<spdlog::sinks::stdout_sink_mt>();
// auto console_logger = std::make_shared<spdlog::logger>("console_logger", console_sink);
// spdlog::initialize_logger(console_logger);
inline void initialize_logger(std::shared_ptr<logger> logger)
{
details::registry::instance().initialize_logger(std::move(logger));
}
// Return an existing logger or nullptr if a logger with such name doesn't
// exist.
// example: spdlog::get("my_logger")->info("hello {}", "world");
@ -312,8 +327,10 @@ inline void critical(const wchar_t *fmt, const Args &... args)
//
#define SPDLOG_LOGGER_CALL(logger, level, ...) \
if (logger->should_log(level)) \
logger->log(spdlog::source_loc{SPDLOG_FILE_BASENAME(__FILE__), __LINE__, SPDLOG_FUNCTION}, level, __VA_ARGS__)
do { \
if (logger->should_log(level)) \
logger->log(spdlog::source_loc{SPDLOG_FILE_BASENAME(__FILE__), __LINE__, SPDLOG_FUNCTION}, level, __VA_ARGS__); \
} while (0)
#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_TRACE
#define SPDLOG_LOGGER_TRACE(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::trace, __VA_ARGS__)

@ -121,6 +121,13 @@
// "MY ERROR", "MY CRITICAL", "OFF" }
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to customize short level names (e.g. "MT")
// These can be longer than one character.
//
// #define SPDLOG_SHORT_LEVEL_NAMES { "T", "D", "I", "W", "E", "C", "O" }
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to disable default logger creation.
// This might save some (very) small initialization time if no default logger is needed.
@ -142,4 +149,4 @@
// Defaults to __FUNCTION__ (should work on all compilers) if not defined.
//
// #define SPDLOG_FUNCTION __PRETTY_FUNCTION__
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

@ -7,6 +7,6 @@
#define SPDLOG_VER_MAJOR 1
#define SPDLOG_VER_MINOR 3
#define SPDLOG_VER_PATCH 0
#define SPDLOG_VER_PATCH 1
#define SPDLOG_VERSION (SPDLOG_VER_MAJOR * 10000 + SPDLOG_VER_MINOR * 100 + SPDLOG_VER_PATCH)

@ -1,6 +1,6 @@
CXX ?= g++
CXXFLAGS = -Wall -pedantic -std=c++11 -pthread -Wconversion -O3 -I../include -fmax-errors=1
LDPFALGS = -pthread
LDPFALGS = -pthread -lsystemd
CPP_FILES := $(wildcard *.cpp)
OBJ_FILES := $(addprefix ./,$(notdir $(CPP_FILES:.cpp=.o)))

@ -60,7 +60,20 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
prepare_logdir();
size_t max_size = 1024 * 10;
std::string basename = "logs/rotating_log";
auto logger = spdlog::rotating_logger_mt("logger", basename, max_size, 1);
{
// make an initial logger to create the first output file
auto logger = spdlog::rotating_logger_mt("logger", basename, max_size, 2, true);
for (int i = 0; i < 10; ++i)
{
logger->info("Test message {}", i);
}
// drop causes the logger destructor to be called, which is required so the
// next logger can rename the first output file.
spdlog::drop(logger->name());
}
auto logger = spdlog::rotating_logger_mt("logger", basename, max_size, 2, true);
for (int i = 0; i < 10; ++i)
{
logger->info("Test message {}", i);

@ -0,0 +1,13 @@
#include "includes.h"
#include <spdlog/sinks/systemd_sink.h>
TEST_CASE("systemd", "[all]")
{
auto systemd_sink = std::make_shared<spdlog::sinks::systemd_sink_st>();
systemd_sink->set_level(spdlog::level::level_enum::err);
spdlog::logger logger("spdlog_systemd_test", systemd_sink);
logger.debug("test debug");
logger.error("test error");
logger.info("test info");
}
Loading…
Cancel
Save