Merged v1.x from upstream

pull/1322/head
Stefano Caiazza 6 years ago
commit f6a5bdde65

@ -63,31 +63,39 @@ option(SPDLOG_SANITIZE_ADDRESS "Enable address sanitizer in tests" OFF)
# install options
option(SPDLOG_INSTALL "Generate the install target" ${SPDLOG_MASTER_PROJECT})
option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" OFF)
option(SPDLOG_NO_EXCEPTIONS "Compile with -fno-exceptions. Call abort() on any spdlog exceptions" OFF)
# misc tweakme options
if(WIN32)
option(SPDLOG_WCHAR_SUPPORT "Support wchar api" OFF)
option(SPDLOG_WCHAR_FILENAMES "Support wchar filenames" OFF)
option(SPDLOG_WCHAR_SUPPORT "Support wchar api" OFF)
option(SPDLOG_WCHAR_FILENAMES "Support wchar filenames" OFF)
endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
option(SPDLOG_CLOCK_COARSE "Use the much faster (but much less accurate) CLOCK_REALTIME_COARSE instead of the regular clock," OFF)
endif()
option(SPDLOG_NO_EXCEPTIONS "Compile with -fno-exceptions. Call abort() on any spdlog exceptions" OFF)
option(SPDLOG_PREVENT_CHILD_FD "Prevent from child processes to inherit log file descriptors" OFF)
option(SPDLOG_NO_THREAD_ID "prevent spdlog from querying the thread id on each log call if thread id is not needed" OFF)
option(SPDLOG_NO_TLS "prevent spdlog from using thread local storage" OFF)
option(SPDLOG_NO_ATOMIC_LEVELS "prevent spdlog from using of std::atomic log levels (use only if your code never modifies log levels concurrently" OFF)
find_package(Threads REQUIRED)
message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
#---------------------------------------------------------------------------------------
# Static/Shared library (shared not supported in windows yet)
#---------------------------------------------------------------------------------------
set(SPDLOG_SRCS
src/spdlog.cpp
src/stdout_sinks.cpp
src/fmt.cpp
src/color_sinks.cpp
src/file_sinks.cpp
src/async.cpp)
set(SPDLOG_CFLAGS "${PROJECT_NAME}")
if(NOT SPDLOG_FMT_EXTERNAL)
list(APPEND SPDLOG_SRCS src/fmt.cpp)
endif()
if (SPDLOG_BUILD_SHARED)
if(WIN32)
@ -123,22 +131,24 @@ target_link_libraries(spdlog_header_only INTERFACE Threads::Threads)
#---------------------------------------------------------------------------------------
# Use fmt package if using exertnal fmt
# Use fmt package if using external fmt
#---------------------------------------------------------------------------------------
if(SPDLOG_FMT_EXTERNAL)
if (NOT TARGET fmt::fmt)
find_package(fmt REQUIRED)
endif ()
set(SPDLOG_CFLAGS "${SPDLOG_CFLAGS} -DSPDLOG_FMT_EXTERNAL")
target_compile_definitions(spdlog PUBLIC SPDLOG_FMT_EXTERNAL)
target_link_libraries(spdlog PUBLIC fmt::fmt)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_FMT_EXTERNAL)
target_link_libraries(spdlog_header_only INTERFACE fmt::fmt)
set(PKG_CONFIG_REQUIRES fmt) # add dependency to pkg-config
endif()
#---------------------------------------------------------------------------------------
# Misc definitions according to tweak options
#---------------------------------------------------------------------------------------
if(SPDLOG_WCHAR_SUPPORT)
target_compile_definitions(spdlog PUBLIC SPDLOG_WCHAR_TO_UTF8_SUPPORT)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_WCHAR_TO_UTF8_SUPPORT)
@ -159,6 +169,31 @@ if(SPDLOG_WCHAR_SUPPORT)
endif()
endif()
if(SPDLOG_CLOCK_COARSE)
target_compile_definitions(spdlog PRIVATE SPDLOG_CLOCK_COARSE)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_CLOCK_COARSE)
endif()
if(SPDLOG_PREVENT_CHILD_FD)
target_compile_definitions(spdlog PRIVATE SPDLOG_PREVENT_CHILD_FD)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_PREVENT_CHILD_FD)
endif()
if(SPDLOG_NO_THREAD_ID)
target_compile_definitions(spdlog PRIVATE SPDLOG_NO_THREAD_ID)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_NO_THREAD_ID)
endif()
if(SPDLOG_NO_TLS)
target_compile_definitions(spdlog PRIVATE SPDLOG_NO_TLS)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_NO_TLS)
endif()
if(SPDLOG_NO_ATOMIC_LEVELS)
target_compile_definitions(spdlog PUBLIC SPDLOG_NO_ATOMIC_LEVELS)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_NO_ATOMIC_LEVELS)
endif()
#---------------------------------------------------------------------------------------
# Build binaries
@ -188,7 +223,7 @@ if (SPDLOG_INSTALL)
set(project_config_out "${CMAKE_CURRENT_BINARY_DIR}/spdlogConfig.cmake")
set(config_targets_file "spdlogConfigTargets.cmake")
set(version_config_file "${CMAKE_CURRENT_BINARY_DIR}/spdlogConfigVersion.cmake")
set(export_dest_dir "${CMAKE_INSTALL_LIBDIR}/spdlog/cmake")
set(export_dest_dir "${CMAKE_INSTALL_LIBDIR}/cmake/spdlog")
set(pkgconfig_install_dir "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
set(pkg_config "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc")
@ -204,11 +239,17 @@ if (SPDLOG_INSTALL)
endif()
#---------------------------------------------------------------------------------------
# Package and version files
# Install pkg-config file
#---------------------------------------------------------------------------------------
get_target_property(PKG_CONFIG_DEFINES spdlog INTERFACE_COMPILE_DEFINITIONS)
string(REPLACE ";" " -D" PKG_CONFIG_DEFINES "${PKG_CONFIG_DEFINES}")
string(CONCAT PKG_CONFIG_DEFINES "-D" "${PKG_CONFIG_DEFINES}")
configure_file("cmake/${PROJECT_NAME}.pc.in" "${pkg_config}" @ONLY)
install(FILES "${pkg_config}" DESTINATION "${pkgconfig_install_dir}")
#---------------------------------------------------------------------------------------
# Install CMake config files
#---------------------------------------------------------------------------------------
install(EXPORT spdlog
DESTINATION ${export_dest_dir}
NAMESPACE spdlog::
@ -216,6 +257,7 @@ if (SPDLOG_INSTALL)
include(CMakePackageConfigHelpers)
configure_file("${project_config_in}" "${project_config_out}" @ONLY)
write_basic_package_version_file("${version_config_file}" COMPATIBILITY SameMajorVersion)
install(FILES
"${project_config_out}"
@ -227,3 +269,4 @@ if (SPDLOG_INSTALL)
include(cmake/spdlogCPack.cmake)
endif ()

@ -30,6 +30,8 @@ $ cmake .. && make -j
* Gentoo: `emerge dev-libs/spdlog`
* Arch Linux: `yaourt -S spdlog-git`
* vcpkg: `vcpkg install spdlog`
* conan: `spdlog/[>=1.4.1]@bincrafters/stable`
## Features
* Very fast (see [benchmarks](#benchmarks) below).

@ -24,5 +24,3 @@ target_link_libraries(latency PRIVATE benchmark::benchmark spdlog::spdlog)
add_executable(formatter-bench formatter-bench.cpp)
target_link_libraries(formatter-bench PRIVATE benchmark::benchmark spdlog::spdlog)
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs")

@ -16,26 +16,6 @@
#include "spdlog/sinks/null_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
void prepare_logdir()
{
spdlog::info("Preparing latency_logs directory..");
#ifdef _WIN32
system("if not exist logs mkdir latency_logs");
system("del /F /Q logs\\*");
#else
auto rv = system("mkdir -p latency_logs");
if (rv != 0)
{
throw std::runtime_error("Failed to mkdir -p latency_logs");
}
rv = system("rm -f latency_logs/*");
if (rv != 0)
{
throw std::runtime_error("Failed to rm -f latency_logs/*");
}
#endif
}
void bench_c_string(benchmark::State &state, std::shared_ptr<spdlog::logger> logger)
{
const char *msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pharetra metus cursus "
@ -83,8 +63,6 @@ int main(int argc, char *argv[])
size_t rotating_files = 5;
int n_threads = benchmark::CPUInfo::Get().num_cpus;
prepare_logdir();
// disabled loggers
auto disabled_logger = std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_mt>());
disabled_logger->set_level(spdlog::level::off);

@ -12,4 +12,3 @@ foreach i : bench_matrix
benchmark('bench_' + i[0], bench_exe, args: i[2])
endforeach
run_command(find_program('mkdir'), meson.current_build_dir() + '/logs')

@ -7,5 +7,7 @@ Name: lib@PROJECT_NAME@
Description: Fast C++ logging library.
URL: https://github.com/gabime/@PROJECT_NAME@
Version: @SPDLOG_VERSION@
CFlags: -I${includedir}/@SPDLOG_CFLAGS@
Libs: -L${libdir}/@PROJECT_NAME@ -l@PROJECT_NAME@
CFlags: -I${includedir} @PKG_CONFIG_DEFINES@
Libs: -L${libdir} -lspdlog -pthread
Requires: @PKG_CONFIG_REQUIRES@

@ -25,5 +25,3 @@ if(SPDLOG_BUILD_EXAMPLE_HO)
target_link_libraries(example_header_only PRIVATE spdlog::spdlog_header_only)
endif()
# Create logs directory
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs")

@ -143,7 +143,7 @@ void async_example()
#include "spdlog/fmt/bin_to_hex.h"
void binary_example()
{
std::vector<char> buf;
std::vector<char> buf(80);
for (int i = 0; i < 80; i++)
{
buf.push_back(static_cast<char>(i & 0xff));

@ -1,5 +1,4 @@
executable('example', 'example.cpp', dependencies: spdlog_dep)
executable('example_header_only', 'example.cpp', dependencies: spdlog_headeronly_dep)
run_command(find_program('mkdir'), meson.current_build_dir() + '/logs')

@ -6,7 +6,7 @@
//
// Async logging using global thread pool
// All loggers created here share same global thread pool.
// Each log message is pushed to a queue along withe a shared pointer to the
// Each log message is pushed to a queue along with a shared pointer to the
// logger.
// If a logger deleted while having pending messages in the queue, it's actual
// destruction will defer
@ -14,9 +14,9 @@
// This is because each message in the queue holds a shared_ptr to the
// originating logger.
#include "spdlog/async_logger.h"
#include "spdlog/details/registry.h"
#include "spdlog/details/thread_pool.h"
#include <spdlog/async_logger.h>
#include <spdlog/details/registry.h>
#include <spdlog/details/thread_pool.h>
#include <memory>
#include <mutex>

@ -4,11 +4,11 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/async_logger.h"
#include <spdlog/async_logger.h>
#endif
#include "spdlog/sinks/sink.h"
#include "spdlog/details/thread_pool.h"
#include <spdlog/sinks/sink.h>
#include <spdlog/details/thread_pool.h>
#include <memory>
#include <string>

@ -14,7 +14,7 @@
// Upon destruction, logs all remaining messages in the queue before
// destructing..
#include "spdlog/logger.h"
#include <spdlog/logger.h>
namespace spdlog {

@ -4,7 +4,7 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/common.h"
#include <spdlog/common.h>
#endif
namespace spdlog {

@ -3,8 +3,8 @@
#pragma once
#include "spdlog/tweakme.h"
#include "spdlog/details/null_mutex.h"
#include <spdlog/tweakme.h>
#include <spdlog/details/null_mutex.h>
#include <atomic>
#include <chrono>
@ -35,7 +35,7 @@
#define SPDLOG_INLINE inline
#endif
#include "spdlog/fmt/fmt.h"
#include <spdlog/fmt/fmt.h>
// visual studio upto 2013 does not support noexcept nor constexpr
#if defined(_MSC_VER) && (_MSC_VER < 1900)
@ -62,7 +62,7 @@
#endif
#ifndef SPDLOG_FUNCTION
#define SPDLOG_FUNCTION __FUNCTION__
#define SPDLOG_FUNCTION static_cast<const char *>(__FUNCTION__)
#endif
#ifdef SPDLOG_NO_EXCEPTIONS

@ -4,7 +4,7 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/details/backtracer.h"
#include <spdlog/details/backtracer.h>
#endif
namespace spdlog {
namespace details {
@ -26,7 +26,7 @@ SPDLOG_INLINE backtracer &backtracer::operator=(backtracer other)
{
std::lock_guard<std::mutex> lock(mutex_);
enabled_ = other.enabled();
messages_ = other.messages_;
messages_ = std::move(other.messages_);
return *this;
}
@ -48,11 +48,6 @@ SPDLOG_INLINE bool backtracer::enabled() const
return enabled_.load(std::memory_order_relaxed);
}
SPDLOG_INLINE backtracer::operator bool() const
{
return enabled();
}
SPDLOG_INLINE void backtracer::push_back(const log_msg &msg)
{
std::lock_guard<std::mutex> lock{mutex_};

@ -3,8 +3,8 @@
#pragma once
#include "spdlog/details/log_msg_buffer.h"
#include "spdlog/details/circular_q.h"
#include <spdlog/details/log_msg_buffer.h>
#include <spdlog/details/circular_q.h>
#include <atomic>
#include <mutex>
@ -31,7 +31,6 @@ public:
void enable(size_t size);
void disable();
bool enabled() const;
explicit operator bool() const;
void push_back(const log_msg &msg);
// pop all items in the q and apply the given fun on each of them.

@ -1,7 +1,7 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
// cirucal q view of std::vector.
// circular q view of std::vector.
#pragma once
#include <vector>
@ -72,6 +72,27 @@ public:
return v_[head_];
}
// Return number of elements actually stored
size_t size() const
{
if (tail_ >= head_)
{
return tail_ - head_;
}
else
{
return max_items_ - (head_ - tail_);
}
}
// Return const reference to item by index.
// If index is out of range 0…size()-1, the behavior is undefined.
const T &at(size_t i) const
{
assert(i < size());
return v_[(head_ + i) % max_items_];
}
// Pop item from front.
// If there are no elements in the container, the behavior is undefined.
void pop_front()

@ -3,7 +3,7 @@
#pragma once
#include "spdlog/details/null_mutex.h"
#include <spdlog/details/null_mutex.h>
#include <mutex>
namespace spdlog {

@ -4,11 +4,11 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/details/file_helper.h"
#include <spdlog/details/file_helper.h>
#endif
#include "spdlog/details/os.h"
#include "spdlog/common.h"
#include <spdlog/details/os.h>
#include <spdlog/common.h>
#include <cerrno>
#include <chrono>
@ -28,28 +28,31 @@ SPDLOG_INLINE file_helper::~file_helper()
SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate)
{
close();
filename_ = fname;
auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
_filename = fname;
for (int tries = 0; tries < open_tries; ++tries)
for (int tries = 0; tries < open_tries_; ++tries)
{
// create containing folder if not exists already.
os::create_dir(os::dir_name(fname));
if (!os::fopen_s(&fd_, fname, mode))
{
return;
}
details::os::sleep_for_millis(open_interval);
details::os::sleep_for_millis(open_interval_);
}
SPDLOG_THROW(spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno));
SPDLOG_THROW(spdlog_ex("Failed opening file " + os::filename_to_str(filename_) + " for writing", errno));
}
SPDLOG_INLINE void file_helper::reopen(bool truncate)
{
if (_filename.empty())
if (filename_.empty())
{
SPDLOG_THROW(spdlog_ex("Failed re opening file - was not opened before"));
}
open(_filename, truncate);
this->open(filename_, truncate);
}
SPDLOG_INLINE void file_helper::flush()
@ -72,7 +75,7 @@ SPDLOG_INLINE void file_helper::write(const memory_buf_t &buf)
auto data = buf.data();
if (std::fwrite(data, 1, msg_size, fd_) != msg_size)
{
SPDLOG_THROW(spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno));
SPDLOG_THROW(spdlog_ex("Failed writing to file " + os::filename_to_str(filename_), errno));
}
}
@ -80,19 +83,14 @@ SPDLOG_INLINE size_t file_helper::size() const
{
if (fd_ == nullptr)
{
SPDLOG_THROW(spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename)));
SPDLOG_THROW(spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(filename_)));
}
return os::filesize(fd_);
}
SPDLOG_INLINE const filename_t &file_helper::filename() const
{
return _filename;
}
SPDLOG_INLINE bool file_helper::file_exists(const filename_t &fname)
{
return os::file_exists(fname);
return filename_;
}
//
@ -119,7 +117,7 @@ SPDLOG_INLINE std::tuple<filename_t, filename_t> file_helper::split_by_extension
return std::make_tuple(fname, filename_t());
}
// treat casese like "/etc/rc.d/somelogfile or "/abc/.hiddenfile"
// treat cases like "/etc/rc.d/somelogfile or "/abc/.hiddenfile"
auto folder_index = fname.rfind(details::os::folder_sep);
if (folder_index != filename_t::npos && folder_index >= ext_index - 1)
{
@ -129,5 +127,6 @@ SPDLOG_INLINE std::tuple<filename_t, filename_t> file_helper::split_by_extension
// finally - return a valid base and extension tuple
return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index));
}
} // namespace details
} // namespace spdlog

@ -3,7 +3,7 @@
#pragma once
#include "spdlog/common.h"
#include <spdlog/common.h>
#include <tuple>
namespace spdlog {
@ -29,7 +29,6 @@ public:
void write(const memory_buf_t &buf);
size_t size() const;
const filename_t &filename() const;
static bool file_exists(const filename_t &fname);
//
// return file path and its extension:
@ -47,10 +46,10 @@ public:
static std::tuple<filename_t, filename_t> split_by_extension(const filename_t &fname);
private:
const int open_tries = 5;
const int open_interval = 10;
const int open_tries_ = 5;
const int open_interval_ = 10;
std::FILE *fd_{nullptr};
filename_t _filename;
filename_t filename_;
};
} // namespace details
} // namespace spdlog

@ -4,8 +4,8 @@
#include <chrono>
#include <type_traits>
#include "spdlog/fmt/fmt.h"
#include "spdlog/common.h"
#include <spdlog/fmt/fmt.h>
#include <spdlog/common.h>
// Some fmt helpers to efficiently format and pad ints and strings
namespace spdlog {

@ -4,10 +4,10 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/details/log_msg.h"
#include <spdlog/details/log_msg.h>
#endif
#include "spdlog/details/os.h"
#include <spdlog/details/os.h>
namespace spdlog {
namespace details {
@ -15,10 +15,7 @@ namespace details {
SPDLOG_INLINE log_msg::log_msg(spdlog::source_loc loc, string_view_t logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg)
: logger_name(logger_name)
, level(lvl)
#ifndef SPDLOG_NO_DATETIME
, time(os::now())
#endif
#ifndef SPDLOG_NO_THREAD_ID
, thread_id(os::thread_id())
#endif

@ -3,7 +3,7 @@
#pragma once
#include "spdlog/common.h"
#include <spdlog/common.h>
#include <string>
namespace spdlog {

@ -4,7 +4,7 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/details/log_msg_buffer.h"
#include <spdlog/details/log_msg_buffer.h>
#endif
namespace spdlog {
@ -26,9 +26,7 @@ SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg_buffer &other)
update_string_views();
}
SPDLOG_INLINE log_msg_buffer::log_msg_buffer(log_msg_buffer &&other)
: log_msg{std::move(other)}
, buffer{std::move(other.buffer)}
SPDLOG_INLINE log_msg_buffer::log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT : log_msg{other}, buffer{std::move(other.buffer)}
{
update_string_views();
}
@ -42,9 +40,9 @@ SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(const log_msg_buffer &ot
return *this;
}
SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(log_msg_buffer &&other)
SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT
{
log_msg::operator=(std::move(other));
log_msg::operator=(other);
buffer = std::move(other.buffer);
update_string_views();
return *this;

@ -3,7 +3,7 @@
#pragma once
#include "spdlog/details/log_msg.h"
#include <spdlog/details/log_msg.h>
namespace spdlog {
namespace details {
@ -20,9 +20,9 @@ public:
log_msg_buffer() = default;
explicit log_msg_buffer(const log_msg &orig_msg);
log_msg_buffer(const log_msg_buffer &other);
log_msg_buffer(log_msg_buffer &&other);
log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT;
log_msg_buffer &operator=(const log_msg_buffer &other);
log_msg_buffer &operator=(log_msg_buffer &&other);
log_msg_buffer &operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT;
};
} // namespace details

@ -10,7 +10,7 @@
// dequeue_for(..) - will block until the queue is not empty or timeout have
// passed.
#include "spdlog/details/circular_q.h"
#include <spdlog/details/circular_q.h>
#include <condition_variable>
#include <mutex>

@ -4,10 +4,10 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/details/os.h"
#include <spdlog/details/os.h>
#endif
#include "spdlog/common.h"
#include <spdlog/common.h>
#include <algorithm>
#include <chrono>
@ -42,6 +42,8 @@
#include <limits>
#endif
#include <direct.h> // for _mkdir/_wmkdir
#else // unix
#include <fcntl.h>
@ -91,17 +93,17 @@ SPDLOG_INLINE std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT
#ifdef _WIN32
std::tm tm;
localtime_s(&tm, &time_tt);
::localtime_s(&tm, &time_tt);
#else
std::tm tm;
localtime_r(&time_tt, &tm);
::localtime_r(&time_tt, &tm);
#endif
return tm;
}
SPDLOG_INLINE std::tm localtime() SPDLOG_NOEXCEPT
{
std::time_t now_t = time(nullptr);
std::time_t now_t = ::time(nullptr);
return localtime(now_t);
}
@ -110,52 +112,52 @@ SPDLOG_INLINE std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT
#ifdef _WIN32
std::tm tm;
gmtime_s(&tm, &time_tt);
::gmtime_s(&tm, &time_tt);
#else
std::tm tm;
gmtime_r(&time_tt, &tm);
::gmtime_r(&time_tt, &tm);
#endif
return tm;
}
SPDLOG_INLINE std::tm gmtime() SPDLOG_NOEXCEPT
{
std::time_t now_t = time(nullptr);
std::time_t now_t = ::time(nullptr);
return gmtime(now_t);
}
#ifdef SPDLOG_PREVENT_CHILD_FD
SPDLOG_INLINE void prevent_child_fd(FILE *f)
{
#ifdef _WIN32
#if !defined(__cplusplus_winrt)
auto file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(f)));
auto file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(::_fileno(f)));
if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0))
SPDLOG_THROW(spdlog_ex("SetHandleInformation failed", errno));
#endif
#else
auto fd = fileno(f);
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
auto fd = ::fileno(f);
if (::fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
{
SPDLOG_THROW(spdlog_ex("fcntl with FD_CLOEXEC failed", errno));
}
#endif
}
#endif // SPDLOG_PREVENT_CHILD_FD
// 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);
*fp = ::_wfsopen((filename.c_str()), mode.c_str(), _SH_DENYNO);
#else
*fp = _fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO);
*fp = ::_fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO);
#endif
#else // unix
*fp = fopen((filename.c_str()), mode.c_str());
*fp = ::fopen((filename.c_str()), mode.c_str());
#endif
#ifdef SPDLOG_PREVENT_CHILD_FD
// prevent child processes from inheriting log file descriptors
if (*fp != nullptr)
{
prevent_child_fd(*fp);
@ -167,7 +169,7 @@ SPDLOG_INLINE bool fopen_s(FILE **fp, const filename_t &filename, const filename
SPDLOG_INLINE int remove(const filename_t &filename) SPDLOG_NOEXCEPT
{
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
return _wremove(filename.c_str());
return ::_wremove(filename.c_str());
#else
return std::remove(filename.c_str());
#endif
@ -175,28 +177,28 @@ SPDLOG_INLINE int remove(const filename_t &filename) SPDLOG_NOEXCEPT
SPDLOG_INLINE int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT
{
return file_exists(filename) ? remove(filename) : 0;
return path_exists(filename) ? remove(filename) : 0;
}
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());
return ::_wrename(filename1.c_str(), filename2.c_str());
#else
return std::rename(filename1.c_str(), filename2.c_str());
#endif
}
// Return true if file exists
SPDLOG_INLINE bool file_exists(const filename_t &filename) SPDLOG_NOEXCEPT
// Return true if path exists (file or directory)
SPDLOG_INLINE bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT
{
#ifdef _WIN32
#ifdef SPDLOG_WCHAR_FILENAMES
auto attribs = GetFileAttributesW(filename.c_str());
auto attribs = ::GetFileAttributesW(filename.c_str());
#else
auto attribs = GetFileAttributesA(filename.c_str());
auto attribs = ::GetFileAttributesA(filename.c_str());
#endif
return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY));
return attribs != INVALID_FILE_ATTRIBUTES;
#else // common linux/unix all have the stat system call
struct stat buffer;
return (::stat(filename.c_str(), &buffer) == 0);
@ -211,16 +213,16 @@ SPDLOG_INLINE size_t filesize(FILE *f)
SPDLOG_THROW(spdlog_ex("Failed getting file size. fd is null"));
}
#if defined(_WIN32) && !defined(__CYGWIN__)
int fd = _fileno(f);
int fd = ::_fileno(f);
#if _WIN64 // 64 bits
__int64 ret = _filelengthi64(fd);
__int64 ret = ::_filelengthi64(fd);
if (ret >= 0)
{
return static_cast<size_t>(ret);
}
#else // windows 32 bits
long ret = _filelength(fd);
long ret = ::_filelength(fd);
if (ret >= 0)
{
return static_cast<size_t>(ret);
@ -228,7 +230,7 @@ SPDLOG_INLINE size_t filesize(FILE *f)
#endif
#else // unix
int fd = fileno(f);
int fd = ::fileno(f);
// 64 bits(but not in osx or cygwin, where fstat64 is deprecated)
#if (defined(__linux__) || defined(__sun) || defined(_AIX)) && (defined(__LP64__) || defined(_LP64))
struct stat64 st;
@ -236,9 +238,8 @@ SPDLOG_INLINE size_t filesize(FILE *f)
{
return static_cast<size_t>(st.st_size);
}
#else // unix 32 bits or cygwin
#else // other unix or linux 32 bits or cygwin
struct stat st;
if (::fstat(fd, &st) == 0)
{
return static_cast<size_t>(st.st_size);
@ -255,10 +256,10 @@ 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);
auto rv = ::GetTimeZoneInformation(&tzinfo);
#else
DYNAMIC_TIME_ZONE_INFORMATION tzinfo;
auto rv = GetDynamicTimeZoneInformation(&tzinfo);
auto rv = ::GetDynamicTimeZoneInformation(&tzinfo);
#endif
if (rv == TIME_ZONE_ID_INVALID)
SPDLOG_THROW(spdlog::spdlog_ex("Failed getting timezone info. ", errno));
@ -275,7 +276,7 @@ SPDLOG_INLINE int utc_minutes_offset(const std::tm &tm)
return offset;
#else
#if defined(sun) || defined(__sun) || defined(_AIX)
#if defined(sun) || defined(__sun) || defined(_AIX) || (!defined(_BSD_SOURCE) && !defined(_GNU_SOURCE))
// 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris
struct helper
{
@ -324,15 +325,15 @@ SPDLOG_INLINE size_t _thread_id() SPDLOG_NOEXCEPT
#if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21)
#define SYS_gettid __NR_gettid
#endif
return static_cast<size_t>(syscall(SYS_gettid));
return static_cast<size_t>(::syscall(SYS_gettid));
#elif defined(_AIX) || defined(__DragonFly__) || defined(__FreeBSD__)
return static_cast<size_t>(pthread_getthreadid_np());
return static_cast<size_t>(::pthread_getthreadid_np());
#elif defined(__NetBSD__)
return static_cast<size_t>(_lwp_self());
return static_cast<size_t>(::_lwp_self());
#elif defined(__OpenBSD__)
return static_cast<size_t>(getthrid());
return static_cast<size_t>(::getthrid());
#elif defined(__sun)
return static_cast<size_t>(thr_self());
return static_cast<size_t>(::thr_self());
#elif __APPLE__
uint64_t tid;
pthread_threadid_np(nullptr, &tid);
@ -417,16 +418,16 @@ SPDLOG_INLINE bool in_terminal(FILE *file) SPDLOG_NOEXCEPT
{
#ifdef _WIN32
return _isatty(_fileno(file)) != 0;
return ::_isatty(_fileno(file)) != 0;
#else
return isatty(fileno(file)) != 0;
return ::isatty(fileno(file)) != 0;
#endif
}
#if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)
SPDLOG_INLINE void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target)
{
if (wstr.size() > static_cast<size_t>(std::numeric_limits<int>::max()))
if (wstr.size() > static_cast<size_t>((std::numeric_limits<int>::max)()))
{
SPDLOG_THROW(spdlog::spdlog_ex("UTF-16 string is too big to be converted to UTF-8"));
}
@ -460,6 +461,76 @@ SPDLOG_INLINE void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target)
}
#endif // (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)
// return true on success
SPDLOG_INLINE bool mkdir_(const filename_t &path)
{
#ifdef _WIN32
#ifdef SPDLOG_WCHAR_FILENAMES
return ::_wmkdir(path.c_str()) == 0;
#else
return ::_mkdir(path.c_str()) == 0;
#endif
#else
return ::mkdir(path.c_str(), mode_t(0755)) == 0;
#endif
}
// create the given directory - and all directories leading to it
// return true on success or if the directory already exists
SPDLOG_INLINE bool create_dir(filename_t path)
{
if (path_exists(path))
{
return true;
}
if (path.empty())
{
return false;
}
#ifdef _WIN32
// support forward slash in windows
std::replace(path.begin(), path.end(), '/', folder_sep);
#endif
size_t search_offset = 0;
do
{
auto token_pos = path.find(folder_sep, search_offset);
// treat the entire path as a folder if no folder separator not found
if (token_pos == filename_t::npos)
{
token_pos = path.size();
}
auto subdir = path.substr(0, token_pos);
if (!subdir.empty() && !path_exists(subdir) && !mkdir_(subdir))
{
return false; // return error if failed creating dir
}
search_offset = token_pos + 1;
} while (search_offset < path.size());
return true;
}
// Return directory name from given path or empty string
// "abc/file" => "abc"
// "abc/" => "abc"
// "abc" => ""
// "abc///" => "abc//"
SPDLOG_INLINE filename_t dir_name(filename_t path)
{
#ifdef _WIN32
// support forward slash in windows
std::replace(path.begin(), path.end(), '/', folder_sep);
#endif
auto pos = path.find_last_of(folder_sep);
return pos != filename_t::npos ? path.substr(0, pos) : filename_t{};
}
} // namespace os
} // namespace details
} // namespace spdlog

@ -3,7 +3,7 @@
#pragma once
#include "spdlog/common.h"
#include <spdlog/common.h>
#include <ctime> // std::time_t
namespace spdlog {
@ -33,12 +33,14 @@ SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL;
// folder separator
#ifdef _WIN32
const char folder_sep = '\\';
static const char folder_sep = '\\';
#else
SPDLOG_CONSTEXPR static const char folder_sep = '/';
#endif
#ifdef SPDLOG_PREVENT_CHILD_FD
void prevent_child_fd(FILE *f);
#endif
// fopen_s on non windows for writing
bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode);
@ -53,7 +55,7 @@ int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT;
int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT;
// Return if file exists.
bool file_exists(const filename_t &filename) SPDLOG_NOEXCEPT;
bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT;
// Return file size according to open FILE* object
size_t filesize(FILE *f);
@ -81,7 +83,7 @@ int pid() SPDLOG_NOEXCEPT;
// Source: https://github.com/agauniyal/rang/
bool is_color_terminal() SPDLOG_NOEXCEPT;
// Detrmine if the terminal attached
// Determine if the terminal attached
// Source: https://github.com/agauniyal/rang/
bool in_terminal(FILE *file) SPDLOG_NOEXCEPT;
@ -89,6 +91,17 @@ bool in_terminal(FILE *file) SPDLOG_NOEXCEPT;
void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target);
#endif
// Return directory name from given path or empty string
// "abc/file" => "abc"
// "abc/" => "abc"
// "abc" => ""
// "abc///" => "abc//"
filename_t dir_name(filename_t path);
// Create a dir from the given path.
// Return true if succeeded or if this dir already exists.
bool create_dir(filename_t path);
} // namespace os
} // namespace details
} // namespace spdlog

@ -4,14 +4,14 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/details/pattern_formatter.h"
#include <spdlog/details/pattern_formatter.h>
#endif
#include "spdlog/details/fmt_helper.h"
#include "spdlog/details/log_msg.h"
#include "spdlog/details/os.h"
#include "spdlog/fmt/fmt.h"
#include "spdlog/formatter.h"
#include <spdlog/details/fmt_helper.h>
#include <spdlog/details/log_msg.h>
#include <spdlog/details/os.h>
#include <spdlog/fmt/fmt.h>
#include <spdlog/formatter.h>
#include <array>
#include <chrono>
@ -39,47 +39,50 @@ public:
: padinfo_(padinfo)
, dest_(dest)
{
if (padinfo_.width_ <= wrapped_size)
remaining_pad_ = static_cast<long>(padinfo.width_) - static_cast<long>(wrapped_size);
if (remaining_pad_ <= 0)
{
total_pad_ = 0;
return;
}
total_pad_ = padinfo.width_ - wrapped_size;
if (padinfo_.side_ == padding_info::left)
{
pad_it(total_pad_);
total_pad_ = 0;
pad_it(remaining_pad_);
remaining_pad_ = 0;
}
else if (padinfo_.side_ == padding_info::center)
{
auto half_pad = total_pad_ / 2;
auto reminder = total_pad_ & 1;
auto half_pad = remaining_pad_ / 2;
auto reminder = remaining_pad_ & 1;
pad_it(half_pad);
total_pad_ = half_pad + reminder; // for the right side
remaining_pad_ = half_pad + reminder; // for the right side
}
}
~scoped_padder()
{
if (total_pad_)
if (remaining_pad_ >= 0)
{
pad_it(remaining_pad_);
}
else if (padinfo_.truncate_)
{
pad_it(total_pad_);
long new_size = static_cast<long>(dest_.size()) + remaining_pad_;
dest_.resize(static_cast<size_t>(new_size));
}
}
private:
void pad_it(size_t count)
void pad_it(long count)
{
// count = std::min(count, spaces_.size());
assert(count <= spaces_.size());
// assert(count <= spaces_.size());
fmt_helper::append_string_view(string_view_t(spaces_.data(), count), dest_);
}
const padding_info &padinfo_;
memory_buf_t &dest_;
size_t total_pad_;
long remaining_pad_;
string_view_t spaces_{" ", 64};
};
@ -593,14 +596,7 @@ public:
const size_t field_size = 6;
ScopedPadder p(field_size, padinfo_, dest);
#ifdef _WIN32
int total_minutes = get_cached_offset(msg, tm_time);
#else
// No need to chache under gcc,
// it is very fast (already stored in tm.tm_gmtoff)
(void)(msg);
int total_minutes = os::utc_minutes_offset(tm_time);
#endif
auto total_minutes = get_cached_offset(msg, tm_time);
bool is_negative = total_minutes < 0;
if (is_negative)
{
@ -619,7 +615,6 @@ public:
private:
log_clock::time_point last_update_{std::chrono::seconds(0)};
#ifdef _WIN32
int offset_minutes_{0};
int get_cached_offset(const log_msg &msg, const std::tm &tm_time)
@ -632,7 +627,6 @@ private:
}
return offset_minutes_;
}
#endif
};
// Thread id
@ -885,7 +879,7 @@ public:
fmt_helper::pad6(static_cast<size_t>(delta_units.count()), dest);
}
protected:
private:
log_clock::time_point last_message_time_;
};
@ -904,8 +898,6 @@ public:
using std::chrono::milliseconds;
using std::chrono::seconds;
#ifndef SPDLOG_NO_DATETIME
// cache the date/time part for the next second.
auto duration = msg.time.time_since_epoch();
auto secs = duration_cast<seconds>(duration);
@ -941,10 +933,6 @@ public:
dest.push_back(']');
dest.push_back(' ');
#else // no datetime needed
(void)tm_time;
#endif
#ifndef SPDLOG_NO_NAME
if (msg.logger_name.size() > 0)
{
@ -1014,14 +1002,13 @@ SPDLOG_INLINE std::unique_ptr<formatter> pattern_formatter::clone() const
SPDLOG_INLINE void pattern_formatter::format(const details::log_msg &msg, memory_buf_t &dest)
{
#ifndef SPDLOG_NO_DATETIME
auto secs = std::chrono::duration_cast<std::chrono::seconds>(msg.time.time_since_epoch());
if (secs != last_log_secs_)
{
cached_tm_ = get_time_(msg);
last_log_secs_ = secs;
}
#endif
for (auto &f : formatters_)
{
f->format(msg, cached_tm_, dest);
@ -1225,7 +1212,7 @@ SPDLOG_INLINE void pattern_formatter::handle_flag_(char flag, details::padding_i
}
}
// Extract given pad spec (e.g. %8X)
// Extract given pad spec (e.g. %8X, %=8X, %-8!X, %8!X, %=8!X, %-8!X, %+8!X)
// Advance the given it pass the end of the padding spec found (if any)
// Return padding.
SPDLOG_INLINE details::padding_info pattern_formatter::handle_padspec_(std::string::const_iterator &it, std::string::const_iterator end)
@ -1256,7 +1243,7 @@ SPDLOG_INLINE details::padding_info pattern_formatter::handle_padspec_(std::stri
if (it == end || !std::isdigit(static_cast<unsigned char>(*it)))
{
return padding_info{0, side};
return padding_info{}; // no padding if no digit found here
}
auto width = static_cast<size_t>(*it) - '0';
@ -1265,7 +1252,20 @@ SPDLOG_INLINE details::padding_info pattern_formatter::handle_padspec_(std::stri
auto digit = static_cast<size_t>(*it) - '0';
width = width * 10 + digit;
}
return details::padding_info{std::min<size_t>(width, max_width), side};
// search for the optional truncate marker '!'
bool truncate;
if (it != end && *it == '!')
{
truncate = true;
++it;
}
else
{
truncate = false;
}
return details::padding_info{std::min<size_t>(width, max_width), side, truncate};
}
SPDLOG_INLINE void pattern_formatter::compile_pattern_(const std::string &pattern)

@ -3,10 +3,10 @@
#pragma once
#include "spdlog/common.h"
#include "spdlog/details/log_msg.h"
#include "spdlog/details/os.h"
#include "spdlog/formatter.h"
#include <spdlog/common.h>
#include <spdlog/details/log_msg.h>
#include <spdlog/details/os.h>
#include <spdlog/formatter.h>
#include <chrono>
#include <ctime>
@ -29,17 +29,21 @@ struct padding_info
};
padding_info() = default;
padding_info(size_t width, padding_info::pad_side side)
padding_info(size_t width, padding_info::pad_side side, bool truncate)
: width_(width)
, side_(side)
, truncate_(truncate)
, enabled_(true)
{}
bool enabled() const
{
return width_ != 0;
return enabled_;
}
const size_t width_ = 0;
const pad_side side_ = left;
bool truncate_ = false;
bool enabled_ = false;
};
class flag_formatter

@ -4,7 +4,7 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/details/periodic_worker.h"
#include <spdlog/details/periodic_worker.h>
#endif
namespace spdlog {

@ -7,16 +7,17 @@
#include "spdlog/details/registry.h"
#endif
#include "spdlog/common.h"
#include "spdlog/logger.h"
#include "spdlog/details/pattern_formatter.h"
#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
#ifdef _WIN32
#include "spdlog/sinks/wincolor_sink.h"
#include <spdlog/sinks/wincolor_sink.h>
#else
#include "spdlog/sinks/ansicolor_sink.h"
#include <spdlog/sinks/ansicolor_sink.h>
#endif
#endif // SPDLOG_DISABLE_DEFAULT_LOGGER
@ -256,10 +257,10 @@ SPDLOG_INLINE std::recursive_mutex &registry::tp_mutex()
return tp_mutex_;
}
SPDLOG_INLINE void registry::set_automatic_registration(bool automatic_regsistration)
SPDLOG_INLINE void registry::set_automatic_registration(bool automatic_registration)
{
std::lock_guard<std::mutex> lock(logger_map_mutex_);
automatic_registration_ = automatic_regsistration;
automatic_registration_ = automatic_registration;
}
SPDLOG_INLINE registry &registry::instance()

@ -8,8 +8,7 @@
// If user requests a non existing logger, nullptr will be returned
// This class is thread safe
#include "spdlog/common.h"
#include "spdlog/details/periodic_worker.h"
#include <spdlog/common.h>
#include <chrono>
#include <functional>
@ -82,7 +81,7 @@ public:
std::recursive_mutex &tp_mutex();
void set_automatic_registration(bool automatic_regsistration);
void set_automatic_registration(bool automatic_registration);
// Factory function to create a new logger and register it in this registry
template<typename Sink, typename... SinkArgs>

@ -4,10 +4,10 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/details/thread_pool.h"
#include <spdlog/details/thread_pool.h>
#endif
#include "spdlog/common.h"
#include <spdlog/common.h>
namespace spdlog {
namespace details {
@ -98,24 +98,20 @@ bool SPDLOG_INLINE thread_pool::process_next_msg_()
switch (incoming_async_msg.msg_type)
{
case async_msg_type::log:
{
case async_msg_type::log: {
incoming_async_msg.worker_ptr->backend_sink_it_(incoming_async_msg);
return true;
}
case async_msg_type::flush:
{
case async_msg_type::flush: {
incoming_async_msg.worker_ptr->backend_flush_();
return true;
}
case async_msg_type::terminate:
{
case async_msg_type::terminate: {
return false;
}
default:
{
default: {
assert(false && "Unexpected async_msg_type");
}
}

@ -3,9 +3,9 @@
#pragma once
#include "spdlog/details/log_msg_buffer.h"
#include "spdlog/details/mpmc_blocking_q.h"
#include "spdlog/details/os.h"
#include <spdlog/details/log_msg_buffer.h>
#include <spdlog/details/mpmc_blocking_q.h>
#include <spdlog/details/os.h>
#include <chrono>
#include <memory>
@ -27,7 +27,7 @@ enum class async_msg_type
terminate
};
#include "spdlog/details/log_msg_buffer.h"
#include <spdlog/details/log_msg_buffer.h>
// Async msg to move to/from the queue
// Movable only. should never be copied
struct async_msg : log_msg_buffer

@ -22,6 +22,6 @@
#include "bundled/core.h"
#include "bundled/format.h"
#else // SPDLOG_FMT_EXTERNAL is defined - use external fmtlib
#include "fmt/core.h"
#include "fmt/format.h"
#include <fmt/core.h>
#include <fmt/format.h>
#endif

@ -3,8 +3,8 @@
#pragma once
#include "fmt/fmt.h"
#include "spdlog/details/log_msg.h"
#include <spdlog/fmt/fmt.h>
#include <spdlog/details/log_msg.h>
namespace spdlog {

@ -4,12 +4,12 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/logger.h"
#include <spdlog/logger.h>
#endif
#include "spdlog/sinks/sink.h"
#include "spdlog/details/backtracer.h"
#include "spdlog/details/pattern_formatter.h"
#include <spdlog/sinks/sink.h>
#include <spdlog/details/backtracer.h>
#include <spdlog/details/pattern_formatter.h>
#include <cstdio>
@ -64,11 +64,6 @@ SPDLOG_INLINE void swap(logger &a, logger &b)
a.swap(b);
}
SPDLOG_INLINE bool logger::should_log(level::level_enum msg_level) const
{
return msg_level >= level_.load(std::memory_order_relaxed);
}
SPDLOG_INLINE void logger::set_level(level::level_enum log_level)
{
level_.store(log_level);
@ -85,7 +80,7 @@ SPDLOG_INLINE const std::string &logger::name() const
}
// set formatting for the sinks in this logger.
// each sink will get a seperate instance of the formatter object.
// each sink will get a separate instance of the formatter object.
SPDLOG_INLINE void logger::set_formatter(std::unique_ptr<formatter> f)
{
for (auto it = sinks_.begin(); it != sinks_.end(); ++it)
@ -155,7 +150,7 @@ SPDLOG_INLINE std::vector<sink_ptr> &logger::sinks()
// error handler
SPDLOG_INLINE void logger::set_error_handler(err_handler handler)
{
custom_err_handler_ = handler;
custom_err_handler_ = std::move(handler);
}
// create new logger with same sinks and configuration.
@ -167,6 +162,18 @@ SPDLOG_INLINE std::shared_ptr<logger> logger::clone(std::string logger_name)
}
// protected methods
SPDLOG_INLINE void logger::log_it_(const spdlog::details::log_msg &log_msg, bool log_enabled, bool traceback_enabled)
{
if (log_enabled)
{
sink_it_(log_msg);
}
if (traceback_enabled)
{
tracer_.push_back(log_msg);
}
}
SPDLOG_INLINE void logger::sink_it_(const details::log_msg &msg)
{
for (auto &sink : sinks_)
@ -202,7 +209,7 @@ SPDLOG_INLINE void logger::flush_()
SPDLOG_INLINE void logger::dump_backtrace_()
{
using details::log_msg;
if (tracer_)
if (tracer_.enabled())
{
sink_it_(log_msg{name(), level::info, "****************** Backtrace Start ******************"});
tracer_.foreach_pop([this](const log_msg &msg) { this->sink_it_(msg); });

@ -14,12 +14,12 @@
// The use of private formatter per sink provides the opportunity to cache some
// formatted data, and support for different format per sink.
#include "spdlog/common.h"
#include "spdlog/details/log_msg.h"
#include "spdlog/details/backtracer.h"
#include <spdlog/common.h>
#include <spdlog/details/log_msg.h>
#include <spdlog/details/backtracer.h>
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
#include "spdlog/details/os.h"
#include <spdlog/details/os.h>
#endif
#include <vector>
@ -76,8 +76,9 @@ public:
template<typename... Args>
void log(source_loc loc, level::level_enum lvl, string_view_t fmt, const Args &... args)
{
auto level_enabled = should_log(lvl);
if (!level_enabled && !tracer_)
bool log_enabled = should_log(lvl);
bool traceback_enabled = tracer_.enabled();
if (!log_enabled && !traceback_enabled)
{
return;
}
@ -86,14 +87,7 @@ public:
memory_buf_t buf;
fmt::format_to(buf, fmt, args...);
details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()));
if (level_enabled)
{
sink_it_(log_msg);
}
if (tracer_)
{
tracer_.push_back(log_msg);
}
log_it_(log_msg, log_enabled, traceback_enabled);
}
SPDLOG_LOGGER_CATCH()
}
@ -150,24 +144,15 @@ public:
template<class T, typename std::enable_if<std::is_convertible<const T &, spdlog::string_view_t>::value, T>::type * = nullptr>
void log(source_loc loc, level::level_enum lvl, const T &msg)
{
auto level_enabled = should_log(lvl);
if (!level_enabled && !tracer_)
bool log_enabled = should_log(lvl);
bool traceback_enabled = tracer_.enabled();
if (!log_enabled && !traceback_enabled)
{
return;
}
SPDLOG_TRY
{
details::log_msg log_msg(loc, name_, lvl, msg);
if (level_enabled)
{
sink_it_(log_msg);
}
if (tracer_)
{
tracer_.push_back(log_msg);
}
}
SPDLOG_LOGGER_CATCH()
details::log_msg log_msg(loc, name_, lvl, msg);
log_it_(log_msg, log_enabled, traceback_enabled);
}
void log(level::level_enum lvl, string_view_t msg)
@ -228,8 +213,9 @@ public:
template<typename... Args>
void log(source_loc loc, level::level_enum lvl, wstring_view_t fmt, const Args &... args)
{
auto level_enabled = should_log(lvl);
if (!level_enabled && !tracer_)
bool log_enabled = should_log(lvl);
bool traceback_enabled = tracer_.enabled();
if (!log_enabled && !traceback_enabled)
{
return;
}
@ -242,15 +228,7 @@ public:
memory_buf_t buf;
details::os::wstr_to_utf8buf(wstring_view_t(wbuf.data(), wbuf.size()), buf);
details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()));
if (level_enabled)
{
sink_it_(log_msg);
}
if (tracer_)
{
tracer_.push_back(log_msg);
}
log_it_(log_msg, log_enabled, traceback_enabled);
}
SPDLOG_LOGGER_CATCH()
}
@ -301,25 +279,36 @@ public:
template<class T, typename std::enable_if<is_convertible_to_wstring_view<const T &>::value, T>::type * = nullptr>
void log(source_loc loc, level::level_enum lvl, const T &msg)
{
if (!should_log(lvl))
bool log_enabled = should_log(lvl);
bool traceback_enabled = tracer_.enabled();
if (!log_enabled && !traceback_enabled)
{
return;
}
try
SPDLOG_TRY
{
memory_buf_t buf;
details::os::wstr_to_utf8buf(msg, buf);
details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()));
sink_it_(log_msg);
log_it_(log_msg, log_enabled, traceback_enabled);
}
SPDLOG_LOGGER_CATCH()
}
#endif // _WIN32
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
bool should_log(level::level_enum msg_level) const;
// return true logging is enabled for the given level.
bool should_log(level::level_enum msg_level) const
{
return msg_level >= level_.load(std::memory_order_relaxed);
}
// return true if backtrace logging is enabled.
bool should_backtrace() const
{
return tracer_.enabled();
}
void set_level(level::level_enum log_level);
@ -328,7 +317,7 @@ public:
const std::string &name() const;
// set formatting for the sinks in this logger.
// each sink will get a seperate instance of the formatter object.
// each sink will get a separate instance of the formatter object.
void set_formatter(std::unique_ptr<formatter> f);
void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local);
@ -363,6 +352,9 @@ protected:
err_handler custom_err_handler_{nullptr};
details::backtracer tracer_;
// log the given message (if the given log level is high enough),
// and save backtrace (if backtrace is enabled).
void log_it_(const details::log_msg &log_msg, bool log_enabled, bool traceback_enabled);
virtual void sink_it_(const details::log_msg &msg);
virtual void flush_();
void dump_backtrace_();

@ -5,11 +5,11 @@
#ifdef __ANDROID__
#include "spdlog/details/fmt_helper.h"
#include "spdlog/details/null_mutex.h"
#include "spdlog/details/os.h"
#include "spdlog/sinks/base_sink.h"
#include "spdlog/details/synchronous_factory.h"
#include <spdlog/details/fmt_helper.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/details/os.h>
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/synchronous_factory.h>
#include <android/log.h>
#include <chrono>

@ -4,11 +4,11 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/sinks/ansicolor_sink.h"
#include <spdlog/sinks/ansicolor_sink.h>
#endif
#include "spdlog/details/pattern_formatter.h"
#include "spdlog/details/os.h"
#include <spdlog/details/pattern_formatter.h>
#include <spdlog/details/os.h>
namespace spdlog {
namespace sinks {

@ -3,9 +3,9 @@
#pragma once
#include "spdlog/details/console_globals.h"
#include "spdlog/details/null_mutex.h"
#include "spdlog/sinks/sink.h"
#include <spdlog/details/console_globals.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/sinks/sink.h>
#include <memory>
#include <mutex>
#include <string>

@ -4,11 +4,11 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/sinks/base_sink.h"
#include <spdlog/sinks/base_sink.h>
#endif
#include "spdlog/common.h"
#include "spdlog/details/pattern_formatter.h"
#include <spdlog/common.h>
#include <spdlog/details/pattern_formatter.h>
#include <memory>

@ -9,9 +9,9 @@
// implementers..
//
#include "spdlog/common.h"
#include "spdlog/details/log_msg.h"
#include "spdlog/sinks/sink.h"
#include <spdlog/common.h>
#include <spdlog/details/log_msg.h>
#include <spdlog/sinks/sink.h>
namespace spdlog {
namespace sinks {

@ -4,11 +4,11 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/sinks/basic_file_sink.h"
#include <spdlog/sinks/basic_file_sink.h>
#endif
#include "spdlog/common.h"
#include "spdlog/details/os.h"
#include <spdlog/common.h>
#include <spdlog/details/os.h>
namespace spdlog {
namespace sinks {

@ -3,10 +3,10 @@
#pragma once
#include "spdlog/details/file_helper.h"
#include "spdlog/details/null_mutex.h"
#include "spdlog/sinks/base_sink.h"
#include "spdlog/details/synchronous_factory.h"
#include <spdlog/details/file_helper.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/synchronous_factory.h>
#include <mutex>
#include <string>

@ -3,13 +3,13 @@
#pragma once
#include "spdlog/common.h"
#include "spdlog/details/file_helper.h"
#include "spdlog/details/null_mutex.h"
#include "spdlog/fmt/fmt.h"
#include "spdlog/sinks/base_sink.h"
#include "spdlog/details/os.h"
#include "spdlog/details/synchronous_factory.h"
#include <spdlog/common.h>
#include <spdlog/details/file_helper.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/fmt/fmt.h>
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/os.h>
#include <spdlog/details/synchronous_factory.h>
#include <chrono>
#include <cstdio>
@ -78,12 +78,7 @@ public:
protected:
void sink_it_(const details::log_msg &msg) override
{
#ifdef SPDLOG_NO_DATETIME
auto time = log_clock::now();
#else
auto time = msg.time;
#endif
bool should_rotate = time >= rotation_tp_;
if (should_rotate)
{
@ -95,7 +90,7 @@ protected:
base_sink<Mutex>::formatter_->format(msg, formatted);
file_helper_.write(formatted);
// Do the cleaning ony at the end because it might throw on failure.
// Do the cleaning only at the end because it might throw on failure.
if (should_rotate && max_files_ > 0)
{
delete_old_();

@ -4,9 +4,9 @@
#pragma once
#include "base_sink.h"
#include "spdlog/details/log_msg.h"
#include "spdlog/details/null_mutex.h"
#include "spdlog/details/pattern_formatter.h"
#include <spdlog/details/log_msg.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/details/pattern_formatter.h>
#include <algorithm>
#include <memory>

@ -4,8 +4,8 @@
#pragma once
#include "dist_sink.h"
#include "spdlog/details/null_mutex.h"
#include "spdlog/details/log_msg.h"
#include <spdlog/details/null_mutex.h>
#include <spdlog/details/log_msg.h>
#include <mutex>
#include <string>
@ -16,7 +16,7 @@
//
// Example:
//
// #include "spdlog/sinks/dup_filter_sink.h"
// #include <spdlog/sinks/dup_filter_sink.h>
//
// int main() {
// auto dup_filter = std::make_shared<dup_filter_sink_st>(std::chrono::seconds(5));
@ -33,10 +33,6 @@
// [2019-06-25 17:50:56.512] [logger] [info] Skipped 3 duplicate messages..
// [2019-06-25 17:50:56.512] [logger] [info] Different Hello
#ifdef SPDLOG_NO_DATETIME
#error "spdlog::sinks::dup_filter_sink: cannot work when SPDLOG_NO_DATETIME is defined"
#endif
namespace spdlog {
namespace sinks {
template<typename Mutex>

@ -5,8 +5,8 @@
#if defined(_WIN32)
#include "spdlog/details/null_mutex.h"
#include "spdlog/sinks/base_sink.h"
#include <spdlog/details/null_mutex.h>
#include <spdlog/sinks/base_sink.h>
#include <winbase.h>

@ -3,9 +3,9 @@
#pragma once
#include "spdlog/details/null_mutex.h"
#include "spdlog/sinks/base_sink.h"
#include "spdlog/details/synchronous_factory.h"
#include <spdlog/details/null_mutex.h>
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/synchronous_factory.h>
#include <mutex>

@ -3,8 +3,8 @@
#pragma once
#include "spdlog/details/null_mutex.h"
#include "spdlog/sinks/base_sink.h"
#include <spdlog/details/null_mutex.h>
#include <spdlog/sinks/base_sink.h>
#include <mutex>
#include <ostream>

@ -0,0 +1,72 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include "spdlog/sinks/base_sink.h"
#include "spdlog/details/circular_q.h"
#include "spdlog/details/log_msg_buffer.h"
#include "spdlog/details/null_mutex.h"
#include <mutex>
#include <string>
#include <vector>
namespace spdlog {
namespace sinks {
/*
* Ring buffer sink
*/
template<typename Mutex>
class ringbuffer_sink final : public base_sink<Mutex>
{
public:
explicit ringbuffer_sink(size_t n_items)
: q_{n_items}
{}
std::vector<details::log_msg_buffer> last_raw(size_t lim = 0)
{
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
auto n_items = lim > 0 ? (std::min)(lim, q_.size()) : q_.size();
std::vector<details::log_msg_buffer> ret;
ret.reserve(n_items);
for (size_t i = 0; i < n_items; i++)
{
ret.push_back(q_.at(i));
}
return ret;
}
std::vector<std::string> last_formatted(size_t lim = 0)
{
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
auto n_items = lim > 0 ? (std::min)(lim, q_.size()) : q_.size();
std::vector<std::string> ret;
ret.reserve(n_items);
for (size_t i = 0; i < n_items; i++)
{
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(q_.at(i), formatted);
ret.push_back(fmt::to_string(formatted));
}
return ret;
}
protected:
void sink_it_(const details::log_msg &msg) override
{
q_.push_back(details::log_msg_buffer{msg});
}
void flush_() override {}
private:
details::circular_q<details::log_msg_buffer> q_;
};
using ringbuffer_sink_mt = ringbuffer_sink<std::mutex>;
using ringbuffer_sink_st = ringbuffer_sink<details::null_mutex>;
} // namespace sinks
} // namespace spdlog

@ -4,14 +4,14 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/sinks/rotating_file_sink.h"
#include <spdlog/sinks/rotating_file_sink.h>
#endif
#include "spdlog/common.h"
#include <spdlog/common.h>
#include "spdlog/details/file_helper.h"
#include "spdlog/details/null_mutex.h"
#include "spdlog/fmt/fmt.h"
#include <spdlog/details/file_helper.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/fmt/fmt.h>
#include <cerrno>
#include <chrono>
@ -88,11 +88,12 @@ template<typename Mutex>
SPDLOG_INLINE void rotating_file_sink<Mutex>::rotate_()
{
using details::os::filename_to_str;
using details::os::path_exists;
file_helper_.close();
for (auto i = max_files_; i > 0; --i)
{
filename_t src = calc_filename(base_filename_, i - 1);
if (!details::file_helper::file_exists(src))
if (!path_exists(src))
{
continue;
}

@ -3,10 +3,10 @@
#pragma once
#include "spdlog/sinks/base_sink.h"
#include "spdlog/details/file_helper.h"
#include "spdlog/details/null_mutex.h"
#include "spdlog/details/synchronous_factory.h"
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/file_helper.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/details/synchronous_factory.h>
#include <chrono>
#include <mutex>

@ -4,10 +4,10 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/sinks/sink.h"
#include <spdlog/sinks/sink.h>
#endif
#include "spdlog/common.h"
#include <spdlog/common.h>
SPDLOG_INLINE bool spdlog::sinks::sink::should_log(spdlog::level::level_enum msg_level) const
{

@ -3,8 +3,8 @@
#pragma once
#include "spdlog/details/log_msg.h"
#include "spdlog/formatter.h"
#include <spdlog/details/log_msg.h>
#include <spdlog/formatter.h>
namespace spdlog {

@ -4,11 +4,11 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/sinks/stdout_color_sinks.h"
#include <spdlog/sinks/stdout_color_sinks.h>
#endif
#include "spdlog/logger.h"
#include "spdlog/common.h"
#include <spdlog/logger.h>
#include <spdlog/common.h>
namespace spdlog {

@ -4,12 +4,12 @@
#pragma once
#ifdef _WIN32
#include "spdlog/sinks/wincolor_sink.h"
#include <spdlog/sinks/wincolor_sink.h>
#else
#include "spdlog/sinks/ansicolor_sink.h"
#include <spdlog/sinks/ansicolor_sink.h>
#endif
#include "spdlog/details/synchronous_factory.h"
#include <spdlog/details/synchronous_factory.h>
namespace spdlog {
namespace sinks {

@ -4,11 +4,11 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/sinks/stdout_sinks.h"
#include <spdlog/sinks/stdout_sinks.h>
#endif
#include "spdlog/details/console_globals.h"
#include "spdlog/details/pattern_formatter.h"
#include <spdlog/details/console_globals.h>
#include <spdlog/details/pattern_formatter.h>
#include <memory>
namespace spdlog {

@ -3,9 +3,9 @@
#pragma once
#include "spdlog/details/console_globals.h"
#include "spdlog/details/synchronous_factory.h"
#include "spdlog/sinks/sink.h"
#include <spdlog/details/console_globals.h>
#include <spdlog/details/synchronous_factory.h>
#include <spdlog/sinks/sink.h>
#include <cstdio>
namespace spdlog {

@ -3,8 +3,8 @@
#pragma once
#include "spdlog/sinks/base_sink.h"
#include "spdlog/details/null_mutex.h"
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/null_mutex.h>
#include <array>
#include <string>

@ -3,10 +3,14 @@
#pragma once
#include "spdlog/sinks/base_sink.h"
#include "spdlog/details/null_mutex.h"
#include "spdlog/details/synchronous_factory.h"
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/details/synchronous_factory.h>
#include <array>
#ifndef SD_JOURNAL_SUPPRESS_LOCATION
#define SD_JOURNAL_SUPPRESS_LOCATION
#endif
#include <systemd/sd-journal.h>
namespace spdlog {
@ -56,13 +60,14 @@ protected:
if (msg.source.empty())
{
// Note: function call inside '()' to avoid macro expansion
err = (sd_journal_send)(
"MESSAGE=%.*s", static_cast<int>(length), msg.payload.data(), "PRIORITY=%d", syslog_level(msg.level), nullptr);
err = (sd_journal_send)("MESSAGE=%.*s", static_cast<int>(length), msg.payload.data(), "PRIORITY=%d", syslog_level(msg.level),
"SYSLOG_IDENTIFIER=%.*s", static_cast<int>(msg.logger_name.size()), msg.logger_name.data(), nullptr);
}
else
{
err = (sd_journal_send)("MESSAGE=%.*s", static_cast<int>(length), msg.payload.data(), "PRIORITY=%d", syslog_level(msg.level),
"SOURCE_FILE=%s", msg.source.filename, "SOURCE_LINE=%d", msg.source.line, "SOURCE_FUNC=%s", msg.source.funcname, nullptr);
"SYSLOG_IDENTIFIER=%.*s", static_cast<int>(msg.logger_name.size()), msg.logger_name.data(), "CODE_FILE=%s",
msg.source.filename, "CODE_LINE=%d", msg.source.line, "CODE_FUNC=%s", msg.source.funcname, nullptr);
}
if (err)

@ -4,11 +4,11 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/sinks/wincolor_sink.h"
#include <spdlog/sinks/wincolor_sink.h>
#endif
#include "spdlog/common.h"
#include "spdlog/details/pattern_formatter.h"
#include <spdlog/common.h>
#include <spdlog/details/pattern_formatter.h>
namespace spdlog {
namespace sinks {
@ -140,7 +140,7 @@ void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::print_range_(const memory_buf_t
template<typename ConsoleMutex>
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::write_to_file_(const memory_buf_t &formatted)
{
if(out_handle_ == nullptr) // no console and no file redirect
if (out_handle_ == nullptr) // no console and no file redirect
{
return;
}

@ -3,10 +3,10 @@
#pragma once
#include "spdlog/common.h"
#include "spdlog/details/console_globals.h"
#include "spdlog/details/null_mutex.h"
#include "spdlog/sinks/sink.h"
#include <spdlog/common.h>
#include <spdlog/details/console_globals.h>
#include <spdlog/details/null_mutex.h>
#include <spdlog/sinks/sink.h>
#include <memory>
#include <mutex>

@ -4,11 +4,11 @@
#pragma once
#ifndef SPDLOG_HEADER_ONLY
#include "spdlog/spdlog.h"
#include <spdlog/spdlog.h>
#endif
#include "spdlog/common.h"
#include "spdlog/details/pattern_formatter.h"
#include <spdlog/common.h>
#include <spdlog/details/pattern_formatter.h>
namespace spdlog {
@ -92,9 +92,9 @@ SPDLOG_INLINE void shutdown()
details::registry::instance().shutdown();
}
SPDLOG_INLINE void set_automatic_registration(bool automatic_registation)
SPDLOG_INLINE void set_automatic_registration(bool automatic_registration)
{
details::registry::instance().set_automatic_registration(automatic_registation);
details::registry::instance().set_automatic_registration(automatic_registration);
}
SPDLOG_INLINE std::shared_ptr<spdlog::logger> default_logger()

@ -9,11 +9,11 @@
#pragma once
#include "spdlog/common.h"
#include "spdlog/details/registry.h"
#include "spdlog/logger.h"
#include "spdlog/version.h"
#include "spdlog/details/synchronous_factory.h"
#include <spdlog/common.h>
#include <spdlog/details/registry.h>
#include <spdlog/logger.h>
#include <spdlog/version.h>
#include <spdlog/details/synchronous_factory.h>
#include <chrono>
#include <functional>
@ -100,7 +100,7 @@ void drop_all();
void shutdown();
// Automatic registration of loggers when using spdlog::create() or spdlog::create_async
void set_automatic_registration(bool automatic_registation);
void set_automatic_registration(bool automatic_registration);
// API for using default logger (stdout_color_mt),
// e.g: spdlog::info("Message {}", 1);
@ -285,7 +285,7 @@ inline void critical(wstring_view_t fmt, const Args &... args)
// SPDLOG_LEVEL_OFF
//
#define SPDLOG_LOGGER_CALL(logger, level, ...) logger->log(spdlog::source_loc{__FILE__, __LINE__, SPDLOG_FUNCTION}, level, __VA_ARGS__)
#define SPDLOG_LOGGER_CALL(logger, level, ...) (logger)->log(spdlog::source_loc{__FILE__, __LINE__, SPDLOG_FUNCTION}, level, __VA_ARGS__)
#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_TRACE
#define SPDLOG_LOGGER_TRACE(logger, ...) SPDLOG_LOGGER_CALL(logger, spdlog::level::trace, __VA_ARGS__)

@ -19,19 +19,6 @@
// #define SPDLOG_CLOCK_COARSE
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment if date/time logging is not needed and never appear in the log
// pattern.
// This will prevent spdlog from querying the clock on each log call.
//
// WARNING: If the log pattern contains any date/time while this flag is on, the
// result is undefined.
// You must set new pattern(spdlog::set_pattern(..") without any
// date/time in it
//
// #define SPDLOG_NO_DATETIME
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment if thread id logging is not needed (i.e. no %t in the log pattern).
// This will prevent spdlog from querying the thread id on each log call.

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

@ -1,12 +1,12 @@
project('spdlog', ['cpp'],
license : 'MIT',
version : run_command(find_program('scripts/extract_version.py')).stdout().strip(),
default_options : [
license : 'MIT',
version : run_command(find_program('scripts/extract_version.py')).stdout().strip(),
default_options : [
'warning_level=3',
'cpp_std=c++11',
'buildtype=release',
'b_colorout=always',
],
],
)
# ------------------------
@ -20,17 +20,57 @@ dep_list += dependency('threads')
# Check for FMT
if get_option('external_fmt')
if not meson.version().version_compare('>=0.49.0')
warning('Finding fmt can fail wit meson versions before 0.49.0')
endif
dep_list += dependency('fmt')
compile_args += '-DSPDLOG_FMT_EXTERNAL'
if not meson.version().version_compare('>=0.49.0')
warning('Finding fmt can fail with meson versions before 0.49.0')
endif
dep_list += dependency('fmt')
compile_args += '-DSPDLOG_FMT_EXTERNAL'
endif
if get_option('no_exceptions')
compile_args += '-DSPDLOG_NO_EXCEPTIONS'
endif
if get_option('wchar_support')
if build_machine.system() != 'windows'
error('wchar_support only supported under windows')
endif
compile_args += '-DSPDLOG_WCHAR_TO_UTF8_SUPPORT'
endif
if get_option('wchar_filenames')
if build_machine.system() != 'windows'
error('wchar_filenames only supported under windows')
endif
compile_args += '-DSPDLOG_WCHAR_FILENAMES'
endif
if get_option('clock_coarse')
if build_machine.system() != 'linux'
error('clock_coarse only supported under linux')
endif
compile_args += '-DSPDLOG_CLOCK_COARSE'
endif
if get_option('prevent_child_fd')
compile_args += '-DSPDLOG_PREVENT_CHILD_FD'
endif
if get_option('no_thread_id')
compile_args += '-DSPDLOG_NO_THREAD_ID'
endif
if get_option('no_tls')
compile_args += '-DSPDLOG_NO_TLS'
endif
if get_option('no_atomic_levels')
compile_args += '-DSPDLOG_NO_ATOMIC_LEVELS'
endif
compile_args_compiled = compile_args + ['-DSPDLOG_COMPILED_LIB']
compile_args_ho = compile_args
# ------------------------------------
# --- Compiled library version ---
# ------------------------------------
@ -41,47 +81,49 @@ spdlog_srcs = files([
'src/async.cpp',
'src/color_sinks.cpp',
'src/file_sinks.cpp',
'src/fmt.cpp',
'src/spdlog.cpp',
'src/stdout_sinks.cpp'
])
if not get_option('external_fmt')
spdlog_srcs+= 'src/fmt.cpp'
endif
if get_option('library_type') == 'static'
spdlog = static_library(
spdlog = static_library(
'spdlog',
spdlog_srcs,
cpp_args : [compile_args] + ['-DSPDLOG_COMPILED_LIB'],
cpp_args : compile_args_compiled,
include_directories : spdlog_inc,
dependencies : dep_list,
install : not meson.is_subproject()
)
else
spdlog = shared_library('spdlog',
spdlog = shared_library('spdlog',
spdlog_srcs,
cpp_args : [compile_args] + ['-DSPDLOG_COMPILED_LIB'],
cpp_args : compile_args_compiled,
include_directories : spdlog_inc,
dependencies : dep_list,
install : not meson.is_subproject(),
)
)
endif
spdlog_dep = declare_dependency(
link_with : spdlog,
include_directories : spdlog_inc,
compile_args : compile_args + ['-DSPDLOG_COMPILED_LIB'],
dependencies : dep_list,
version : meson.project_version(),
link_with : spdlog,
include_directories : spdlog_inc,
compile_args : compile_args_compiled,
dependencies : dep_list,
version : meson.project_version(),
)
# ----------------------------------
# --- Header only dependency ---
# ----------------------------------
spdlog_headeronly_dep = declare_dependency(
include_directories : spdlog_inc,
compile_args : compile_args,
dependencies : dep_list,
version : meson.project_version(),
include_directories : spdlog_inc,
compile_args : compile_args_ho,
dependencies : dep_list,
version : meson.project_version(),
)
# ------------------------
@ -90,31 +132,31 @@ spdlog_headeronly_dep = declare_dependency(
# Do not install when spdlog is used as a subproject
if not meson.is_subproject()
install_subdir('include/spdlog', install_dir: get_option('includedir'))
install_subdir('include/spdlog', install_dir: get_option('includedir'))
pkg = import('pkgconfig')
pkg.generate(spdlog,
pkg = import('pkgconfig')
pkg.generate(spdlog,
name : 'spdlog',
description : 'Fast C++ logging library',
url : 'https://github.com/gabime/spdlog',
extra_cflags : ['-DSPDLOG_COMPILED_LIB']
)
extra_cflags : compile_args_compiled
)
endif
# -------------------------------------
# --- Conditionally add subdirs ---
# -------------------------------------
if get_option('enable_tests')
subdir('tests')
if get_option('enable_tests') or get_option('enable_tests-ho')
subdir('tests')
endif
if get_option('enable_examples')
subdir('example')
subdir('example')
endif
if get_option('enable_benchmarks')
subdir('bench')
subdir('bench')
endif
# -------------------
@ -122,7 +164,6 @@ endif
# -------------------
summary_str = '''spdlog build summary:
- using external fmt: @0@
- building tests: @1@
- building examples: @2@

@ -1,6 +1,15 @@
option('external_fmt', type: 'boolean', value: false, description: 'Use external fmt package instead of the bundled')
option('enable_examples', type: 'boolean', value: true, description: 'Build examples')
option('enable_benchmarks', type: 'boolean', value: false, description: 'Build benchmarks')
option('enable_tests', type: 'boolean', value: false, description: 'Build tests')
option('external_fmt', type: 'boolean', value: false, description: 'Use external fmt package instead of the bundled')
option('enable_examples', type: 'boolean', value: true, description: 'Build examples')
option('enable_benchmarks', type: 'boolean', value: false, description: 'Build benchmarks')
option('enable_tests', type: 'boolean', value: true, description: 'Build tests')
option('enable_tests_ho', type: 'boolean', value: false, description: 'Build header-only tests')
option('library_type', type: 'combo', choices: ['static', 'shared'], value: 'static', description: 'Library build type')
option('no_exceptions', type: 'boolean', value: false, description: 'Disabled exceptions - abort() instead any error')
option('no_exceptions', type: 'boolean', value: false, description: 'Disabled exceptions - abort() instead any error')
option('wchar_support', type: 'boolean', value: false, description:'(Windows only) Support wchar api')
option('wchar_filenames', type: 'boolean', value: false, description: '(Windows only) Support wchar filenames')
option('clock_coarse', type: 'boolean', value: false, description: '(Linux only) Use the much faster (but much less accurate) CLOCK_REALTIME_COARSE instead of the regular clock')
option('prevent_child_fd', type: 'boolean', value: false, description: 'Prevent from child processes to inherit log file descriptors')
option('no_thread_id', type: 'boolean', value: false, description: 'prevent spdlog from querying the thread id on each log call if thread id is not needed')
option('no_tls', type: 'boolean', value: false, description: 'prevent spdlog from using thread local storage')
option('no_atomic_levels', type: 'boolean', value: false, description: 'prevent spdlog from using of std::atomic log levels (use only if your code never modifies log levels concurrently')

@ -1,4 +1,17 @@
Checks: 'modernize-*,modernize-use-override,google-*,-google-runtime-references,misc-*,clang-analyzer-*,-misc-non-private-member-variables-in-classes'
Checks: '\
cppcoreguidelines-*,\
performance-*,\
-performance-unnecessary-value-param,\
modernize-*,\
-modernize-use-trailing-return-type,\
google-*,\
-google-runtime-references,\
misc-*,\
-misc-non-private-member-variables-in-classes,\
cert-*,\
readability-*,\
clang-analyzer-*'
WarningsAsErrors: ''
HeaderFilterRegex: 'async.h|async_logger.h|common.h|details|formatter.h|logger.h|sinks|spdlog.h|tweakme.h|version.h'
AnalyzeTemporaryDtors: false

@ -14,18 +14,16 @@ set(SPDLOG_UTESTS_SOURCES
test_misc.cpp
test_pattern_formatter.cpp
test_async.cpp
includes.h
test_registry.cpp
test_macros.cpp
utils.cpp
utils.h
main.cpp
test_mpmc_q.cpp
test_sink.h
test_dup_filter.cpp
test_fmt_helper.cpp
test_stdout_api.cpp
test_dup_filter.cpp
test_backtrace.cpp)
test_backtrace.cpp
test_create_dir.cpp)
if(NOT SPDLOG_NO_EXCEPTIONS)
list(APPEND SPDLOG_UTESTS_SOURCES test_errors.cpp)
@ -35,34 +33,28 @@ if(systemd_FOUND)
list(APPEND SPDLOG_UTESTS_SOURCES test_systemd.cpp)
endif()
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs")
enable_testing()
# The compiled library tests
if(SPDLOG_BUILD_TESTS)
add_executable(spdlog-utests ${SPDLOG_UTESTS_SOURCES})
spdlog_enable_warnings(spdlog-utests)
target_link_libraries(spdlog-utests PRIVATE spdlog)
enable_testing()
function(spdlog_prepare_test test_target spdlog_lib)
add_executable(${test_target} ${SPDLOG_UTESTS_SOURCES})
spdlog_enable_warnings(${test_target})
target_link_libraries(${test_target} PRIVATE ${spdlog_lib})
if(systemd_FOUND)
target_link_libraries(spdlog-utests PRIVATE ${systemd_LIBRARIES})
target_link_libraries(${test_target} PRIVATE ${systemd_LIBRARIES})
endif()
if(SPDLOG_SANITIZE_ADDRESS)
spdlog_enable_sanitizer(spdlog-utests)
spdlog_enable_sanitizer(${test_target})
endif()
add_test(NAME spdlog-utests COMMAND spdlog-utests)
add_test(NAME ${test_target} COMMAND ${test_target})
endfunction()
# The compiled library tests
if(SPDLOG_BUILD_TESTS)
spdlog_prepare_test(spdlog-utests spdlog::spdlog)
endif()
# The header-only library version tests
if(SPDLOG_BUILD_TESTS_HO)
add_executable(spdlog-utests-ho ${SPDLOG_UTESTS_SOURCES})
spdlog_enable_warnings(spdlog-utests-ho)
target_link_libraries(spdlog-utests-ho PRIVATE spdlog::spdlog_header_only)
if(systemd_FOUND)
target_link_libraries(spdlog-utests-ho PRIVATE ${systemd_LIBRARIES})
endif()
if(SPDLOG_SANITIZE_ADDRESS)
spdlog_set_address_sanitizer(spdlog-utests-ho)
endif()
add_test(NAME spdlog-utests-ho COMMAND spdlog-utests-ho)
spdlog_prepare_test(spdlog-utests-ho spdlog::spdlog_header_only)
endif()

@ -5,19 +5,18 @@ test_sources = files([
'test_misc.cpp',
'test_pattern_formatter.cpp',
'test_async.cpp',
'includes.h',
'test_registry.cpp',
'test_macros.cpp',
'utils.cpp',
'main.cpp',
'test_mpmc_q.cpp',
'test_dup_filter.cpp',
'test_fmt_helper.cpp',
'test_stdout_api.cpp',
'test_dup_filter.cpp',
'test_backtrace.cpp'
'test_backtrace.cpp',
'test_create_dir.cpp'
])
if not get_option('no_exceptions')
test_sources += 'test_errors.cpp'
endif
@ -35,19 +34,15 @@ if systemd_dep.found()
global_test_deps += systemd_dep
endif
run_command('mkdir', 'logs')
# --------------------------------------
# --- Build the test executables ---
# --------------------------------------
if get_option('enable_tests')
test_exe = executable('spdlog-utests', test_sources, dependencies: global_test_deps + [spdlog_dep])
test('test_spdlog', test_exe, is_parallel : false)
endif
test_matrix = [
['spdlog-utests', spdlog_dep],
['spdlog-utests-ho', spdlog_headeronly_dep],
]
foreach i : test_matrix
test_exe = executable(i[0], test_sources, dependencies: global_test_deps + [i[1]])
test('test_' + i[0], test_exe)
endforeach
run_command(find_program('mkdir'), meson.current_build_dir() + '/logs')
if get_option('enable_tests_ho')
test_exe = executable('spdlog-utests-ho', test_sources, dependencies: global_test_deps + [spdlog_headeronly_dep])
test('test_spdlog-ho', test_exe, is_parallel : false)
endif

@ -157,7 +157,7 @@ TEST_CASE("to_file", "[async]")
prepare_logdir();
size_t messages = 1024;
size_t tp_threads = 1;
std::string filename = "logs/async_test.log";
std::string filename = "test_logs/async_test.log";
{
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
auto tp = std::make_shared<spdlog::details::thread_pool>(messages, tp_threads);
@ -179,7 +179,7 @@ TEST_CASE("to_file multi-workers", "[async]")
prepare_logdir();
size_t messages = 1024 * 10;
size_t tp_threads = 10;
std::string filename = "logs/async_test.log";
std::string filename = "test_logs/async_test.log";
{
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
auto tp = std::make_shared<spdlog::details::thread_pool>(messages, tp_threads);

@ -0,0 +1,80 @@
/*
* This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE
*/
#include "includes.h"
using spdlog::details::os::create_dir;
using spdlog::details::os::path_exists;
bool try_create_dir(const char *path, const char *normalized_path)
{
auto rv = create_dir(path);
REQUIRE(rv == true);
return path_exists(normalized_path);
}
TEST_CASE("create_dir", "[create_dir]")
{
prepare_logdir();
REQUIRE(try_create_dir("test_logs/dir1/dir1", "test_logs/dir1/dir1"));
REQUIRE(try_create_dir("test_logs/dir1/dir1", "test_logs/dir1/dir1")); // test existing
REQUIRE(try_create_dir("test_logs/dir1///dir2//", "test_logs/dir1/dir2"));
REQUIRE(try_create_dir("./test_logs/dir1/dir3", "test_logs/dir1/dir3"));
REQUIRE(try_create_dir("test_logs/../test_logs/dir1/dir4", "test_logs/dir1/dir4"));
#ifdef WIN32
// test backslash folder separator
REQUIRE(try_create_dir("test_logs\\dir1\\dir222", "test_logs\\dir1\\dir222"));
REQUIRE(try_create_dir("test_logs\\dir1\\dir223\\", "test_logs\\dir1\\dir223\\"));
REQUIRE(try_create_dir(".\\test_logs\\dir1\\dir2\\dir99\\..\\dir23", "test_logs\\dir1\\dir2\\dir23"));
REQUIRE(try_create_dir("test_logs\\..\\test_logs\\dir1\\dir5", "test_logs\\dir1\\dir5"));
#endif
}
TEST_CASE("create_invalid_dir", "[create_dir]")
{
REQUIRE(create_dir("") == false);
REQUIRE(create_dir(spdlog::filename_t{}) == false);
#ifdef __linux__
REQUIRE(create_dir("/proc/spdlog-utest") == false);
#endif
}
TEST_CASE("dir_name", "[create_dir]")
{
using spdlog::details::os::dir_name;
REQUIRE(dir_name("").empty());
REQUIRE(dir_name("dir").empty());
#ifdef WIN32
REQUIRE(dir_name(R"(dir\)") == "dir");
REQUIRE(dir_name(R"(dir\\\)") == R"(dir\\)");
REQUIRE(dir_name(R"(dir\file)") == "dir");
REQUIRE(dir_name(R"(dir/file)") == "dir");
REQUIRE(dir_name(R"(dir\file.txt)") == "dir");
REQUIRE(dir_name(R"(dir/file)") == "dir");
REQUIRE(dir_name(R"(dir\file.txt\)") == R"(dir\file.txt)");
REQUIRE(dir_name(R"(dir/file.txt/)") == R"(dir\file.txt)");
REQUIRE(dir_name(R"(\dir\file.txt)") == R"(\dir)");
REQUIRE(dir_name(R"(/dir/file.txt)") == R"(\dir)");
REQUIRE(dir_name(R"(\\dir\file.txt)") == R"(\\dir)");
REQUIRE(dir_name(R"(//dir/file.txt)") == R"(\\dir)");
REQUIRE(dir_name(R"(..\file.txt)") == "..");
REQUIRE(dir_name(R"(../file.txt)") == "..");
REQUIRE(dir_name(R"(.\file.txt)") == ".");
REQUIRE(dir_name(R"(./file.txt)") == ".");
REQUIRE(dir_name(R"(c:\\a\b\c\d\file.txt)") == R"(c:\\a\b\c\d)");
REQUIRE(dir_name(R"(c://a/b/c/d/file.txt)") == R"(c:\\a\b\c\d)");
#else
REQUIRE(dir_name("dir/") == "dir");
REQUIRE(dir_name("dir///") == "dir//");
REQUIRE(dir_name("dir/file") == "dir");
REQUIRE(dir_name("dir/file.txt") == "dir");
REQUIRE(dir_name("dir/file.txt/") == "dir/file.txt");
REQUIRE(dir_name("/dir/file.txt") == "/dir");
REQUIRE(dir_name("//dir/file.txt") == "//dir");
REQUIRE(dir_name("../file.txt") == "..");
REQUIRE(dir_name("./file.txt") == ".");
#endif
}

@ -10,7 +10,7 @@ TEST_CASE("daily_logger with dateonly calculator", "[daily_logger]")
prepare_logdir();
// calculate filename (time based)
std::string basename = "logs/daily_dateonly";
std::string basename = "test_logs/daily_dateonly";
std::tm tm = spdlog::details::os::localtime();
spdlog::memory_buf_t w;
fmt::format_to(w, "{}_{:04d}-{:02d}-{:02d}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
@ -44,7 +44,7 @@ TEST_CASE("daily_logger with custom calculator", "[daily_logger]")
prepare_logdir();
// calculate filename (time based)
std::string basename = "logs/daily_dateonly";
std::string basename = "test_logs/daily_dateonly";
std::tm tm = spdlog::details::os::localtime();
spdlog::memory_buf_t w;
fmt::format_to(w, "{}{:04d}{:02d}{:02d}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
@ -119,7 +119,7 @@ static void test_rotate(int days_to_run, uint16_t max_days, uint16_t expected_n_
prepare_logdir();
std::string basename = "logs/daily_rotate.txt";
std::string basename = "test_logs/daily_rotate.txt";
daily_file_sink_st sink{basename, 2, 30, true, max_days};
// simulate messages with 24 intervals
@ -130,7 +130,7 @@ static void test_rotate(int days_to_run, uint16_t max_days, uint16_t expected_n_
sink.log(create_msg(offset));
}
REQUIRE(count_files("logs") == static_cast<size_t>(expected_n_files));
REQUIRE(count_files("test_logs") == static_cast<size_t>(expected_n_files));
}
TEST_CASE("daily_logger rotate", "[daily_file_sink]")

@ -26,7 +26,7 @@ protected:
TEST_CASE("default_error_handler", "[errors]]")
{
prepare_logdir();
std::string filename = "logs/simple_log.txt";
std::string filename = "test_logs/simple_log.txt";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("test-error", filename, true);
logger->set_pattern("%v");
@ -43,7 +43,7 @@ struct custom_ex
TEST_CASE("custom_error_handler", "[errors]]")
{
prepare_logdir();
std::string filename = "logs/simple_log.txt";
std::string filename = "test_logs/simple_log.txt";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename, true);
logger->flush_on(spdlog::level::info);
logger->set_error_handler([=](const std::string &) { throw custom_ex(); });
@ -75,15 +75,15 @@ TEST_CASE("async_error_handler", "[errors]]")
prepare_logdir();
std::string err_msg("log failed with some msg");
std::string filename = "logs/simple_async_log.txt";
std::string filename = "test_logs/simple_async_log.txt";
{
spdlog::init_thread_pool(128, 1);
auto logger = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("logger", filename, true);
logger->set_error_handler([=](const std::string &) {
std::ofstream ofs("logs/custom_err.txt");
std::ofstream ofs("test_logs/custom_err.txt");
if (!ofs)
{
throw std::runtime_error("Failed open logs/custom_err.txt");
throw std::runtime_error("Failed open test_logs/custom_err.txt");
}
ofs << err_msg;
});
@ -94,7 +94,7 @@ TEST_CASE("async_error_handler", "[errors]]")
}
spdlog::init_thread_pool(128, 1);
REQUIRE(count_lines(filename) == 2);
REQUIRE(file_contents("logs/custom_err.txt") == err_msg);
REQUIRE(file_contents("test_logs/custom_err.txt") == err_msg);
}
// Make sure async error handler is executed
@ -103,12 +103,13 @@ TEST_CASE("async_error_handler2", "[errors]]")
prepare_logdir();
std::string err_msg("This is async handler error message");
{
spdlog::details::os::create_dir("test_logs");
spdlog::init_thread_pool(128, 1);
auto logger = spdlog::create_async<failing_sink>("failed_logger");
logger->set_error_handler([=](const std::string &) {
std::ofstream ofs("logs/custom_err2.txt");
std::ofstream ofs("test_logs/custom_err2.txt");
if (!ofs)
throw std::runtime_error("Failed open logs/custom_err2.txt");
throw std::runtime_error("Failed open test_logs/custom_err2.txt");
ofs << err_msg;
});
logger->info("Hello failure");
@ -116,5 +117,5 @@ TEST_CASE("async_error_handler2", "[errors]]")
}
spdlog::init_thread_pool(128, 1);
REQUIRE(file_contents("logs/custom_err2.txt") == err_msg);
REQUIRE(file_contents("test_logs/custom_err2.txt") == err_msg);
}

@ -6,7 +6,7 @@
using spdlog::details::file_helper;
using spdlog::details::log_msg;
static const std::string target_filename = "logs/file_helper_test.txt";
static const std::string target_filename = "test_logs/file_helper_test.txt";
static void write_with_helper(file_helper &helper, size_t howmany)
{
@ -38,15 +38,6 @@ TEST_CASE("file_helper_size", "[file_helper::size()]]")
REQUIRE(get_filesize(target_filename) == expected_size);
}
TEST_CASE("file_helper_exists", "[file_helper::file_exists()]]")
{
prepare_logdir();
REQUIRE(!file_helper::file_exists(target_filename));
file_helper helper;
helper.open(target_filename);
REQUIRE(file_helper::file_exists(target_filename));
}
TEST_CASE("file_helper_reopen", "[file_helper::reopen()]]")
{
prepare_logdir();

@ -6,7 +6,7 @@
TEST_CASE("simple_file_logger", "[simple_logger]]")
{
prepare_logdir();
std::string filename = "logs/simple_log";
std::string filename = "test_logs/simple_log";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
logger->set_pattern("%v");
@ -22,7 +22,7 @@ TEST_CASE("simple_file_logger", "[simple_logger]]")
TEST_CASE("flush_on", "[flush_on]]")
{
prepare_logdir();
std::string filename = "logs/simple_log";
std::string filename = "test_logs/simple_log";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
logger->set_pattern("%v");
@ -42,7 +42,7 @@ TEST_CASE("rotating_file_logger1", "[rotating_logger]]")
{
prepare_logdir();
size_t max_size = 1024 * 10;
std::string basename = "logs/rotating_log";
std::string basename = "test_logs/rotating_log";
auto logger = spdlog::rotating_logger_mt("logger", basename, max_size, 0);
for (int i = 0; i < 10; ++i)
@ -59,7 +59,7 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
{
prepare_logdir();
size_t max_size = 1024 * 10;
std::string basename = "logs/rotating_log";
std::string basename = "test_logs/rotating_log";
{
// make an initial logger to create the first output file

@ -12,7 +12,7 @@ TEST_CASE("debug and trace w/o format string", "[macros]]")
{
prepare_logdir();
std::string filename = "logs/simple_log";
std::string filename = "test_logs/simple_log";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
logger->set_pattern("%v");
@ -39,3 +39,21 @@ TEST_CASE("disable param evaluation", "[macros]")
{
SPDLOG_TRACE("Test message {}", throw std::runtime_error("Should not be evaluated"));
}
TEST_CASE("pass logger pointer", "[macros]")
{
auto logger = spdlog::create<spdlog::sinks::null_sink_mt>("refmacro");
auto &ref = *logger;
SPDLOG_LOGGER_TRACE(&ref, "Test message 1");
SPDLOG_LOGGER_DEBUG(&ref, "Test message 2");
}
// ensure that even if right macro level is on- don't evaluate if the logger's level is not high enough
// TEST_CASE("disable param evaluation2", "[macros]")
//{
// auto logger = std::make_shared<spdlog::logger>("test-macro");
// logger->set_level(spdlog::level::off);
// int x = 0;
// SPDLOG_LOGGER_DEBUG(logger, "Test message {}", ++x);
// REQUIRE(x == 0);
//}

@ -1,4 +1,5 @@
#include "includes.h"
#include "test_sink.h"
using spdlog::memory_buf_t;
@ -138,58 +139,111 @@ TEST_CASE("color range test6", "[pattern_formatter]")
TEST_CASE("level_left_padded", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%8l] %v", spdlog::pattern_time_type::local, "\n") == "[ info] Some message\n");
REQUIRE(log_to_str("Some message", "[%8!l] %v", spdlog::pattern_time_type::local, "\n") == "[ info] Some message\n");
}
TEST_CASE("level_right_padded", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%-8l] %v", spdlog::pattern_time_type::local, "\n") == "[info ] Some message\n");
REQUIRE(log_to_str("Some message", "[%-8!l] %v", spdlog::pattern_time_type::local, "\n") == "[info ] Some message\n");
}
TEST_CASE("level_center_padded", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%=8l] %v", spdlog::pattern_time_type::local, "\n") == "[ info ] Some message\n");
REQUIRE(log_to_str("Some message", "[%=8!l] %v", spdlog::pattern_time_type::local, "\n") == "[ info ] Some message\n");
}
TEST_CASE("short level_left_padded", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%3L] %v", spdlog::pattern_time_type::local, "\n") == "[ I] Some message\n");
REQUIRE(log_to_str("Some message", "[%3!L] %v", spdlog::pattern_time_type::local, "\n") == "[ I] Some message\n");
}
TEST_CASE("short level_right_padded", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%-3L] %v", spdlog::pattern_time_type::local, "\n") == "[I ] Some message\n");
REQUIRE(log_to_str("Some message", "[%-3!L] %v", spdlog::pattern_time_type::local, "\n") == "[I ] Some message\n");
}
TEST_CASE("short level_center_padded", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%=3L] %v", spdlog::pattern_time_type::local, "\n") == "[ I ] Some message\n");
REQUIRE(log_to_str("Some message", "[%=3!L] %v", spdlog::pattern_time_type::local, "\n") == "[ I ] Some message\n");
}
TEST_CASE("left_padded_short", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n");
REQUIRE(log_to_str("Some message", "[%3!n] %v", spdlog::pattern_time_type::local, "\n") == "[pat] Some message\n");
}
TEST_CASE("right_padded_short", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%-3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n");
REQUIRE(log_to_str("Some message", "[%-3!n] %v", spdlog::pattern_time_type::local, "\n") == "[pat] Some message\n");
}
TEST_CASE("center_padded_short", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%=3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n");
REQUIRE(log_to_str("Some message", "[%=3!n] %v", spdlog::pattern_time_type::local, "\n") == "[pat] Some message\n");
}
TEST_CASE("left_padded_huge", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%-300n] %v", spdlog::pattern_time_type::local, "\n") ==
"[pattern_tester ] Some message\n");
"[pattern_tester ] Some message\n");
REQUIRE(log_to_str("Some message", "[%-300!n] %v", spdlog::pattern_time_type::local, "\n") ==
"[pattern_tester ] Some message\n");
}
TEST_CASE("left_padded_max", "[pattern_formatter]")
{
REQUIRE(log_to_str("Some message", "[%-64n] %v", spdlog::pattern_time_type::local, "\n") ==
"[pattern_tester ] Some message\n");
"[pattern_tester ] Some message\n");
REQUIRE(log_to_str("Some message", "[%-64!n] %v", spdlog::pattern_time_type::local, "\n") ==
"[pattern_tester ] Some message\n");
}
// Test padding + truncate flag
TEST_CASE("paddinng_truncate", "[pattern_formatter]")
{
REQUIRE(log_to_str("123456", "%6!v", spdlog::pattern_time_type::local, "\n") == "123456\n");
REQUIRE(log_to_str("123456", "%5!v", spdlog::pattern_time_type::local, "\n") == "12345\n");
REQUIRE(log_to_str("123456", "%7!v", spdlog::pattern_time_type::local, "\n") == " 123456\n");
REQUIRE(log_to_str("123456", "%-6!v", spdlog::pattern_time_type::local, "\n") == "123456\n");
REQUIRE(log_to_str("123456", "%-5!v", spdlog::pattern_time_type::local, "\n") == "12345\n");
REQUIRE(log_to_str("123456", "%-7!v", spdlog::pattern_time_type::local, "\n") == "123456 \n");
REQUIRE(log_to_str("123456", "%=6!v", spdlog::pattern_time_type::local, "\n") == "123456\n");
REQUIRE(log_to_str("123456", "%=5!v", spdlog::pattern_time_type::local, "\n") == "12345\n");
REQUIRE(log_to_str("123456", "%=7!v", spdlog::pattern_time_type::local, "\n") == "123456 \n");
REQUIRE(log_to_str("123456", "%0!v", spdlog::pattern_time_type::local, "\n") == "\n");
}
TEST_CASE("paddinng_truncate_funcname", "[pattern_formatter]")
{
spdlog::sinks::test_sink_st test_sink;
const char* pattern = "%v [%5!!]";
auto formatter = std::unique_ptr<spdlog::formatter>(new spdlog::pattern_formatter(pattern));
test_sink.set_formatter(std::move(formatter));
spdlog::details::log_msg msg1{spdlog::source_loc{"ignored", 1, "func"}, "test_logger", spdlog::level::info, "message"};
test_sink.log(msg1);
spdlog::details::log_msg msg2{spdlog::source_loc{"ignored", 1, "function"}, "test_logger", spdlog::level::info, "message"};
test_sink.log(msg2);
auto lines = test_sink.lines();
REQUIRE(lines[0] == "message [ func]");
REQUIRE(lines[1] == "message [funct]");
}
TEST_CASE("clone-default-formatter", "[pattern_formatter]")

@ -9,7 +9,7 @@ TEST_CASE("register_drop", "[registry]")
spdlog::drop_all();
spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name);
REQUIRE(spdlog::get(tested_logger_name) != nullptr);
// Throw if registring existing name
// Throw if registering existing name
REQUIRE_THROWS_AS(spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name), spdlog::spdlog_ex);
}
@ -19,7 +19,7 @@ TEST_CASE("explicit register", "[registry]")
auto logger = std::make_shared<spdlog::logger>(tested_logger_name, std::make_shared<spdlog::sinks::null_sink_st>());
spdlog::register_logger(logger);
REQUIRE(spdlog::get(tested_logger_name) != nullptr);
// Throw if registring existing name
// Throw if registering existing name
REQUIRE_THROWS_AS(spdlog::create<spdlog::sinks::null_sink_mt>(tested_logger_name), spdlog::spdlog_ex);
}
#endif

@ -9,18 +9,12 @@ void prepare_logdir()
{
spdlog::drop_all();
#ifdef _WIN32
system("if not exist logs mkdir logs");
system("del /F /Q logs\\*");
system("rmdir /S /Q test_logs");
#else
auto rv = system("mkdir -p logs");
auto rv = system("rm -rf test_logs");
if (rv != 0)
{
throw std::runtime_error("Failed to mkdir -p logs");
}
rv = system("rm -f logs/*");
if (rv != 0)
{
throw std::runtime_error("Failed to rm -f logs/*");
throw std::runtime_error("Failed to rm -rf test_logs");
}
#endif
}

Loading…
Cancel
Save