mirror of
https://github.com/gabime/spdlog.git
synced 2025-09-30 10:29:02 +08:00
Compare commits
99 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
012fe99ab1 | ||
![]() |
8ff5a3e096 | ||
![]() |
65317eb019 | ||
![]() |
e86f450428 | ||
![]() |
7b2776fdc7 | ||
![]() |
2a16d1d230 | ||
![]() |
53e1c9ab11 | ||
![]() |
410abc4626 | ||
![]() |
a2e28443f0 | ||
![]() |
c1af0a3f21 | ||
![]() |
bb5e1ee2f9 | ||
![]() |
3aee89c8fd | ||
![]() |
44e1f9f682 | ||
![]() |
37d76b961c | ||
![]() |
1305663d99 | ||
![]() |
8f4efe57a2 | ||
![]() |
0613dbc4a2 | ||
![]() |
0ed0d69368 | ||
![]() |
2ffbbee1f6 | ||
![]() |
b9d2f2537b | ||
![]() |
69dc173979 | ||
![]() |
ded8b5ebd4 | ||
![]() |
ed58ae9f98 | ||
![]() |
f7f790b4b3 | ||
![]() |
fe74c80992 | ||
![]() |
fa659bf7ad | ||
![]() |
9b41649601 | ||
![]() |
1b3438f5a5 | ||
![]() |
3eed64e5c4 | ||
![]() |
0fac33781d | ||
![]() |
3135b6a33d | ||
![]() |
2686ae2322 | ||
![]() |
a709e29586 | ||
![]() |
dd46579cb4 | ||
![]() |
f4b7210e7b | ||
![]() |
05a0b0d7b0 | ||
![]() |
c1f4d7506a | ||
![]() |
b6ba0be550 | ||
![]() |
23dfb4e2f9 | ||
![]() |
7a10e31982 | ||
![]() |
de89c4fd01 | ||
![]() |
5d4956d34b | ||
![]() |
42c5eb59c9 | ||
![]() |
09cc6e7754 | ||
![]() |
4a5bc41e89 | ||
![]() |
0ade18828d | ||
![]() |
91046e6ca4 | ||
![]() |
17e1ba8ae2 | ||
![]() |
c47c854f15 | ||
![]() |
e931866b35 | ||
![]() |
7828a065bf | ||
![]() |
3e689e700e | ||
![]() |
a9964afcf7 | ||
![]() |
95c19876c6 | ||
![]() |
5efccfa5e2 | ||
![]() |
89e737a258 | ||
![]() |
8fbc853b0d | ||
![]() |
2e008b319c | ||
![]() |
ff6e3c95f2 | ||
![]() |
7e9385405f | ||
![]() |
592ea36a86 | ||
![]() |
e059ebf99d | ||
![]() |
609480ed78 | ||
![]() |
4271185936 | ||
![]() |
aacae62591 | ||
![]() |
47cbf3828d | ||
![]() |
46d418164d | ||
![]() |
ede8d84884 | ||
![]() |
53d223b45f | ||
![]() |
ac35dd5a6f | ||
![]() |
9e19012cb0 | ||
![]() |
1234cda3b3 | ||
![]() |
710a0e3a45 | ||
![]() |
b7f24b2456 | ||
![]() |
fc594b551a | ||
![]() |
f39ccccc0c | ||
![]() |
f0a4ddd78b | ||
![]() |
c691769e46 | ||
![]() |
19dc30567e | ||
![]() |
a453bccff0 | ||
![]() |
aa2053a575 | ||
![]() |
3d8f71c4d2 | ||
![]() |
6aaaabbc4d | ||
![]() |
42c36f48ed | ||
![]() |
a5f4139102 | ||
![]() |
030d85a9b3 | ||
![]() |
adcfb7fb55 | ||
![]() |
cec365888a | ||
![]() |
55bfa8dd11 | ||
![]() |
e99759fe45 | ||
![]() |
17c6e6ee3f | ||
![]() |
7fff900a1a | ||
![]() |
c67974e4c8 | ||
![]() |
a36696e02e | ||
![]() |
9b80ca6c41 | ||
![]() |
22f514aabf | ||
![]() |
211478e13e | ||
![]() |
5e33a7e58b | ||
![]() |
b2e31721e8 |
@@ -30,6 +30,11 @@ if(NOT CMAKE_CXX_STANDARD)
|
|||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# make sure __cplusplus is defined when using msvc
|
||||||
|
if(MSVC)
|
||||||
|
string(APPEND CMAKE_CXX_FLAGS " /Zc:__cplusplus")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN" OR CMAKE_SYSTEM_NAME MATCHES "MSYS")
|
if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN" OR CMAKE_SYSTEM_NAME MATCHES "MSYS")
|
||||||
@@ -100,6 +105,7 @@ option(
|
|||||||
SPDLOG_NO_ATOMIC_LEVELS
|
SPDLOG_NO_ATOMIC_LEVELS
|
||||||
"prevent spdlog from using of std::atomic log levels (use only if your code never modifies log levels concurrently"
|
"prevent spdlog from using of std::atomic log levels (use only if your code never modifies log levels concurrently"
|
||||||
OFF)
|
OFF)
|
||||||
|
option(SPDLOG_DISABLE_DEFAULT_LOGGER "Disable default logger creation" OFF)
|
||||||
|
|
||||||
# clang-tidy
|
# clang-tidy
|
||||||
if(${CMAKE_VERSION} VERSION_GREATER "3.5")
|
if(${CMAKE_VERSION} VERSION_GREATER "3.5")
|
||||||
@@ -123,7 +129,7 @@ if(NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
|
|||||||
list(APPEND SPDLOG_SRCS src/fmt.cpp)
|
list(APPEND SPDLOG_SRCS src/fmt.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(SPDLOG_BUILD_SHARED)
|
if(SPDLOG_BUILD_SHARED OR BUILD_SHARED_LIBS)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY)
|
||||||
list(APPEND SPDLOG_SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
list(APPEND SPDLOG_SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||||
@@ -131,7 +137,8 @@ if(SPDLOG_BUILD_SHARED)
|
|||||||
add_library(spdlog SHARED ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS})
|
add_library(spdlog SHARED ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS})
|
||||||
target_compile_definitions(spdlog PUBLIC SPDLOG_SHARED_LIB)
|
target_compile_definitions(spdlog PUBLIC SPDLOG_SHARED_LIB)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
target_compile_options(spdlog PUBLIC /wd4251 /wd4275)
|
target_compile_options(spdlog PUBLIC
|
||||||
|
$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<NOT:$<COMPILE_LANGUAGE:CUDA>>>:/wd4251 /wd4275>)
|
||||||
endif()
|
endif()
|
||||||
if(NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
|
if(NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
|
||||||
target_compile_definitions(spdlog PRIVATE FMT_EXPORT PUBLIC FMT_SHARED)
|
target_compile_definitions(spdlog PRIVATE FMT_EXPORT PUBLIC FMT_SHARED)
|
||||||
@@ -171,7 +178,7 @@ target_link_libraries(spdlog_header_only INTERFACE Threads::Threads)
|
|||||||
# ---------------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------------
|
||||||
if(SPDLOG_FMT_EXTERNAL OR SPDLOG_FMT_EXTERNAL_HO)
|
if(SPDLOG_FMT_EXTERNAL OR SPDLOG_FMT_EXTERNAL_HO)
|
||||||
if(NOT TARGET fmt::fmt)
|
if(NOT TARGET fmt::fmt)
|
||||||
find_package(fmt 5.3.0 REQUIRED)
|
find_package(fmt CONFIG REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
target_compile_definitions(spdlog PUBLIC SPDLOG_FMT_EXTERNAL)
|
target_compile_definitions(spdlog PUBLIC SPDLOG_FMT_EXTERNAL)
|
||||||
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_FMT_EXTERNAL)
|
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_FMT_EXTERNAL)
|
||||||
@@ -188,6 +195,14 @@ if(SPDLOG_FMT_EXTERNAL OR SPDLOG_FMT_EXTERNAL_HO)
|
|||||||
set(PKG_CONFIG_REQUIRES fmt) # add dependency to pkg-config
|
set(PKG_CONFIG_REQUIRES fmt) # add dependency to pkg-config
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Add required libraries for Android CMake build
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
if (ANDROID)
|
||||||
|
target_link_libraries(spdlog PUBLIC log)
|
||||||
|
target_link_libraries(spdlog_header_only INTERFACE log)
|
||||||
|
endif ()
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------------
|
||||||
# Misc definitions according to tweak options
|
# Misc definitions according to tweak options
|
||||||
# ---------------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------------
|
||||||
@@ -201,7 +216,8 @@ foreach(
|
|||||||
SPDLOG_PREVENT_CHILD_FD
|
SPDLOG_PREVENT_CHILD_FD
|
||||||
SPDLOG_NO_THREAD_ID
|
SPDLOG_NO_THREAD_ID
|
||||||
SPDLOG_NO_TLS
|
SPDLOG_NO_TLS
|
||||||
SPDLOG_NO_ATOMIC_LEVELS)
|
SPDLOG_NO_ATOMIC_LEVELS
|
||||||
|
SPDLOG_DISABLE_DEFAULT_LOGGER)
|
||||||
if(${SPDLOG_OPTION})
|
if(${SPDLOG_OPTION})
|
||||||
target_compile_definitions(spdlog PUBLIC ${SPDLOG_OPTION})
|
target_compile_definitions(spdlog PUBLIC ${SPDLOG_OPTION})
|
||||||
target_compile_definitions(spdlog_header_only INTERFACE ${SPDLOG_OPTION})
|
target_compile_definitions(spdlog_header_only INTERFACE ${SPDLOG_OPTION})
|
||||||
@@ -289,3 +305,4 @@ if(SPDLOG_INSTALL)
|
|||||||
# ---------------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------------
|
||||||
include(cmake/spdlogCPack.cmake)
|
include(cmake/spdlogCPack.cmake)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@@ -31,6 +31,8 @@ $ cmake .. && make -j
|
|||||||
* vcpkg: `vcpkg install spdlog`
|
* vcpkg: `vcpkg install spdlog`
|
||||||
* conan: `spdlog/[>=1.4.1]`
|
* conan: `spdlog/[>=1.4.1]`
|
||||||
* conda: `conda install -c conda-forge spdlog`
|
* conda: `conda install -c conda-forge spdlog`
|
||||||
|
* build2: ```depends: spdlog ^1.8.2```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
@@ -45,7 +47,8 @@ $ cmake .. && make -j
|
|||||||
* Daily log files.
|
* Daily log files.
|
||||||
* Console logging (colors supported).
|
* Console logging (colors supported).
|
||||||
* syslog.
|
* syslog.
|
||||||
* Windows debugger (```OutputDebugString(..)```)
|
* Windows event log.
|
||||||
|
* Windows debugger (```OutputDebugString(..)```).
|
||||||
* Easily extendable with custom log targets (just implement a single function in the [sink](include/spdlog/sinks/sink.h) interface).
|
* Easily extendable with custom log targets (just implement a single function in the [sink](include/spdlog/sinks/sink.h) interface).
|
||||||
* Log filtering - log levels can be modified in runtime as well as in compile time.
|
* Log filtering - log levels can be modified in runtime as well as in compile time.
|
||||||
* Support for loading log levels from argv or from environment var.
|
* Support for loading log levels from argv or from environment var.
|
||||||
|
36
appveyor.yml
36
appveyor.yml
@@ -4,32 +4,52 @@ environment:
|
|||||||
matrix:
|
matrix:
|
||||||
- GENERATOR: '"Visual Studio 14 2015"'
|
- GENERATOR: '"Visual Studio 14 2015"'
|
||||||
BUILD_TYPE: Debug
|
BUILD_TYPE: Debug
|
||||||
WCHAR: 'OFF'
|
|
||||||
BUILD_SHARED: 'OFF'
|
BUILD_SHARED: 'OFF'
|
||||||
|
WCHAR: 'OFF'
|
||||||
|
WCHAR_FILES: 'OFF'
|
||||||
|
BUILD_EXAMPLE: 'ON'
|
||||||
- GENERATOR: '"Visual Studio 14 2015"'
|
- GENERATOR: '"Visual Studio 14 2015"'
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
WCHAR: 'ON'
|
|
||||||
BUILD_SHARED: 'OFF'
|
BUILD_SHARED: 'OFF'
|
||||||
|
WCHAR: 'ON'
|
||||||
|
WCHAR_FILES: 'OFF'
|
||||||
|
BUILD_EXAMPLE: 'ON'
|
||||||
- GENERATOR: '"Visual Studio 14 2015 Win64"'
|
- GENERATOR: '"Visual Studio 14 2015 Win64"'
|
||||||
BUILD_TYPE: Debug
|
BUILD_TYPE: Debug
|
||||||
WCHAR: 'ON'
|
|
||||||
BUILD_SHARED: 'OFF'
|
BUILD_SHARED: 'OFF'
|
||||||
|
WCHAR: 'ON'
|
||||||
|
WCHAR_FILES: 'OFF'
|
||||||
|
BUILD_EXAMPLE: 'ON'
|
||||||
- GENERATOR: '"Visual Studio 14 2015 Win64"'
|
- GENERATOR: '"Visual Studio 14 2015 Win64"'
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
WCHAR: 'ON'
|
|
||||||
BUILD_SHARED: 'OFF'
|
BUILD_SHARED: 'OFF'
|
||||||
|
WCHAR: 'ON'
|
||||||
|
WCHAR_FILES: 'OFF'
|
||||||
|
BUILD_EXAMPLE: 'ON'
|
||||||
- GENERATOR: '"Visual Studio 15 2017 Win64"'
|
- GENERATOR: '"Visual Studio 15 2017 Win64"'
|
||||||
BUILD_TYPE: Debug
|
BUILD_TYPE: Debug
|
||||||
|
BUILD_SHARED: 'OFF'
|
||||||
WCHAR: 'ON'
|
WCHAR: 'ON'
|
||||||
BUILD_SHARED: 'OFF'
|
WCHAR_FILES: 'OFF'
|
||||||
|
BUILD_EXAMPLE: 'ON'
|
||||||
- GENERATOR: '"Visual Studio 15 2017 Win64"'
|
- GENERATOR: '"Visual Studio 15 2017 Win64"'
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
WCHAR: 'OFF'
|
|
||||||
BUILD_SHARED: 'OFF'
|
BUILD_SHARED: 'OFF'
|
||||||
|
WCHAR: 'OFF'
|
||||||
|
WCHAR_FILES: 'OFF'
|
||||||
|
BUILD_EXAMPLE: 'ON'
|
||||||
- GENERATOR: '"Visual Studio 15 2017 Win64"'
|
- GENERATOR: '"Visual Studio 15 2017 Win64"'
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
WCHAR: 'OFF'
|
|
||||||
BUILD_SHARED: 'ON'
|
BUILD_SHARED: 'ON'
|
||||||
|
WCHAR: 'OFF'
|
||||||
|
WCHAR_FILES: 'OFF'
|
||||||
|
BUILD_EXAMPLE: 'ON'
|
||||||
|
- GENERATOR: '"Visual Studio 15 2017 Win64"'
|
||||||
|
BUILD_TYPE: Release
|
||||||
|
BUILD_SHARED: 'ON'
|
||||||
|
WCHAR: 'ON'
|
||||||
|
WCHAR_FILES: 'ON'
|
||||||
|
BUILD_EXAMPLE: 'OFF'
|
||||||
build_script:
|
build_script:
|
||||||
- cmd: >-
|
- cmd: >-
|
||||||
set
|
set
|
||||||
@@ -40,7 +60,7 @@ build_script:
|
|||||||
|
|
||||||
set PATH=%PATH%;C:\Program Files\Git\usr\bin
|
set PATH=%PATH%;C:\Program Files\Git\usr\bin
|
||||||
|
|
||||||
cmake .. -G %GENERATOR% -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DSPDLOG_WCHAR_SUPPORT=%WCHAR% -DSPDLOG_BUILD_SHARED=%BUILD_SHARED% -DSPDLOG_BUILD_EXAMPLE=ON -DSPDLOG_BUILD_EXAMPLE_HO=ON -DSPDLOG_BUILD_TESTS=ON -DSPDLOG_BUILD_TESTS_HO=OFF -DSPDLOG_BUILD_WARNINGS=ON
|
cmake -G %GENERATOR% -D CMAKE_BUILD_TYPE=%BUILD_TYPE% -D BUILD_SHARED_LIBS=%BUILD_SHARED% -D SPDLOG_WCHAR_SUPPORT=%WCHAR% -D SPDLOG_WCHAR_FILENAMES=%WCHAR_FILES% -D SPDLOG_BUILD_EXAMPLE=%BUILD_EXAMPLE% -D SPDLOG_BUILD_EXAMPLE_HO=%BUILD_EXAMPLE% -D SPDLOG_BUILD_TESTS=ON -D SPDLOG_BUILD_TESTS_HO=OFF -D SPDLOG_BUILD_WARNINGS=ON ..
|
||||||
|
|
||||||
cmake --build . --config %BUILD_TYPE%
|
cmake --build . --config %BUILD_TYPE%
|
||||||
|
|
||||||
|
@@ -9,7 +9,12 @@
|
|||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
#include "spdlog/async.h"
|
#include "spdlog/async.h"
|
||||||
#include "spdlog/sinks/basic_file_sink.h"
|
#include "spdlog/sinks/basic_file_sink.h"
|
||||||
|
|
||||||
|
#ifdef SPDLOG_FMT_EXTERNAL
|
||||||
|
#include <fmt/locale.h>
|
||||||
|
#else
|
||||||
#include "spdlog/fmt/bundled/locale.h"
|
#include "spdlog/fmt/bundled/locale.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
@@ -11,7 +11,12 @@
|
|||||||
#include "spdlog/sinks/daily_file_sink.h"
|
#include "spdlog/sinks/daily_file_sink.h"
|
||||||
#include "spdlog/sinks/null_sink.h"
|
#include "spdlog/sinks/null_sink.h"
|
||||||
#include "spdlog/sinks/rotating_file_sink.h"
|
#include "spdlog/sinks/rotating_file_sink.h"
|
||||||
|
|
||||||
|
#ifdef SPDLOG_FMT_EXTERNAL
|
||||||
|
#include <fmt/locale.h>
|
||||||
|
#else
|
||||||
#include "spdlog/fmt/bundled/locale.h"
|
#include "spdlog/fmt/bundled/locale.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
@@ -34,14 +34,14 @@ void bench_formatters()
|
|||||||
for (auto &flag : all_flags)
|
for (auto &flag : all_flags)
|
||||||
{
|
{
|
||||||
auto pattern = std::string("%") + flag;
|
auto pattern = std::string("%") + flag;
|
||||||
benchmark::RegisterBenchmark(pattern.c_str(), bench_formatter, pattern);
|
benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern);
|
||||||
|
|
||||||
// pattern = std::string("%16") + flag;
|
// pattern = std::string("%16") + flag;
|
||||||
// benchmark::RegisterBenchmark(pattern.c_str(), bench_formatter, pattern);
|
// benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern);
|
||||||
//
|
//
|
||||||
// // bench center padding
|
// // bench center padding
|
||||||
// pattern = std::string("%=16") + flag;
|
// pattern = std::string("%=16") + flag;
|
||||||
// benchmark::RegisterBenchmark(pattern.c_str(), bench_formatter, pattern);
|
// benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
// complex patterns
|
// complex patterns
|
||||||
@@ -52,7 +52,7 @@ void bench_formatters()
|
|||||||
};
|
};
|
||||||
for (auto &pattern : patterns)
|
for (auto &pattern : patterns)
|
||||||
{
|
{
|
||||||
benchmark::RegisterBenchmark(pattern.c_str(), bench_formatter, pattern)->Iterations(2500000);
|
benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern)->Iterations(2500000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
benchmark::RegisterBenchmark(pattern.c_str(), bench_formatter, pattern);
|
benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern);
|
||||||
}
|
}
|
||||||
benchmark::Initialize(&argc, argv);
|
benchmark::Initialize(&argc, argv);
|
||||||
benchmark::RunSpecifiedBenchmarks();
|
benchmark::RunSpecifiedBenchmarks();
|
||||||
|
@@ -59,3 +59,4 @@ function(spdlog_enable_sanitizer target_name)
|
|||||||
target_compile_options(${target_name} PRIVATE -fno-omit-frame-pointer)
|
target_compile_options(${target_name} PRIVATE -fno-omit-frame-pointer)
|
||||||
target_link_libraries(${target_name} PRIVATE -fsanitize=address,undefined -fuse-ld=gold)
|
target_link_libraries(${target_name} PRIVATE -fsanitize=address,undefined -fuse-ld=gold)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@ void syslog_example();
|
|||||||
void custom_flags_example();
|
void custom_flags_example();
|
||||||
|
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
#include "spdlog/cfg/env.h" // for loading levels from the environment variable
|
#include "spdlog/cfg/env.h" // support for loading levels from the environment variable
|
||||||
|
|
||||||
int main(int, char *[])
|
int main(int, char *[])
|
||||||
{
|
{
|
||||||
|
@@ -9,15 +9,24 @@
|
|||||||
|
|
||||||
namespace spdlog {
|
namespace spdlog {
|
||||||
namespace level {
|
namespace level {
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
constexpr
|
||||||
|
#endif
|
||||||
static string_view_t level_string_views[] SPDLOG_LEVEL_NAMES;
|
static string_view_t level_string_views[] SPDLOG_LEVEL_NAMES;
|
||||||
|
|
||||||
static const char *short_level_names[] SPDLOG_SHORT_LEVEL_NAMES;
|
static const char *short_level_names[] SPDLOG_SHORT_LEVEL_NAMES;
|
||||||
|
|
||||||
SPDLOG_INLINE string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT
|
SPDLOG_INLINE const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT
|
||||||
{
|
{
|
||||||
return level_string_views[l];
|
return level_string_views[l];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPDLOG_INLINE void set_string_view(spdlog::level::level_enum l, const string_view_t &s) SPDLOG_NOEXCEPT
|
||||||
|
{
|
||||||
|
level_string_views[l] = s;
|
||||||
|
}
|
||||||
|
|
||||||
SPDLOG_INLINE const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT
|
SPDLOG_INLINE const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT
|
||||||
{
|
{
|
||||||
return short_level_names[l];
|
return short_level_names[l];
|
||||||
|
@@ -88,7 +88,9 @@ class sink;
|
|||||||
|
|
||||||
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
|
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
|
||||||
using filename_t = std::wstring;
|
using filename_t = std::wstring;
|
||||||
#define SPDLOG_FILENAME_T(s) L##s
|
// allow macro expansion to occur in SPDLOG_FILENAME_T
|
||||||
|
#define SPDLOG_FILENAME_T_INNER(s) L##s
|
||||||
|
#define SPDLOG_FILENAME_T(s) SPDLOG_FILENAME_T_INNER(s)
|
||||||
#else
|
#else
|
||||||
using filename_t = std::string;
|
using filename_t = std::string;
|
||||||
#define SPDLOG_FILENAME_T(s) s
|
#define SPDLOG_FILENAME_T(s) s
|
||||||
@@ -101,6 +103,7 @@ using err_handler = std::function<void(const std::string &err_msg)>;
|
|||||||
using string_view_t = fmt::basic_string_view<char>;
|
using string_view_t = fmt::basic_string_view<char>;
|
||||||
using wstring_view_t = fmt::basic_string_view<wchar_t>;
|
using wstring_view_t = fmt::basic_string_view<wchar_t>;
|
||||||
using memory_buf_t = fmt::basic_memory_buffer<char, 250>;
|
using memory_buf_t = fmt::basic_memory_buffer<char, 250>;
|
||||||
|
using wmemory_buf_t = fmt::basic_memory_buffer<wchar_t, 250>;
|
||||||
|
|
||||||
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
|
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
@@ -163,7 +166,8 @@ enum level_enum
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SPDLOG_API string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
|
SPDLOG_API const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
|
||||||
|
SPDLOG_API void set_string_view(spdlog::level::level_enum l, const string_view_t &s) SPDLOG_NOEXCEPT;
|
||||||
SPDLOG_API const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
|
SPDLOG_API const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
|
||||||
SPDLOG_API spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT;
|
SPDLOG_API spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT;
|
||||||
|
|
||||||
@@ -203,8 +207,8 @@ private:
|
|||||||
std::string msg_;
|
std::string msg_;
|
||||||
};
|
};
|
||||||
|
|
||||||
SPDLOG_API void throw_spdlog_ex(const std::string &msg, int last_errno);
|
[[noreturn]] SPDLOG_API void throw_spdlog_ex(const std::string &msg, int last_errno);
|
||||||
SPDLOG_API void throw_spdlog_ex(std::string msg);
|
[[noreturn]] SPDLOG_API void throw_spdlog_ex(std::string msg);
|
||||||
|
|
||||||
struct source_loc
|
struct source_loc
|
||||||
{
|
{
|
||||||
|
@@ -29,12 +29,27 @@ SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate)
|
|||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
filename_ = fname;
|
filename_ = fname;
|
||||||
auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
|
|
||||||
|
auto *mode = SPDLOG_FILENAME_T("ab");
|
||||||
|
auto *trunc_mode = SPDLOG_FILENAME_T("wb");
|
||||||
|
|
||||||
for (int tries = 0; tries < open_tries_; ++tries)
|
for (int tries = 0; tries < open_tries_; ++tries)
|
||||||
{
|
{
|
||||||
// create containing folder if not exists already.
|
// create containing folder if not exists already.
|
||||||
os::create_dir(os::dir_name(fname));
|
os::create_dir(os::dir_name(fname));
|
||||||
|
if (truncate)
|
||||||
|
{
|
||||||
|
// Truncate by opening-and-closing a tmp file in "wb" mode, always
|
||||||
|
// opening the actual log-we-write-to in "ab" mode, since that
|
||||||
|
// interacts more politely with eternal processes that might
|
||||||
|
// rotate/truncate the file underneath us.
|
||||||
|
std::FILE *tmp;
|
||||||
|
if (os::fopen_s(&tmp, fname, trunc_mode))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::fclose(tmp);
|
||||||
|
}
|
||||||
if (!os::fopen_s(&fd_, fname, mode))
|
if (!os::fopen_s(&fd_, fname, mode))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -118,7 +133,7 @@ SPDLOG_INLINE std::tuple<filename_t, filename_t> file_helper::split_by_extension
|
|||||||
}
|
}
|
||||||
|
|
||||||
// treat cases 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);
|
auto folder_index = fname.find_last_of(details::os::folder_seps_filename);
|
||||||
if (folder_index != filename_t::npos && folder_index >= ext_index - 1)
|
if (folder_index != filename_t::npos && folder_index >= ext_index - 1)
|
||||||
{
|
{
|
||||||
return std::make_tuple(fname, filename_t());
|
return std::make_tuple(fname, filename_t());
|
||||||
|
@@ -26,7 +26,9 @@ SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg_buffer &other)
|
|||||||
update_string_views();
|
update_string_views();
|
||||||
}
|
}
|
||||||
|
|
||||||
SPDLOG_INLINE log_msg_buffer::log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT : log_msg{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();
|
update_string_views();
|
||||||
}
|
}
|
||||||
|
@@ -397,17 +397,26 @@ SPDLOG_INLINE bool is_color_terminal() SPDLOG_NOEXCEPT
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
static constexpr std::array<const char *, 14> terms = {
|
|
||||||
{"ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm", "linux", "msys", "putty", "rxvt", "screen", "vt100", "xterm"}};
|
|
||||||
|
|
||||||
const char *env_p = std::getenv("TERM");
|
static const bool result = []() {
|
||||||
if (env_p == nullptr)
|
const char *env_colorterm_p = std::getenv("COLORTERM");
|
||||||
{
|
if (env_colorterm_p != nullptr)
|
||||||
return false;
|
{
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr std::array<const char *, 15> terms = {{"ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm", "linux",
|
||||||
|
"msys", "putty", "rxvt", "screen", "vt100", "xterm", "alacritty"}};
|
||||||
|
|
||||||
|
const char *env_term_p = std::getenv("TERM");
|
||||||
|
if (env_term_p == nullptr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::any_of(terms.begin(), terms.end(), [&](const char *term) { return std::strstr(env_term_p, term) != nullptr; });
|
||||||
|
}();
|
||||||
|
|
||||||
static const bool result =
|
|
||||||
std::any_of(terms.begin(), terms.end(), [&](const char *term) { return std::strstr(env_p, term) != nullptr; });
|
|
||||||
return result;
|
return result;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -427,7 +436,7 @@ SPDLOG_INLINE bool in_terminal(FILE *file) SPDLOG_NOEXCEPT
|
|||||||
#if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)
|
#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)
|
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)()) / 2 - 1)
|
||||||
{
|
{
|
||||||
throw_spdlog_ex("UTF-16 string is too big to be converted to UTF-8");
|
throw_spdlog_ex("UTF-16 string is too big to be converted to UTF-8");
|
||||||
}
|
}
|
||||||
@@ -459,6 +468,41 @@ SPDLOG_INLINE void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target)
|
|||||||
|
|
||||||
throw_spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError()));
|
throw_spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPDLOG_INLINE void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target)
|
||||||
|
{
|
||||||
|
if (str.size() > static_cast<size_t>((std::numeric_limits<int>::max)()) - 1)
|
||||||
|
{
|
||||||
|
throw_spdlog_ex("UTF-8 string is too big to be converted to UTF-16");
|
||||||
|
}
|
||||||
|
|
||||||
|
int str_size = static_cast<int>(str.size());
|
||||||
|
if (str_size == 0)
|
||||||
|
{
|
||||||
|
target.resize(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result_size = static_cast<int>(target.capacity());
|
||||||
|
if (str_size + 1 > result_size)
|
||||||
|
{
|
||||||
|
result_size = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.data(), str_size, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result_size > 0)
|
||||||
|
{
|
||||||
|
target.resize(result_size);
|
||||||
|
result_size = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.data(), str_size, target.data(), result_size);
|
||||||
|
|
||||||
|
if (result_size > 0)
|
||||||
|
{
|
||||||
|
target.resize(result_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw_spdlog_ex(fmt::format("MultiByteToWideChar failed. Last error: {}", ::GetLastError()));
|
||||||
|
}
|
||||||
#endif // (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)
|
#endif // (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)
|
||||||
|
|
||||||
// return true on success
|
// return true on success
|
||||||
@@ -489,15 +533,10 @@ SPDLOG_INLINE bool create_dir(filename_t path)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
// support forward slash in windows
|
|
||||||
std::replace(path.begin(), path.end(), '/', folder_sep);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
size_t search_offset = 0;
|
size_t search_offset = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
auto token_pos = path.find(folder_sep, search_offset);
|
auto token_pos = path.find_first_of(folder_seps_filename, search_offset);
|
||||||
// treat the entire path as a folder if no folder separator not found
|
// treat the entire path as a folder if no folder separator not found
|
||||||
if (token_pos == filename_t::npos)
|
if (token_pos == filename_t::npos)
|
||||||
{
|
{
|
||||||
@@ -523,11 +562,7 @@ SPDLOG_INLINE bool create_dir(filename_t path)
|
|||||||
// "abc///" => "abc//"
|
// "abc///" => "abc//"
|
||||||
SPDLOG_INLINE filename_t dir_name(filename_t path)
|
SPDLOG_INLINE filename_t dir_name(filename_t path)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
auto pos = path.find_last_of(folder_seps_filename);
|
||||||
// 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{};
|
return pos != filename_t::npos ? path.substr(0, pos) : filename_t{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,11 +32,16 @@ SPDLOG_API std::tm gmtime() SPDLOG_NOEXCEPT;
|
|||||||
SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL;
|
SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL;
|
||||||
|
|
||||||
// folder separator
|
// folder separator
|
||||||
|
#if !defined(SPDLOG_FOLDER_SEPS)
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static const char folder_sep = '\\';
|
#define SPDLOG_FOLDER_SEPS "\\/"
|
||||||
#else
|
#else
|
||||||
SPDLOG_CONSTEXPR static const char folder_sep = '/';
|
#define SPDLOG_FOLDER_SEPS "/"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SPDLOG_CONSTEXPR static const char folder_seps[] = SPDLOG_FOLDER_SEPS;
|
||||||
|
SPDLOG_CONSTEXPR static const filename_t::value_type folder_seps_filename[] = SPDLOG_FILENAME_T(SPDLOG_FOLDER_SEPS);
|
||||||
|
|
||||||
// fopen_s on non windows for writing
|
// fopen_s on non windows for writing
|
||||||
SPDLOG_API bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode);
|
SPDLOG_API bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode);
|
||||||
@@ -85,6 +90,8 @@ SPDLOG_API bool in_terminal(FILE *file) SPDLOG_NOEXCEPT;
|
|||||||
|
|
||||||
#if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)
|
#if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)
|
||||||
SPDLOG_API void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target);
|
SPDLOG_API void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target);
|
||||||
|
|
||||||
|
SPDLOG_API void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Return directory name from given path or empty string
|
// Return directory name from given path or empty string
|
||||||
|
@@ -99,7 +99,7 @@ private:
|
|||||||
std::unique_ptr<formatter> formatter_;
|
std::unique_ptr<formatter> formatter_;
|
||||||
spdlog::level::level_enum global_log_level_ = level::info;
|
spdlog::level::level_enum global_log_level_ = level::info;
|
||||||
level::level_enum flush_level_ = level::off;
|
level::level_enum flush_level_ = level::off;
|
||||||
void (*err_handler_)(const std::string &msg);
|
void (*err_handler_)(const std::string &msg) = nullptr;
|
||||||
std::shared_ptr<thread_pool> tp_;
|
std::shared_ptr<thread_pool> tp_;
|
||||||
std::unique_ptr<periodic_worker> periodic_flusher_;
|
std::unique_ptr<periodic_worker> periodic_flusher_;
|
||||||
std::shared_ptr<logger> default_logger_;
|
std::shared_ptr<logger> default_logger_;
|
||||||
|
@@ -13,11 +13,13 @@
|
|||||||
#include <spdlog/fmt/fmt.h>
|
#include <spdlog/fmt/fmt.h>
|
||||||
#include <spdlog/formatter.h>
|
#include <spdlog/formatter.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iterator>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -127,7 +129,7 @@ public:
|
|||||||
|
|
||||||
void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override
|
void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override
|
||||||
{
|
{
|
||||||
string_view_t &level_name = level::to_string_view(msg.level);
|
const string_view_t &level_name = level::to_string_view(msg.level);
|
||||||
ScopedPadder p(level_name.size(), padinfo_, dest);
|
ScopedPadder p(level_name.size(), padinfo_, dest);
|
||||||
fmt_helper::append_string_view(level_name, dest);
|
fmt_helper::append_string_view(level_name, dest);
|
||||||
}
|
}
|
||||||
@@ -814,11 +816,31 @@ public:
|
|||||||
: flag_formatter(padinfo)
|
: flag_formatter(padinfo)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4127) // consider using 'if constexpr' instead
|
||||||
|
#endif // _MSC_VER
|
||||||
static const char *basename(const char *filename)
|
static const char *basename(const char *filename)
|
||||||
{
|
{
|
||||||
const char *rv = std::strrchr(filename, os::folder_sep);
|
// if the size is 2 (1 character + null terminator) we can use the more efficient strrchr
|
||||||
return rv != nullptr ? rv + 1 : filename;
|
// the branch will be elided by optimizations
|
||||||
|
if (sizeof(os::folder_seps) == 2)
|
||||||
|
{
|
||||||
|
const char *rv = std::strrchr(filename, os::folder_seps[0]);
|
||||||
|
return rv != nullptr ? rv + 1 : filename;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const std::reverse_iterator<const char*> begin(filename + std::strlen(filename));
|
||||||
|
const std::reverse_iterator<const char*> end(filename);
|
||||||
|
|
||||||
|
const auto it = std::find_first_of(begin, end, std::begin(os::folder_seps), std::end(os::folder_seps) - 1);
|
||||||
|
return it != end ? it.base() : filename;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override
|
void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override
|
||||||
{
|
{
|
||||||
|
@@ -106,6 +106,8 @@ SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_color_mode(color_mode mode)
|
|||||||
case color_mode::never:
|
case color_mode::never:
|
||||||
should_do_colors_ = false;
|
should_do_colors_ = false;
|
||||||
return;
|
return;
|
||||||
|
default:
|
||||||
|
should_do_colors_ = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#include <spdlog/details/file_helper.h>
|
#include <spdlog/details/file_helper.h>
|
||||||
#include <spdlog/details/null_mutex.h>
|
#include <spdlog/details/null_mutex.h>
|
||||||
#include <spdlog/fmt/fmt.h>
|
#include <spdlog/fmt/fmt.h>
|
||||||
|
#include <spdlog/fmt/chrono.h>
|
||||||
#include <spdlog/sinks/base_sink.h>
|
#include <spdlog/sinks/base_sink.h>
|
||||||
#include <spdlog/details/os.h>
|
#include <spdlog/details/os.h>
|
||||||
#include <spdlog/details/circular_q.h>
|
#include <spdlog/details/circular_q.h>
|
||||||
@@ -36,6 +37,23 @@ struct daily_filename_calculator
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generator of daily log file names with strftime format.
|
||||||
|
* Usages:
|
||||||
|
* auto sink = std::make_shared<spdlog::sinks::daily_file_format_sink_mt>("myapp-%Y-%m-%d:%H:%M:%S.log", hour, minute);"
|
||||||
|
* auto logger = spdlog::daily_logger_format_mt("loggername, "myapp-%Y-%m-%d:%X.log", hour, minute)"
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct daily_filename_format_calculator
|
||||||
|
{
|
||||||
|
static filename_t calc_filename (const filename_t &filename, const tm &now_tm)
|
||||||
|
{
|
||||||
|
// generate fmt datetime format string, e.g. {:%Y-%m-%d}.
|
||||||
|
filename_t fmt_filename = fmt::format(SPDLOG_FILENAME_T ("{{:{}}}"), filename);
|
||||||
|
return fmt::format(fmt_filename, now_tm);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rotating file sink based on date.
|
* Rotating file sink based on date.
|
||||||
* If truncate != false , the created file will be truncated.
|
* If truncate != false , the created file will be truncated.
|
||||||
@@ -182,6 +200,8 @@ private:
|
|||||||
|
|
||||||
using daily_file_sink_mt = daily_file_sink<std::mutex>;
|
using daily_file_sink_mt = daily_file_sink<std::mutex>;
|
||||||
using daily_file_sink_st = daily_file_sink<details::null_mutex>;
|
using daily_file_sink_st = daily_file_sink<details::null_mutex>;
|
||||||
|
using daily_file_format_sink_mt = daily_file_sink<std::mutex, daily_filename_format_calculator>;
|
||||||
|
using daily_file_format_sink_st = daily_file_sink<details::null_mutex, daily_filename_format_calculator>;
|
||||||
|
|
||||||
} // namespace sinks
|
} // namespace sinks
|
||||||
|
|
||||||
@@ -195,10 +215,24 @@ inline std::shared_ptr<logger> daily_logger_mt(
|
|||||||
return Factory::template create<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute, truncate, max_files);
|
return Factory::template create<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute, truncate, max_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Factory = spdlog::synchronous_factory>
|
||||||
|
inline std::shared_ptr<logger> daily_logger_format_mt(
|
||||||
|
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0)
|
||||||
|
{
|
||||||
|
return Factory::template create<sinks::daily_file_format_sink_mt>(logger_name, filename, hour, minute, truncate, max_files);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Factory = spdlog::synchronous_factory>
|
template<typename Factory = spdlog::synchronous_factory>
|
||||||
inline std::shared_ptr<logger> daily_logger_st(
|
inline std::shared_ptr<logger> daily_logger_st(
|
||||||
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0)
|
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0)
|
||||||
{
|
{
|
||||||
return Factory::template create<sinks::daily_file_sink_st>(logger_name, filename, hour, minute, truncate, max_files);
|
return Factory::template create<sinks::daily_file_sink_st>(logger_name, filename, hour, minute, truncate, max_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Factory = spdlog::synchronous_factory>
|
||||||
|
inline std::shared_ptr<logger> daily_logger_format_st(
|
||||||
|
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0)
|
||||||
|
{
|
||||||
|
return Factory::template create<sinks::daily_file_format_sink_st>(logger_name, filename, hour, minute, truncate, max_files);
|
||||||
|
}
|
||||||
} // namespace spdlog
|
} // namespace spdlog
|
||||||
|
194
include/spdlog/sinks/hourly_file_sink.h
Normal file
194
include/spdlog/sinks/hourly_file_sink.h
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||||
|
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
|
#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/circular_q.h>
|
||||||
|
#include <spdlog/details/synchronous_factory.h>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <ctime>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace spdlog {
|
||||||
|
namespace sinks {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generator of Hourly log file names in format basename.YYYY-MM-DD-HH.ext
|
||||||
|
*/
|
||||||
|
struct hourly_filename_calculator
|
||||||
|
{
|
||||||
|
// Create filename for the form basename.YYYY-MM-DD-H
|
||||||
|
static filename_t calc_filename(const filename_t &filename, const tm &now_tm)
|
||||||
|
{
|
||||||
|
filename_t basename, ext;
|
||||||
|
std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
|
||||||
|
return fmt::format(
|
||||||
|
SPDLOG_FILENAME_T("{}_{:04d}{:02d}{:02d}_{:02d}{}"), basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday, now_tm.tm_hour, ext);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rotating file sink based on time.
|
||||||
|
* If truncate != false , the created file will be truncated.
|
||||||
|
* If max_files > 0, retain only the last max_files and delete previous.
|
||||||
|
*/
|
||||||
|
template<typename Mutex, typename FileNameCalc = hourly_filename_calculator>
|
||||||
|
class hourly_file_sink final : public base_sink<Mutex>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// create hourly file sink which rotates on given time
|
||||||
|
hourly_file_sink(filename_t base_filename, bool truncate = false, uint16_t max_files = 0)
|
||||||
|
: base_filename_(std::move(base_filename))
|
||||||
|
, truncate_(truncate)
|
||||||
|
, max_files_(max_files)
|
||||||
|
, filenames_q_()
|
||||||
|
{
|
||||||
|
auto now = log_clock::now();
|
||||||
|
auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now));
|
||||||
|
file_helper_.open(filename, truncate_);
|
||||||
|
rotation_tp_ = next_rotation_tp_();
|
||||||
|
|
||||||
|
if (max_files_ > 0)
|
||||||
|
{
|
||||||
|
init_filenames_q_();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filename_t filename()
|
||||||
|
{
|
||||||
|
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
|
||||||
|
return file_helper_.filename();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void sink_it_(const details::log_msg &msg) override
|
||||||
|
{
|
||||||
|
auto time = msg.time;
|
||||||
|
bool should_rotate = time >= rotation_tp_;
|
||||||
|
if (should_rotate)
|
||||||
|
{
|
||||||
|
auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(time));
|
||||||
|
file_helper_.open(filename, truncate_);
|
||||||
|
rotation_tp_ = next_rotation_tp_();
|
||||||
|
}
|
||||||
|
memory_buf_t formatted;
|
||||||
|
base_sink<Mutex>::formatter_->format(msg, formatted);
|
||||||
|
file_helper_.write(formatted);
|
||||||
|
|
||||||
|
// Do the cleaning only at the end because it might throw on failure.
|
||||||
|
if (should_rotate && max_files_ > 0)
|
||||||
|
{
|
||||||
|
delete_old_();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_() override
|
||||||
|
{
|
||||||
|
file_helper_.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init_filenames_q_()
|
||||||
|
{
|
||||||
|
using details::os::path_exists;
|
||||||
|
|
||||||
|
filenames_q_ = details::circular_q<filename_t>(static_cast<size_t>(max_files_));
|
||||||
|
std::vector<filename_t> filenames;
|
||||||
|
auto now = log_clock::now();
|
||||||
|
while (filenames.size() < max_files_)
|
||||||
|
{
|
||||||
|
auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now));
|
||||||
|
if (!path_exists(filename))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
filenames.emplace_back(filename);
|
||||||
|
now -= std::chrono::hours(1);
|
||||||
|
}
|
||||||
|
for (auto iter = filenames.rbegin(); iter != filenames.rend(); ++iter)
|
||||||
|
{
|
||||||
|
filenames_q_.push_back(std::move(*iter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tm now_tm(log_clock::time_point tp)
|
||||||
|
{
|
||||||
|
time_t tnow = log_clock::to_time_t(tp);
|
||||||
|
return spdlog::details::os::localtime(tnow);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_clock::time_point next_rotation_tp_()
|
||||||
|
{
|
||||||
|
auto now = log_clock::now();
|
||||||
|
tm date = now_tm(now);
|
||||||
|
date.tm_min = 0;
|
||||||
|
date.tm_sec = 0;
|
||||||
|
auto rotation_time = log_clock::from_time_t(std::mktime(&date));
|
||||||
|
if (rotation_time > now)
|
||||||
|
{
|
||||||
|
return rotation_time;
|
||||||
|
}
|
||||||
|
return {rotation_time + std::chrono::hours(1)};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the file N rotations ago.
|
||||||
|
// Throw spdlog_ex on failure to delete the old file.
|
||||||
|
void delete_old_()
|
||||||
|
{
|
||||||
|
using details::os::filename_to_str;
|
||||||
|
using details::os::remove_if_exists;
|
||||||
|
|
||||||
|
filename_t current_file = file_helper_.filename();
|
||||||
|
if (filenames_q_.full())
|
||||||
|
{
|
||||||
|
auto old_filename = std::move(filenames_q_.front());
|
||||||
|
filenames_q_.pop_front();
|
||||||
|
bool ok = remove_if_exists(old_filename) == 0;
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
filenames_q_.push_back(std::move(current_file));
|
||||||
|
SPDLOG_THROW(spdlog_ex("Failed removing hourly file " + filename_to_str(old_filename), errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filenames_q_.push_back(std::move(current_file));
|
||||||
|
}
|
||||||
|
|
||||||
|
filename_t base_filename_;
|
||||||
|
log_clock::time_point rotation_tp_;
|
||||||
|
details::file_helper file_helper_;
|
||||||
|
bool truncate_;
|
||||||
|
uint16_t max_files_;
|
||||||
|
details::circular_q<filename_t> filenames_q_;
|
||||||
|
};
|
||||||
|
|
||||||
|
using hourly_file_sink_mt = hourly_file_sink<std::mutex>;
|
||||||
|
using hourly_file_sink_st = hourly_file_sink<details::null_mutex>;
|
||||||
|
|
||||||
|
} // namespace sinks
|
||||||
|
|
||||||
|
//
|
||||||
|
// factory functions
|
||||||
|
//
|
||||||
|
template<typename Factory = spdlog::synchronous_factory>
|
||||||
|
inline std::shared_ptr<logger> hourly_logger_mt(
|
||||||
|
const std::string &logger_name, const filename_t &filename, bool truncate = false, uint16_t max_files = 0)
|
||||||
|
{
|
||||||
|
return Factory::template create<sinks::hourly_file_sink_mt>(logger_name, filename, truncate, max_files);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Factory = spdlog::synchronous_factory>
|
||||||
|
inline std::shared_ptr<logger> hourly_logger_st(
|
||||||
|
const std::string &logger_name, const filename_t &filename, bool truncate = false, uint16_t max_files = 0)
|
||||||
|
{
|
||||||
|
return Factory::template create<sinks::hourly_file_sink_st>(logger_name, filename, truncate, max_files);
|
||||||
|
}
|
||||||
|
} // namespace spdlog
|
@@ -32,8 +32,13 @@ SPDLOG_INLINE stdout_sink_base<ConsoleMutex>::stdout_sink_base(FILE *file)
|
|||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// get windows handle from the FILE* object
|
// get windows handle from the FILE* object
|
||||||
handle_ = (HANDLE)::_get_osfhandle(::_fileno(file_));
|
|
||||||
if (handle_ == INVALID_HANDLE_VALUE)
|
handle_ = (HANDLE)::_get_osfhandle(::_fileno(file_));
|
||||||
|
|
||||||
|
// don't throw to support cases where no console is attached,
|
||||||
|
// and let the log method to do nothing if (handle_ == INVALID_HANDLE_VALUE).
|
||||||
|
// throw only if non stdout/stderr target is requested (probably regular file and not console).
|
||||||
|
if (handle_ == INVALID_HANDLE_VALUE && file != stdout && file != stderr)
|
||||||
{
|
{
|
||||||
throw_spdlog_ex("spdlog::stdout_sink_base: _get_osfhandle() failed", errno);
|
throw_spdlog_ex("spdlog::stdout_sink_base: _get_osfhandle() failed", errno);
|
||||||
}
|
}
|
||||||
@@ -43,10 +48,14 @@ SPDLOG_INLINE stdout_sink_base<ConsoleMutex>::stdout_sink_base(FILE *file)
|
|||||||
template<typename ConsoleMutex>
|
template<typename ConsoleMutex>
|
||||||
SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::log(const details::log_msg &msg)
|
SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::log(const details::log_msg &msg)
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (handle_ == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
std::lock_guard<mutex_t> lock(mutex_);
|
std::lock_guard<mutex_t> lock(mutex_);
|
||||||
memory_buf_t formatted;
|
memory_buf_t formatted;
|
||||||
formatter_->format(msg, formatted);
|
formatter_->format(msg, formatted);
|
||||||
#ifdef _WIN32
|
|
||||||
::fflush(file_); // flush in case there is somthing in this file_ already
|
::fflush(file_); // flush in case there is somthing in this file_ already
|
||||||
auto size = static_cast<DWORD>(formatted.size());
|
auto size = static_cast<DWORD>(formatted.size());
|
||||||
DWORD bytes_written = 0;
|
DWORD bytes_written = 0;
|
||||||
@@ -56,6 +65,9 @@ SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::log(const details::log_msg &m
|
|||||||
throw_spdlog_ex("stdout_sink_base: WriteFile() failed. GetLastError(): " + std::to_string(::GetLastError()));
|
throw_spdlog_ex("stdout_sink_base: WriteFile() failed. GetLastError(): " + std::to_string(::GetLastError()));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
std::lock_guard<mutex_t> lock(mutex_);
|
||||||
|
memory_buf_t formatted;
|
||||||
|
formatter_->format(msg, formatted);
|
||||||
::fwrite(formatted.data(), sizeof(char), formatted.size(), file_);
|
::fwrite(formatted.data(), sizeof(char), formatted.size(), file_);
|
||||||
::fflush(file_); // flush every line to terminal
|
::fflush(file_); // flush every line to terminal
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
@@ -57,7 +57,7 @@ struct win32_error : public spdlog_ex
|
|||||||
|
|
||||||
LPSTR format_message_result{};
|
LPSTR format_message_result{};
|
||||||
auto format_message_succeeded =
|
auto format_message_succeeded =
|
||||||
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
|
::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
|
||||||
error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&format_message_result, 0, nullptr);
|
error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&format_message_result, 0, nullptr);
|
||||||
|
|
||||||
if (format_message_succeeded && format_message_result)
|
if (format_message_succeeded && format_message_result)
|
||||||
@@ -203,7 +203,7 @@ private:
|
|||||||
{
|
{
|
||||||
if (!hEventLog_)
|
if (!hEventLog_)
|
||||||
{
|
{
|
||||||
hEventLog_ = ::RegisterEventSource(nullptr, source_.c_str());
|
hEventLog_ = ::RegisterEventSourceA(nullptr, source_.c_str());
|
||||||
if (!hEventLog_ || hEventLog_ == (HANDLE)ERROR_ACCESS_DENIED)
|
if (!hEventLog_ || hEventLog_ == (HANDLE)ERROR_ACCESS_DENIED)
|
||||||
{
|
{
|
||||||
SPDLOG_THROW(internal::win32_error("RegisterEventSource"));
|
SPDLOG_THROW(internal::win32_error("RegisterEventSource"));
|
||||||
@@ -218,13 +218,23 @@ protected:
|
|||||||
{
|
{
|
||||||
using namespace internal;
|
using namespace internal;
|
||||||
|
|
||||||
|
bool succeeded;
|
||||||
memory_buf_t formatted;
|
memory_buf_t formatted;
|
||||||
base_sink<Mutex>::formatter_->format(msg, formatted);
|
base_sink<Mutex>::formatter_->format(msg, formatted);
|
||||||
formatted.push_back('\0');
|
formatted.push_back('\0');
|
||||||
LPCSTR lp_str = static_cast<LPCSTR>(formatted.data());
|
|
||||||
|
|
||||||
auto succeeded = ::ReportEvent(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_,
|
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
|
||||||
current_user_sid_.as_sid(), 1, 0, &lp_str, nullptr);
|
wmemory_buf_t buf;
|
||||||
|
details::os::utf8_to_wstrbuf(string_view_t(formatted.data(), formatted.size()), buf);
|
||||||
|
|
||||||
|
LPCWSTR lp_wstr = buf.data();
|
||||||
|
succeeded = ::ReportEventW(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_,
|
||||||
|
current_user_sid_.as_sid(), 1, 0, &lp_wstr, nullptr);
|
||||||
|
#else
|
||||||
|
LPCSTR lp_str = formatted.data();
|
||||||
|
succeeded = ::ReportEventA(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_,
|
||||||
|
current_user_sid_.as_sid(), 1, 0, &lp_str, nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!succeeded)
|
if (!succeeded)
|
||||||
{
|
{
|
||||||
|
@@ -7,30 +7,30 @@
|
|||||||
#include <spdlog/sinks/wincolor_sink.h>
|
#include <spdlog/sinks/wincolor_sink.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <spdlog/details/windows_include.h>
|
||||||
|
#include <wincon.h>
|
||||||
|
|
||||||
#include <spdlog/common.h>
|
#include <spdlog/common.h>
|
||||||
#include <spdlog/pattern_formatter.h>
|
#include <spdlog/pattern_formatter.h>
|
||||||
|
|
||||||
namespace spdlog {
|
namespace spdlog {
|
||||||
namespace sinks {
|
namespace sinks {
|
||||||
|
|
||||||
template<typename ConsoleMutex>
|
template<typename ConsoleMutex>
|
||||||
SPDLOG_INLINE wincolor_sink<ConsoleMutex>::wincolor_sink(HANDLE out_handle, color_mode mode)
|
SPDLOG_INLINE wincolor_sink<ConsoleMutex>::wincolor_sink(void *out_handle, color_mode mode)
|
||||||
: out_handle_(out_handle)
|
: out_handle_(out_handle)
|
||||||
, mutex_(ConsoleMutex::mutex())
|
, mutex_(ConsoleMutex::mutex())
|
||||||
, formatter_(details::make_unique<spdlog::pattern_formatter>())
|
, formatter_(details::make_unique<spdlog::pattern_formatter>())
|
||||||
{
|
{
|
||||||
// check if out_handle is points to the actual console.
|
|
||||||
// ::GetConsoleMode() should return 0 if it is redirected or not valid console handle.
|
|
||||||
DWORD console_mode;
|
|
||||||
in_console_ = ::GetConsoleMode(out_handle, &console_mode) != 0;
|
|
||||||
|
|
||||||
set_color_mode(mode);
|
set_color_mode_impl(mode);
|
||||||
colors_[level::trace] = WHITE;
|
// set level colors
|
||||||
colors_[level::debug] = CYAN;
|
colors_[level::trace] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; // white
|
||||||
colors_[level::info] = GREEN;
|
colors_[level::debug] = FOREGROUND_GREEN | FOREGROUND_BLUE; // cyan
|
||||||
colors_[level::warn] = YELLOW | BOLD;
|
colors_[level::info] = FOREGROUND_GREEN; // green
|
||||||
colors_[level::err] = RED | BOLD; // red bold
|
colors_[level::warn] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; // intense yellow
|
||||||
colors_[level::critical] = BACKGROUND_RED | WHITE | BOLD; // white bold on red background
|
colors_[level::err] = FOREGROUND_RED | FOREGROUND_INTENSITY; // intense red
|
||||||
|
colors_[level::critical] =
|
||||||
|
BACKGROUND_RED | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; // intense white on red background
|
||||||
colors_[level::off] = 0;
|
colors_[level::off] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ SPDLOG_INLINE wincolor_sink<ConsoleMutex>::~wincolor_sink()
|
|||||||
|
|
||||||
// change the color for the given level
|
// change the color for the given level
|
||||||
template<typename ConsoleMutex>
|
template<typename ConsoleMutex>
|
||||||
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color(level::level_enum level, WORD color)
|
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color(level::level_enum level, std::uint16_t color)
|
||||||
{
|
{
|
||||||
std::lock_guard<mutex_t> lock(mutex_);
|
std::lock_guard<mutex_t> lock(mutex_);
|
||||||
colors_[level] = color;
|
colors_[level] = color;
|
||||||
@@ -51,31 +51,30 @@ void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color(level::level_enum leve
|
|||||||
template<typename ConsoleMutex>
|
template<typename ConsoleMutex>
|
||||||
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::log(const details::log_msg &msg)
|
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::log(const details::log_msg &msg)
|
||||||
{
|
{
|
||||||
|
if (out_handle_ == nullptr || out_handle_ == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::lock_guard<mutex_t> lock(mutex_);
|
std::lock_guard<mutex_t> lock(mutex_);
|
||||||
msg.color_range_start = 0;
|
msg.color_range_start = 0;
|
||||||
msg.color_range_end = 0;
|
msg.color_range_end = 0;
|
||||||
memory_buf_t formatted;
|
memory_buf_t formatted;
|
||||||
formatter_->format(msg, formatted);
|
formatter_->format(msg, formatted);
|
||||||
if (!in_console_)
|
|
||||||
{
|
|
||||||
write_to_file_(formatted);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (should_do_colors_ && msg.color_range_end > msg.color_range_start)
|
if (should_do_colors_ && msg.color_range_end > msg.color_range_start)
|
||||||
{
|
{
|
||||||
// before color range
|
// before color range
|
||||||
print_range_(formatted, 0, msg.color_range_start);
|
print_range_(formatted, 0, msg.color_range_start);
|
||||||
|
|
||||||
// in color range
|
// in color range
|
||||||
auto orig_attribs = set_foreground_color_(colors_[msg.level]);
|
auto orig_attribs = static_cast<WORD>(set_foreground_color_(colors_[msg.level]));
|
||||||
print_range_(formatted, msg.color_range_start, msg.color_range_end);
|
print_range_(formatted, msg.color_range_start, msg.color_range_end);
|
||||||
// reset to orig colors
|
// reset to orig colors
|
||||||
::SetConsoleTextAttribute(out_handle_, orig_attribs);
|
::SetConsoleTextAttribute(static_cast<HANDLE>(out_handle_), orig_attribs);
|
||||||
print_range_(formatted, msg.color_range_end, formatted.size());
|
print_range_(formatted, msg.color_range_end, formatted.size());
|
||||||
}
|
}
|
||||||
else // print without colors if color range is invalid (or color is disabled)
|
else // print without colors if color range is invalid (or color is disabled)
|
||||||
{
|
{
|
||||||
print_range_(formatted, 0, formatted.size());
|
write_to_file_(formatted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,56 +101,63 @@ void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_formatter(std::unique_ptr<sp
|
|||||||
template<typename ConsoleMutex>
|
template<typename ConsoleMutex>
|
||||||
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color_mode(color_mode mode)
|
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color_mode(color_mode mode)
|
||||||
{
|
{
|
||||||
switch (mode)
|
std::lock_guard<mutex_t> lock(mutex_);
|
||||||
|
set_color_mode_impl(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ConsoleMutex>
|
||||||
|
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color_mode_impl(color_mode mode)
|
||||||
|
{
|
||||||
|
if (mode == color_mode::automatic)
|
||||||
{
|
{
|
||||||
case color_mode::always:
|
// should do colors only if out_handle_ points to actual console.
|
||||||
case color_mode::automatic:
|
DWORD console_mode;
|
||||||
should_do_colors_ = true;
|
bool in_console = ::GetConsoleMode(static_cast<HANDLE>(out_handle_), &console_mode) != 0;
|
||||||
break;
|
should_do_colors_ = in_console;
|
||||||
case color_mode::never:
|
}
|
||||||
should_do_colors_ = false;
|
else
|
||||||
break;
|
{
|
||||||
default:
|
should_do_colors_ = mode == color_mode::always ? true : false;
|
||||||
should_do_colors_ = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set foreground color and return the orig console attributes (for resetting later)
|
// set foreground color and return the orig console attributes (for resetting later)
|
||||||
template<typename ConsoleMutex>
|
template<typename ConsoleMutex>
|
||||||
WORD SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_foreground_color_(WORD attribs)
|
std::uint16_t SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_foreground_color_(std::uint16_t attribs)
|
||||||
{
|
{
|
||||||
CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info;
|
CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info;
|
||||||
::GetConsoleScreenBufferInfo(out_handle_, &orig_buffer_info);
|
if (!::GetConsoleScreenBufferInfo(static_cast<HANDLE>(out_handle_), &orig_buffer_info))
|
||||||
WORD back_color = orig_buffer_info.wAttributes;
|
{
|
||||||
// retrieve the current background color
|
// just return white if failed getting console info
|
||||||
back_color &= static_cast<WORD>(~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY));
|
return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
||||||
// keep the background color unchanged
|
}
|
||||||
::SetConsoleTextAttribute(out_handle_, attribs | back_color);
|
|
||||||
return orig_buffer_info.wAttributes; // return orig attribs
|
// change only the foreground bits (lowest 4 bits)
|
||||||
|
auto new_attribs = static_cast<WORD>(attribs) | (orig_buffer_info.wAttributes & 0xfff0);
|
||||||
|
auto ignored = ::SetConsoleTextAttribute(static_cast<HANDLE>(out_handle_), static_cast<WORD>(new_attribs));
|
||||||
|
(void)(ignored);
|
||||||
|
return static_cast<std::uint16_t>(orig_buffer_info.wAttributes); // return orig attribs
|
||||||
}
|
}
|
||||||
|
|
||||||
// print a range of formatted message to console
|
// print a range of formatted message to console
|
||||||
template<typename ConsoleMutex>
|
template<typename ConsoleMutex>
|
||||||
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::print_range_(const memory_buf_t &formatted, size_t start, size_t end)
|
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::print_range_(const memory_buf_t &formatted, size_t start, size_t end)
|
||||||
{
|
{
|
||||||
auto size = static_cast<DWORD>(end - start);
|
if (end > start)
|
||||||
::WriteConsoleA(out_handle_, formatted.data() + start, size, nullptr, nullptr);
|
{
|
||||||
|
auto size = static_cast<DWORD>(end - start);
|
||||||
|
auto ignored = ::WriteConsoleA(static_cast<HANDLE>(out_handle_), formatted.data() + start, size, nullptr, nullptr);
|
||||||
|
(void)(ignored);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ConsoleMutex>
|
template<typename ConsoleMutex>
|
||||||
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::write_to_file_(const memory_buf_t &formatted)
|
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::write_to_file_(const memory_buf_t &formatted)
|
||||||
{
|
{
|
||||||
if (out_handle_ == nullptr) // no console and no file redirect
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto size = static_cast<DWORD>(formatted.size());
|
auto size = static_cast<DWORD>(formatted.size());
|
||||||
DWORD bytes_written = 0;
|
DWORD bytes_written = 0;
|
||||||
bool ok = ::WriteFile(out_handle_, formatted.data(), size, &bytes_written, nullptr) != 0;
|
auto ignored = ::WriteFile(static_cast<HANDLE>(out_handle_), formatted.data(), size, &bytes_written, nullptr);
|
||||||
if (!ok)
|
(void)(ignored);
|
||||||
{
|
|
||||||
throw_spdlog_ex("wincolor_sink: ::WriteFile() failed. GetLastError(): " + std::to_string(::GetLastError()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// wincolor_stdout_sink
|
// wincolor_stdout_sink
|
||||||
@@ -165,6 +171,5 @@ template<typename ConsoleMutex>
|
|||||||
SPDLOG_INLINE wincolor_stderr_sink<ConsoleMutex>::wincolor_stderr_sink(color_mode mode)
|
SPDLOG_INLINE wincolor_stderr_sink<ConsoleMutex>::wincolor_stderr_sink(color_mode mode)
|
||||||
: wincolor_sink<ConsoleMutex>(::GetStdHandle(STD_ERROR_HANDLE), mode)
|
: wincolor_sink<ConsoleMutex>(::GetStdHandle(STD_ERROR_HANDLE), mode)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
} // namespace sinks
|
} // namespace sinks
|
||||||
} // namespace spdlog
|
} // namespace spdlog
|
||||||
|
@@ -12,9 +12,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
#include <spdlog/details/windows_include.h>
|
|
||||||
#include <wincon.h>
|
|
||||||
|
|
||||||
namespace spdlog {
|
namespace spdlog {
|
||||||
namespace sinks {
|
namespace sinks {
|
||||||
@@ -25,22 +23,15 @@ namespace sinks {
|
|||||||
template<typename ConsoleMutex>
|
template<typename ConsoleMutex>
|
||||||
class wincolor_sink : public sink
|
class wincolor_sink : public sink
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const WORD BOLD = FOREGROUND_INTENSITY;
|
wincolor_sink(void *out_handle, color_mode mode);
|
||||||
const WORD RED = FOREGROUND_RED;
|
|
||||||
const WORD GREEN = FOREGROUND_GREEN;
|
|
||||||
const WORD CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE;
|
|
||||||
const WORD WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
|
||||||
const WORD YELLOW = FOREGROUND_RED | FOREGROUND_GREEN;
|
|
||||||
|
|
||||||
wincolor_sink(HANDLE out_handle, color_mode mode);
|
|
||||||
~wincolor_sink() override;
|
~wincolor_sink() override;
|
||||||
|
|
||||||
wincolor_sink(const wincolor_sink &other) = delete;
|
wincolor_sink(const wincolor_sink &other) = delete;
|
||||||
wincolor_sink &operator=(const wincolor_sink &other) = delete;
|
wincolor_sink &operator=(const wincolor_sink &other) = delete;
|
||||||
|
|
||||||
// change the color for the given level
|
// change the color for the given level
|
||||||
void set_color(level::level_enum level, WORD color);
|
void set_color(level::level_enum level, std::uint16_t color);
|
||||||
void log(const details::log_msg &msg) final override;
|
void log(const details::log_msg &msg) final override;
|
||||||
void flush() final override;
|
void flush() final override;
|
||||||
void set_pattern(const std::string &pattern) override final;
|
void set_pattern(const std::string &pattern) override final;
|
||||||
@@ -49,21 +40,22 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
using mutex_t = typename ConsoleMutex::mutex_t;
|
using mutex_t = typename ConsoleMutex::mutex_t;
|
||||||
HANDLE out_handle_;
|
void *out_handle_;
|
||||||
mutex_t &mutex_;
|
mutex_t &mutex_;
|
||||||
bool in_console_;
|
|
||||||
bool should_do_colors_;
|
bool should_do_colors_;
|
||||||
std::unique_ptr<spdlog::formatter> formatter_;
|
std::unique_ptr<spdlog::formatter> formatter_;
|
||||||
std::array<WORD, level::n_levels> colors_;
|
std::array<std::uint16_t, level::n_levels> colors_;
|
||||||
|
|
||||||
// set foreground color and return the orig console attributes (for resetting later)
|
// set foreground color and return the orig console attributes (for resetting later)
|
||||||
WORD set_foreground_color_(WORD attribs);
|
std::uint16_t set_foreground_color_(std::uint16_t attribs);
|
||||||
|
|
||||||
// print a range of formatted message to console
|
// print a range of formatted message to console
|
||||||
void print_range_(const memory_buf_t &formatted, size_t start, size_t end);
|
void print_range_(const memory_buf_t &formatted, size_t start, size_t end);
|
||||||
|
|
||||||
// in case we are redirected to file (not in console mode)
|
// in case we are redirected to file (not in console mode)
|
||||||
void write_to_file_(const memory_buf_t &formatted);
|
void write_to_file_(const memory_buf_t &formatted);
|
||||||
|
|
||||||
|
void set_color_mode_impl(color_mode mode);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ConsoleMutex>
|
template<typename ConsoleMutex>
|
||||||
@@ -85,7 +77,6 @@ using wincolor_stdout_sink_st = wincolor_stdout_sink<details::console_nullmutex>
|
|||||||
|
|
||||||
using wincolor_stderr_sink_mt = wincolor_stderr_sink<details::console_mutex>;
|
using wincolor_stderr_sink_mt = wincolor_stderr_sink<details::console_mutex>;
|
||||||
using wincolor_stderr_sink_st = wincolor_stderr_sink<details::console_nullmutex>;
|
using wincolor_stderr_sink_st = wincolor_stderr_sink<details::console_nullmutex>;
|
||||||
|
|
||||||
} // namespace sinks
|
} // namespace sinks
|
||||||
} // namespace spdlog
|
} // namespace spdlog
|
||||||
|
|
||||||
|
@@ -58,6 +58,14 @@
|
|||||||
// #define SPDLOG_EOL ";-)\n"
|
// #define SPDLOG_EOL ";-)\n"
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Uncomment to override default folder separators ("/" or "\\/" under
|
||||||
|
// Linux/Windows). Each character in the string is treated as a different
|
||||||
|
// separator.
|
||||||
|
//
|
||||||
|
// #define SPDLOG_FOLDER_SEPS "\\"
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Uncomment to use your own copy of the fmt library instead of spdlog's copy.
|
// Uncomment to use your own copy of the fmt library instead of spdlog's copy.
|
||||||
// In this case spdlog will try to include <fmt/format.h> so set your -I flag
|
// In this case spdlog will try to include <fmt/format.h> so set your -I flag
|
||||||
|
@@ -5,6 +5,6 @@
|
|||||||
|
|
||||||
#define SPDLOG_VER_MAJOR 1
|
#define SPDLOG_VER_MAJOR 1
|
||||||
#define SPDLOG_VER_MINOR 8
|
#define SPDLOG_VER_MINOR 8
|
||||||
#define SPDLOG_VER_PATCH 2
|
#define SPDLOG_VER_PATCH 4
|
||||||
|
|
||||||
#define SPDLOG_VERSION (SPDLOG_VER_MAJOR * 10000 + SPDLOG_VER_MINOR * 100 + SPDLOG_VER_PATCH)
|
#define SPDLOG_VERSION (SPDLOG_VER_MAJOR * 10000 + SPDLOG_VER_MINOR * 100 + SPDLOG_VER_PATCH)
|
||||||
|
@@ -3,6 +3,8 @@
|
|||||||
#include "spdlog/sinks/basic_file_sink.h"
|
#include "spdlog/sinks/basic_file_sink.h"
|
||||||
#include "test_sink.h"
|
#include "test_sink.h"
|
||||||
|
|
||||||
|
#define TEST_FILENAME "test_logs/async_test.log"
|
||||||
|
|
||||||
TEST_CASE("basic async test ", "[async]")
|
TEST_CASE("basic async test ", "[async]")
|
||||||
{
|
{
|
||||||
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
|
auto test_sink = std::make_shared<spdlog::sinks::test_sink_mt>();
|
||||||
@@ -149,7 +151,7 @@ TEST_CASE("to_file", "[async]")
|
|||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
size_t messages = 1024;
|
size_t messages = 1024;
|
||||||
size_t tp_threads = 1;
|
size_t tp_threads = 1;
|
||||||
std::string filename = "test_logs/async_test.log";
|
spdlog::filename_t filename = SPDLOG_FILENAME_T(TEST_FILENAME);
|
||||||
{
|
{
|
||||||
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
|
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);
|
auto tp = std::make_shared<spdlog::details::thread_pool>(messages, tp_threads);
|
||||||
@@ -161,8 +163,8 @@ TEST_CASE("to_file", "[async]")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
require_message_count(filename, messages);
|
require_message_count(TEST_FILENAME, messages);
|
||||||
auto contents = file_contents(filename);
|
auto contents = file_contents(TEST_FILENAME);
|
||||||
using spdlog::details::os::default_eol;
|
using spdlog::details::os::default_eol;
|
||||||
REQUIRE(ends_with(contents, fmt::format("Hello message #1023{}", default_eol)));
|
REQUIRE(ends_with(contents, fmt::format("Hello message #1023{}", default_eol)));
|
||||||
}
|
}
|
||||||
@@ -172,7 +174,7 @@ TEST_CASE("to_file multi-workers", "[async]")
|
|||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
size_t messages = 1024 * 10;
|
size_t messages = 1024 * 10;
|
||||||
size_t tp_threads = 10;
|
size_t tp_threads = 10;
|
||||||
std::string filename = "test_logs/async_test.log";
|
spdlog::filename_t filename = SPDLOG_FILENAME_T(TEST_FILENAME);
|
||||||
{
|
{
|
||||||
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
|
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);
|
auto tp = std::make_shared<spdlog::details::thread_pool>(messages, tp_threads);
|
||||||
@@ -184,5 +186,5 @@ TEST_CASE("to_file multi-workers", "[async]")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
require_message_count(filename, messages);
|
require_message_count(TEST_FILENAME, messages);
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
using spdlog::details::os::create_dir;
|
using spdlog::details::os::create_dir;
|
||||||
using spdlog::details::os::path_exists;
|
using spdlog::details::os::path_exists;
|
||||||
|
|
||||||
bool try_create_dir(const char *path, const char *normalized_path)
|
bool try_create_dir(const spdlog::filename_t &path, const spdlog::filename_t &normalized_path)
|
||||||
{
|
{
|
||||||
auto rv = create_dir(path);
|
auto rv = create_dir(path);
|
||||||
REQUIRE(rv == true);
|
REQUIRE(rv == true);
|
||||||
@@ -17,24 +17,24 @@ TEST_CASE("create_dir", "[create_dir]")
|
|||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
|
|
||||||
REQUIRE(try_create_dir("test_logs/dir1/dir1", "test_logs/dir1/dir1"));
|
REQUIRE(try_create_dir(SPDLOG_FILENAME_T("test_logs/dir1/dir1"), SPDLOG_FILENAME_T("test_logs/dir1/dir1")));
|
||||||
REQUIRE(try_create_dir("test_logs/dir1/dir1", "test_logs/dir1/dir1")); // test existing
|
REQUIRE(try_create_dir(SPDLOG_FILENAME_T("test_logs/dir1/dir1"), SPDLOG_FILENAME_T("test_logs/dir1/dir1"))); // test existing
|
||||||
REQUIRE(try_create_dir("test_logs/dir1///dir2//", "test_logs/dir1/dir2"));
|
REQUIRE(try_create_dir(SPDLOG_FILENAME_T("test_logs/dir1///dir2//"), SPDLOG_FILENAME_T("test_logs/dir1/dir2")));
|
||||||
REQUIRE(try_create_dir("./test_logs/dir1/dir3", "test_logs/dir1/dir3"));
|
REQUIRE(try_create_dir(SPDLOG_FILENAME_T("./test_logs/dir1/dir3"), SPDLOG_FILENAME_T("test_logs/dir1/dir3")));
|
||||||
REQUIRE(try_create_dir("test_logs/../test_logs/dir1/dir4", "test_logs/dir1/dir4"));
|
REQUIRE(try_create_dir(SPDLOG_FILENAME_T("test_logs/../test_logs/dir1/dir4"), SPDLOG_FILENAME_T("test_logs/dir1/dir4")));
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
// test backslash folder separator
|
// test backslash folder separator
|
||||||
REQUIRE(try_create_dir("test_logs\\dir1\\dir222", "test_logs\\dir1\\dir222"));
|
REQUIRE(try_create_dir(SPDLOG_FILENAME_T("test_logs\\dir1\\dir222"), SPDLOG_FILENAME_T("test_logs\\dir1\\dir222")));
|
||||||
REQUIRE(try_create_dir("test_logs\\dir1\\dir223\\", "test_logs\\dir1\\dir223\\"));
|
REQUIRE(try_create_dir(SPDLOG_FILENAME_T("test_logs\\dir1\\dir223\\"), SPDLOG_FILENAME_T("test_logs\\dir1\\dir223\\")));
|
||||||
REQUIRE(try_create_dir(".\\test_logs\\dir1\\dir2\\dir99\\..\\dir23", "test_logs\\dir1\\dir2\\dir23"));
|
REQUIRE(try_create_dir(SPDLOG_FILENAME_T(".\\test_logs\\dir1\\dir2\\dir99\\..\\dir23"), SPDLOG_FILENAME_T("test_logs\\dir1\\dir2\\dir23")));
|
||||||
REQUIRE(try_create_dir("test_logs\\..\\test_logs\\dir1\\dir5", "test_logs\\dir1\\dir5"));
|
REQUIRE(try_create_dir(SPDLOG_FILENAME_T("test_logs\\..\\test_logs\\dir1\\dir5"), SPDLOG_FILENAME_T("test_logs\\dir1\\dir5")));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("create_invalid_dir", "[create_dir]")
|
TEST_CASE("create_invalid_dir", "[create_dir]")
|
||||||
{
|
{
|
||||||
REQUIRE(create_dir("") == false);
|
REQUIRE(create_dir(SPDLOG_FILENAME_T("")) == false);
|
||||||
REQUIRE(create_dir(spdlog::filename_t{}) == false);
|
REQUIRE(create_dir(spdlog::filename_t{}) == false);
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
REQUIRE(create_dir("/proc/spdlog-utest") == false);
|
REQUIRE(create_dir("/proc/spdlog-utest") == false);
|
||||||
@@ -44,37 +44,31 @@ TEST_CASE("create_invalid_dir", "[create_dir]")
|
|||||||
TEST_CASE("dir_name", "[create_dir]")
|
TEST_CASE("dir_name", "[create_dir]")
|
||||||
{
|
{
|
||||||
using spdlog::details::os::dir_name;
|
using spdlog::details::os::dir_name;
|
||||||
REQUIRE(dir_name("").empty());
|
REQUIRE(dir_name(SPDLOG_FILENAME_T("")).empty());
|
||||||
REQUIRE(dir_name("dir").empty());
|
REQUIRE(dir_name(SPDLOG_FILENAME_T("dir")).empty());
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
REQUIRE(dir_name(R"(dir\)") == "dir");
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\)")) == SPDLOG_FILENAME_T("dir"));
|
||||||
REQUIRE(dir_name(R"(dir\\\)") == R"(dir\\)");
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\\\)")) == SPDLOG_FILENAME_T(R"(dir\\)"));
|
||||||
REQUIRE(dir_name(R"(dir\file)") == "dir");
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\file)")) == SPDLOG_FILENAME_T("dir"));
|
||||||
REQUIRE(dir_name(R"(dir/file)") == "dir");
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir/file)")) == SPDLOG_FILENAME_T("dir"));
|
||||||
REQUIRE(dir_name(R"(dir\file.txt)") == "dir");
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\file.txt)")) == SPDLOG_FILENAME_T("dir"));
|
||||||
REQUIRE(dir_name(R"(dir/file)") == "dir");
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir/file)")) == SPDLOG_FILENAME_T("dir"));
|
||||||
REQUIRE(dir_name(R"(dir\file.txt\)") == R"(dir\file.txt)");
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\file.txt\)")) == SPDLOG_FILENAME_T(R"(dir\file.txt)"));
|
||||||
REQUIRE(dir_name(R"(dir/file.txt/)") == R"(dir\file.txt)");
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(\dir\file.txt)")) == SPDLOG_FILENAME_T(R"(\dir)"));
|
||||||
REQUIRE(dir_name(R"(\dir\file.txt)") == R"(\dir)");
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(\\dir\file.txt)")) == SPDLOG_FILENAME_T(R"(\\dir)"));
|
||||||
REQUIRE(dir_name(R"(/dir/file.txt)") == R"(\dir)");
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(..\file.txt)")) == SPDLOG_FILENAME_T(".."));
|
||||||
REQUIRE(dir_name(R"(\\dir\file.txt)") == R"(\\dir)");
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(.\file.txt)")) == SPDLOG_FILENAME_T("."));
|
||||||
REQUIRE(dir_name(R"(//dir/file.txt)") == R"(\\dir)");
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(c:\\a\b\c\d\file.txt)")) == SPDLOG_FILENAME_T(R"(c:\\a\b\c\d)"));
|
||||||
REQUIRE(dir_name(R"(..\file.txt)") == "..");
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(c://a/b/c/d/file.txt)")) == SPDLOG_FILENAME_T(R"(c://a/b/c/d)"));
|
||||||
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
|
#endif
|
||||||
|
REQUIRE(dir_name(SPDLOG_FILENAME_T("dir/")) == SPDLOG_FILENAME_T("dir"));
|
||||||
|
REQUIRE(dir_name(SPDLOG_FILENAME_T("dir///")) == SPDLOG_FILENAME_T("dir//"));
|
||||||
|
REQUIRE(dir_name(SPDLOG_FILENAME_T("dir/file")) == SPDLOG_FILENAME_T("dir"));
|
||||||
|
REQUIRE(dir_name(SPDLOG_FILENAME_T("dir/file.txt")) == SPDLOG_FILENAME_T("dir"));
|
||||||
|
REQUIRE(dir_name(SPDLOG_FILENAME_T("dir/file.txt/")) == SPDLOG_FILENAME_T("dir/file.txt"));
|
||||||
|
REQUIRE(dir_name(SPDLOG_FILENAME_T("/dir/file.txt")) == SPDLOG_FILENAME_T("/dir"));
|
||||||
|
REQUIRE(dir_name(SPDLOG_FILENAME_T("//dir/file.txt")) == SPDLOG_FILENAME_T("//dir"));
|
||||||
|
REQUIRE(dir_name(SPDLOG_FILENAME_T("../file.txt")) == SPDLOG_FILENAME_T(".."));
|
||||||
|
REQUIRE(dir_name(SPDLOG_FILENAME_T("./file.txt")) == SPDLOG_FILENAME_T("."));
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,8 @@
|
|||||||
*/
|
*/
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
|
using filename_memory_buf_t = fmt::basic_memory_buffer<spdlog::filename_t::value_type, 250>;
|
||||||
|
|
||||||
TEST_CASE("daily_logger with dateonly calculator", "[daily_logger]")
|
TEST_CASE("daily_logger with dateonly calculator", "[daily_logger]")
|
||||||
{
|
{
|
||||||
using sink_type = spdlog::sinks::daily_file_sink<std::mutex, spdlog::sinks::daily_filename_calculator>;
|
using sink_type = spdlog::sinks::daily_file_sink<std::mutex, spdlog::sinks::daily_filename_calculator>;
|
||||||
@@ -10,10 +12,10 @@ TEST_CASE("daily_logger with dateonly calculator", "[daily_logger]")
|
|||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
|
|
||||||
// calculate filename (time based)
|
// calculate filename (time based)
|
||||||
std::string basename = "test_logs/daily_dateonly";
|
spdlog::filename_t basename = SPDLOG_FILENAME_T("test_logs/daily_dateonly");
|
||||||
std::tm tm = spdlog::details::os::localtime();
|
std::tm tm = spdlog::details::os::localtime();
|
||||||
spdlog::memory_buf_t w;
|
filename_memory_buf_t w;
|
||||||
fmt::format_to(w, "{}_{:04d}-{:02d}-{:02d}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
|
fmt::format_to(w, SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
|
||||||
|
|
||||||
auto logger = spdlog::create<sink_type>("logger", basename, 0, 0);
|
auto logger = spdlog::create<sink_type>("logger", basename, 0, 0);
|
||||||
for (int i = 0; i < 10; ++i)
|
for (int i = 0; i < 10; ++i)
|
||||||
@@ -23,7 +25,13 @@ TEST_CASE("daily_logger with dateonly calculator", "[daily_logger]")
|
|||||||
}
|
}
|
||||||
logger->flush();
|
logger->flush();
|
||||||
|
|
||||||
|
#ifdef SPDLOG_WCHAR_FILENAMES
|
||||||
|
spdlog::memory_buf_t buf;
|
||||||
|
spdlog::details::os::wstr_to_utf8buf(fmt::to_string(w), buf);
|
||||||
|
auto filename = fmt::to_string(buf);
|
||||||
|
#else
|
||||||
auto filename = fmt::to_string(w);
|
auto filename = fmt::to_string(w);
|
||||||
|
#endif
|
||||||
require_message_count(filename, 10);
|
require_message_count(filename, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,8 +39,8 @@ struct custom_daily_file_name_calculator
|
|||||||
{
|
{
|
||||||
static spdlog::filename_t calc_filename(const spdlog::filename_t &basename, const tm &now_tm)
|
static spdlog::filename_t calc_filename(const spdlog::filename_t &basename, const tm &now_tm)
|
||||||
{
|
{
|
||||||
spdlog::memory_buf_t w;
|
filename_memory_buf_t w;
|
||||||
fmt::format_to(w, "{}{:04d}{:02d}{:02d}", basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday);
|
fmt::format_to(w, SPDLOG_FILENAME_T("{}{:04d}{:02d}{:02d}"), basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday);
|
||||||
return fmt::to_string(w);
|
return fmt::to_string(w);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -44,10 +52,10 @@ TEST_CASE("daily_logger with custom calculator", "[daily_logger]")
|
|||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
|
|
||||||
// calculate filename (time based)
|
// calculate filename (time based)
|
||||||
std::string basename = "test_logs/daily_dateonly";
|
spdlog::filename_t basename = SPDLOG_FILENAME_T("test_logs/daily_dateonly");
|
||||||
std::tm tm = spdlog::details::os::localtime();
|
std::tm tm = spdlog::details::os::localtime();
|
||||||
spdlog::memory_buf_t w;
|
filename_memory_buf_t w;
|
||||||
fmt::format_to(w, "{}{:04d}{:02d}{:02d}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
|
fmt::format_to(w, SPDLOG_FILENAME_T("{}{:04d}{:02d}{:02d}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
|
||||||
|
|
||||||
auto logger = spdlog::create<sink_type>("logger", basename, 0, 0);
|
auto logger = spdlog::create<sink_type>("logger", basename, 0, 0);
|
||||||
for (int i = 0; i < 10; ++i)
|
for (int i = 0; i < 10; ++i)
|
||||||
@@ -57,7 +65,13 @@ TEST_CASE("daily_logger with custom calculator", "[daily_logger]")
|
|||||||
|
|
||||||
logger->flush();
|
logger->flush();
|
||||||
|
|
||||||
|
#ifdef SPDLOG_WCHAR_FILENAMES
|
||||||
|
spdlog::memory_buf_t buf;
|
||||||
|
spdlog::details::os::wstr_to_utf8buf(fmt::to_string(w), buf);
|
||||||
|
auto filename = fmt::to_string(buf);
|
||||||
|
#else
|
||||||
auto filename = fmt::to_string(w);
|
auto filename = fmt::to_string(w);
|
||||||
|
#endif
|
||||||
require_message_count(filename, 10);
|
require_message_count(filename, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,20 +81,20 @@ TEST_CASE("daily_logger with custom calculator", "[daily_logger]")
|
|||||||
|
|
||||||
TEST_CASE("rotating_file_sink::calc_filename1", "[rotating_file_sink]]")
|
TEST_CASE("rotating_file_sink::calc_filename1", "[rotating_file_sink]]")
|
||||||
{
|
{
|
||||||
auto filename = spdlog::sinks::rotating_file_sink_st::calc_filename("rotated.txt", 3);
|
auto filename = spdlog::sinks::rotating_file_sink_st::calc_filename(SPDLOG_FILENAME_T("rotated.txt"), 3);
|
||||||
REQUIRE(filename == "rotated.3.txt");
|
REQUIRE(filename == SPDLOG_FILENAME_T("rotated.3.txt"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("rotating_file_sink::calc_filename2", "[rotating_file_sink]]")
|
TEST_CASE("rotating_file_sink::calc_filename2", "[rotating_file_sink]]")
|
||||||
{
|
{
|
||||||
auto filename = spdlog::sinks::rotating_file_sink_st::calc_filename("rotated", 3);
|
auto filename = spdlog::sinks::rotating_file_sink_st::calc_filename(SPDLOG_FILENAME_T("rotated"), 3);
|
||||||
REQUIRE(filename == "rotated.3");
|
REQUIRE(filename == SPDLOG_FILENAME_T("rotated.3"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("rotating_file_sink::calc_filename3", "[rotating_file_sink]]")
|
TEST_CASE("rotating_file_sink::calc_filename3", "[rotating_file_sink]]")
|
||||||
{
|
{
|
||||||
auto filename = spdlog::sinks::rotating_file_sink_st::calc_filename("rotated.txt", 0);
|
auto filename = spdlog::sinks::rotating_file_sink_st::calc_filename(SPDLOG_FILENAME_T("rotated.txt"), 0);
|
||||||
REQUIRE(filename == "rotated.txt");
|
REQUIRE(filename == SPDLOG_FILENAME_T("rotated.txt"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// regex supported only from gcc 4.9 and above
|
// regex supported only from gcc 4.9 and above
|
||||||
@@ -91,10 +105,10 @@ TEST_CASE("rotating_file_sink::calc_filename3", "[rotating_file_sink]]")
|
|||||||
TEST_CASE("daily_file_sink::daily_filename_calculator", "[daily_file_sink]]")
|
TEST_CASE("daily_file_sink::daily_filename_calculator", "[daily_file_sink]]")
|
||||||
{
|
{
|
||||||
// daily_YYYY-MM-DD_hh-mm.txt
|
// daily_YYYY-MM-DD_hh-mm.txt
|
||||||
auto filename = spdlog::sinks::daily_filename_calculator::calc_filename("daily.txt", spdlog::details::os::localtime());
|
auto filename = spdlog::sinks::daily_filename_calculator::calc_filename(SPDLOG_FILENAME_T("daily.txt"), spdlog::details::os::localtime());
|
||||||
// date regex based on https://www.regular-expressions.info/dates.html
|
// date regex based on https://www.regular-expressions.info/dates.html
|
||||||
std::regex re(R"(^daily_(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])\.txt$)");
|
std::basic_regex<spdlog::filename_t::value_type> re(SPDLOG_FILENAME_T(R"(^daily_(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])\.txt$)"));
|
||||||
std::smatch match;
|
std::match_results<spdlog::filename_t::const_iterator> match;
|
||||||
REQUIRE(std::regex_match(filename, match, re));
|
REQUIRE(std::regex_match(filename, match, re));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -116,7 +130,7 @@ static void test_rotate(int days_to_run, uint16_t max_days, uint16_t expected_n_
|
|||||||
|
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
|
|
||||||
std::string basename = "test_logs/daily_rotate.txt";
|
spdlog::filename_t basename = SPDLOG_FILENAME_T("test_logs/daily_rotate.txt");
|
||||||
daily_file_sink_st sink{basename, 2, 30, true, max_days};
|
daily_file_sink_st sink{basename, 2, 30, true, max_days};
|
||||||
|
|
||||||
// simulate messages with 24 intervals
|
// simulate messages with 24 intervals
|
||||||
|
@@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#define SIMPLE_LOG "test_logs/simple_log.txt"
|
||||||
|
#define SIMPLE_ASYNC_LOG "test_logs/simple_async_log.txt"
|
||||||
|
|
||||||
class failing_sink : public spdlog::sinks::base_sink<std::mutex>
|
class failing_sink : public spdlog::sinks::base_sink<std::mutex>
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@@ -22,7 +25,7 @@ protected:
|
|||||||
TEST_CASE("default_error_handler", "[errors]]")
|
TEST_CASE("default_error_handler", "[errors]]")
|
||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
std::string filename = "test_logs/simple_log.txt";
|
spdlog::filename_t filename = SPDLOG_FILENAME_T(SIMPLE_LOG);
|
||||||
|
|
||||||
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("test-error", filename, true);
|
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("test-error", filename, true);
|
||||||
logger->set_pattern("%v");
|
logger->set_pattern("%v");
|
||||||
@@ -31,8 +34,8 @@ TEST_CASE("default_error_handler", "[errors]]")
|
|||||||
logger->flush();
|
logger->flush();
|
||||||
|
|
||||||
using spdlog::details::os::default_eol;
|
using spdlog::details::os::default_eol;
|
||||||
REQUIRE(file_contents(filename) == fmt::format("Test message 2{}", default_eol));
|
REQUIRE(file_contents(SIMPLE_LOG) == fmt::format("Test message 2{}", default_eol));
|
||||||
REQUIRE(count_lines(filename) == 1);
|
REQUIRE(count_lines(SIMPLE_LOG) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct custom_ex
|
struct custom_ex
|
||||||
@@ -40,7 +43,7 @@ struct custom_ex
|
|||||||
TEST_CASE("custom_error_handler", "[errors]]")
|
TEST_CASE("custom_error_handler", "[errors]]")
|
||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
std::string filename = "test_logs/simple_log.txt";
|
spdlog::filename_t filename = SPDLOG_FILENAME_T(SIMPLE_LOG);
|
||||||
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename, true);
|
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename, true);
|
||||||
logger->flush_on(spdlog::level::info);
|
logger->flush_on(spdlog::level::info);
|
||||||
logger->set_error_handler([=](const std::string &) { throw custom_ex(); });
|
logger->set_error_handler([=](const std::string &) { throw custom_ex(); });
|
||||||
@@ -48,7 +51,7 @@ TEST_CASE("custom_error_handler", "[errors]]")
|
|||||||
|
|
||||||
REQUIRE_THROWS_AS(logger->info("Bad format msg {} {}", "xxx"), custom_ex);
|
REQUIRE_THROWS_AS(logger->info("Bad format msg {} {}", "xxx"), custom_ex);
|
||||||
logger->info("Good message #2");
|
logger->info("Good message #2");
|
||||||
require_message_count(filename, 2);
|
require_message_count(SIMPLE_LOG, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("default_error_handler2", "[errors]]")
|
TEST_CASE("default_error_handler2", "[errors]]")
|
||||||
@@ -72,7 +75,7 @@ TEST_CASE("async_error_handler", "[errors]]")
|
|||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
std::string err_msg("log failed with some msg");
|
std::string err_msg("log failed with some msg");
|
||||||
|
|
||||||
std::string filename = "test_logs/simple_async_log.txt";
|
spdlog::filename_t filename = SPDLOG_FILENAME_T(SIMPLE_ASYNC_LOG);
|
||||||
{
|
{
|
||||||
spdlog::init_thread_pool(128, 1);
|
spdlog::init_thread_pool(128, 1);
|
||||||
auto logger = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("logger", filename, true);
|
auto logger = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("logger", filename, true);
|
||||||
@@ -90,7 +93,7 @@ TEST_CASE("async_error_handler", "[errors]]")
|
|||||||
spdlog::drop("logger"); // force logger to drain the queue and shutdown
|
spdlog::drop("logger"); // force logger to drain the queue and shutdown
|
||||||
}
|
}
|
||||||
spdlog::init_thread_pool(128, 1);
|
spdlog::init_thread_pool(128, 1);
|
||||||
require_message_count(filename, 2);
|
require_message_count(SIMPLE_ASYNC_LOG, 2);
|
||||||
REQUIRE(file_contents("test_logs/custom_err.txt") == err_msg);
|
REQUIRE(file_contents("test_logs/custom_err.txt") == err_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +103,7 @@ TEST_CASE("async_error_handler2", "[errors]]")
|
|||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
std::string err_msg("This is async handler error message");
|
std::string err_msg("This is async handler error message");
|
||||||
{
|
{
|
||||||
spdlog::details::os::create_dir("test_logs");
|
spdlog::details::os::create_dir(SPDLOG_FILENAME_T("test_logs"));
|
||||||
spdlog::init_thread_pool(128, 1);
|
spdlog::init_thread_pool(128, 1);
|
||||||
auto logger = spdlog::create_async<failing_sink>("failed_logger");
|
auto logger = spdlog::create_async<failing_sink>("failed_logger");
|
||||||
logger->set_error_handler([=](const std::string &) {
|
logger->set_error_handler([=](const std::string &) {
|
||||||
|
@@ -24,20 +24,20 @@ static void test_single_print(std::function<void(std::string const &)> do_log, s
|
|||||||
REQUIRE(CloseEventLog(handle_));
|
REQUIRE(CloseEventLog(handle_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} event_log{::OpenEventLog(nullptr, TEST_SOURCE)};
|
} event_log{::OpenEventLogA(nullptr, TEST_SOURCE)};
|
||||||
|
|
||||||
REQUIRE(event_log.handle_);
|
REQUIRE(event_log.handle_);
|
||||||
|
|
||||||
DWORD read_bytes{}, size_needed{};
|
DWORD read_bytes{}, size_needed{};
|
||||||
auto ok =
|
auto ok =
|
||||||
::ReadEventLog(event_log.handle_, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ, 0, &read_bytes, 0, &read_bytes, &size_needed);
|
::ReadEventLogA(event_log.handle_, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ, 0, &read_bytes, 0, &read_bytes, &size_needed);
|
||||||
REQUIRE(!ok);
|
REQUIRE(!ok);
|
||||||
REQUIRE(::GetLastError() == ERROR_INSUFFICIENT_BUFFER);
|
REQUIRE(::GetLastError() == ERROR_INSUFFICIENT_BUFFER);
|
||||||
|
|
||||||
std::vector<char> record_buffer(size_needed);
|
std::vector<char> record_buffer(size_needed);
|
||||||
PEVENTLOGRECORD record = (PEVENTLOGRECORD)record_buffer.data();
|
PEVENTLOGRECORD record = (PEVENTLOGRECORD)record_buffer.data();
|
||||||
|
|
||||||
ok = ::ReadEventLog(
|
ok = ::ReadEventLogA(
|
||||||
event_log.handle_, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ, 0, record, size_needed, &read_bytes, &size_needed);
|
event_log.handle_, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ, 0, record, size_needed, &read_bytes, &size_needed);
|
||||||
REQUIRE(ok);
|
REQUIRE(ok);
|
||||||
|
|
||||||
|
@@ -3,6 +3,8 @@
|
|||||||
*/
|
*/
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
|
#define TEST_FILENAME "test_logs/file_helper_test.txt"
|
||||||
|
|
||||||
using spdlog::details::file_helper;
|
using spdlog::details::file_helper;
|
||||||
|
|
||||||
static void write_with_helper(file_helper &helper, size_t howmany)
|
static void write_with_helper(file_helper &helper, size_t howmany)
|
||||||
@@ -18,7 +20,7 @@ TEST_CASE("file_helper_filename", "[file_helper::filename()]]")
|
|||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
|
|
||||||
file_helper helper;
|
file_helper helper;
|
||||||
std::string target_filename = "test_logs/file_helper_test.txt";
|
spdlog::filename_t target_filename = SPDLOG_FILENAME_T(TEST_FILENAME);
|
||||||
helper.open(target_filename);
|
helper.open(target_filename);
|
||||||
REQUIRE(helper.filename() == target_filename);
|
REQUIRE(helper.filename() == target_filename);
|
||||||
}
|
}
|
||||||
@@ -26,7 +28,7 @@ TEST_CASE("file_helper_filename", "[file_helper::filename()]]")
|
|||||||
TEST_CASE("file_helper_size", "[file_helper::size()]]")
|
TEST_CASE("file_helper_size", "[file_helper::size()]]")
|
||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
std::string target_filename = "test_logs/file_helper_test.txt";
|
spdlog::filename_t target_filename = SPDLOG_FILENAME_T(TEST_FILENAME);
|
||||||
size_t expected_size = 123;
|
size_t expected_size = 123;
|
||||||
{
|
{
|
||||||
file_helper helper;
|
file_helper helper;
|
||||||
@@ -34,13 +36,13 @@ TEST_CASE("file_helper_size", "[file_helper::size()]]")
|
|||||||
write_with_helper(helper, expected_size);
|
write_with_helper(helper, expected_size);
|
||||||
REQUIRE(static_cast<size_t>(helper.size()) == expected_size);
|
REQUIRE(static_cast<size_t>(helper.size()) == expected_size);
|
||||||
}
|
}
|
||||||
REQUIRE(get_filesize(target_filename) == expected_size);
|
REQUIRE(get_filesize(TEST_FILENAME) == expected_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("file_helper_reopen", "[file_helper::reopen()]]")
|
TEST_CASE("file_helper_reopen", "[file_helper::reopen()]]")
|
||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
std::string target_filename = "test_logs/file_helper_test.txt";
|
spdlog::filename_t target_filename = SPDLOG_FILENAME_T(TEST_FILENAME);
|
||||||
file_helper helper;
|
file_helper helper;
|
||||||
helper.open(target_filename);
|
helper.open(target_filename);
|
||||||
write_with_helper(helper, 12);
|
write_with_helper(helper, 12);
|
||||||
@@ -52,7 +54,7 @@ TEST_CASE("file_helper_reopen", "[file_helper::reopen()]]")
|
|||||||
TEST_CASE("file_helper_reopen2", "[file_helper::reopen(false)]]")
|
TEST_CASE("file_helper_reopen2", "[file_helper::reopen(false)]]")
|
||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
std::string target_filename = "test_logs/file_helper_test.txt";
|
spdlog::filename_t target_filename = SPDLOG_FILENAME_T(TEST_FILENAME);
|
||||||
size_t expected_size = 14;
|
size_t expected_size = 14;
|
||||||
file_helper helper;
|
file_helper helper;
|
||||||
helper.open(target_filename);
|
helper.open(target_filename);
|
||||||
@@ -62,16 +64,12 @@ TEST_CASE("file_helper_reopen2", "[file_helper::reopen(false)]]")
|
|||||||
REQUIRE(helper.size() == expected_size);
|
REQUIRE(helper.size() == expected_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_split_ext(const char *fname, const char *expect_base, const char *expect_ext)
|
static void test_split_ext(const spdlog::filename_t::value_type *fname, const spdlog::filename_t::value_type *expect_base, const spdlog::filename_t::value_type *expect_ext)
|
||||||
{
|
{
|
||||||
spdlog::filename_t filename(fname);
|
spdlog::filename_t filename(fname);
|
||||||
spdlog::filename_t expected_base(expect_base);
|
spdlog::filename_t expected_base(expect_base);
|
||||||
spdlog::filename_t expected_ext(expect_ext);
|
spdlog::filename_t expected_ext(expect_ext);
|
||||||
|
|
||||||
#ifdef _WIN32 // replace folder sep
|
|
||||||
std::replace(filename.begin(), filename.end(), '/', '\\');
|
|
||||||
std::replace(expected_base.begin(), expected_base.end(), '/', '\\');
|
|
||||||
#endif
|
|
||||||
spdlog::filename_t basename;
|
spdlog::filename_t basename;
|
||||||
spdlog::filename_t ext;
|
spdlog::filename_t ext;
|
||||||
std::tie(basename, ext) = file_helper::split_by_extension(filename);
|
std::tie(basename, ext) = file_helper::split_by_extension(filename);
|
||||||
@@ -81,22 +79,22 @@ static void test_split_ext(const char *fname, const char *expect_base, const cha
|
|||||||
|
|
||||||
TEST_CASE("file_helper_split_by_extension", "[file_helper::split_by_extension()]]")
|
TEST_CASE("file_helper_split_by_extension", "[file_helper::split_by_extension()]]")
|
||||||
{
|
{
|
||||||
test_split_ext("mylog.txt", "mylog", ".txt");
|
test_split_ext(SPDLOG_FILENAME_T("mylog.txt"), SPDLOG_FILENAME_T("mylog"), SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext(".mylog.txt", ".mylog", ".txt");
|
test_split_ext(SPDLOG_FILENAME_T(".mylog.txt"), SPDLOG_FILENAME_T(".mylog"), SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext(".mylog", ".mylog", "");
|
test_split_ext(SPDLOG_FILENAME_T(".mylog"), SPDLOG_FILENAME_T(".mylog"), SPDLOG_FILENAME_T(""));
|
||||||
test_split_ext("/aaa/bb.d/mylog", "/aaa/bb.d/mylog", "");
|
test_split_ext(SPDLOG_FILENAME_T("/aaa/bb.d/mylog"), SPDLOG_FILENAME_T("/aaa/bb.d/mylog"), SPDLOG_FILENAME_T(""));
|
||||||
test_split_ext("/aaa/bb.d/mylog.txt", "/aaa/bb.d/mylog", ".txt");
|
test_split_ext(SPDLOG_FILENAME_T("/aaa/bb.d/mylog.txt"), SPDLOG_FILENAME_T("/aaa/bb.d/mylog"), SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext("aaa/bbb/ccc/mylog.txt", "aaa/bbb/ccc/mylog", ".txt");
|
test_split_ext(SPDLOG_FILENAME_T("aaa/bbb/ccc/mylog.txt"), SPDLOG_FILENAME_T("aaa/bbb/ccc/mylog"), SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext("aaa/bbb/ccc/mylog.", "aaa/bbb/ccc/mylog.", "");
|
test_split_ext(SPDLOG_FILENAME_T("aaa/bbb/ccc/mylog."), SPDLOG_FILENAME_T("aaa/bbb/ccc/mylog."), SPDLOG_FILENAME_T(""));
|
||||||
test_split_ext("aaa/bbb/ccc/.mylog.txt", "aaa/bbb/ccc/.mylog", ".txt");
|
test_split_ext(SPDLOG_FILENAME_T("aaa/bbb/ccc/.mylog.txt"), SPDLOG_FILENAME_T("aaa/bbb/ccc/.mylog"), SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext("/aaa/bbb/ccc/mylog.txt", "/aaa/bbb/ccc/mylog", ".txt");
|
test_split_ext(SPDLOG_FILENAME_T("/aaa/bbb/ccc/mylog.txt"), SPDLOG_FILENAME_T("/aaa/bbb/ccc/mylog"), SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext("/aaa/bbb/ccc/.mylog", "/aaa/bbb/ccc/.mylog", "");
|
test_split_ext(SPDLOG_FILENAME_T("/aaa/bbb/ccc/.mylog"), SPDLOG_FILENAME_T("/aaa/bbb/ccc/.mylog"), SPDLOG_FILENAME_T(""));
|
||||||
test_split_ext("../mylog.txt", "../mylog", ".txt");
|
test_split_ext(SPDLOG_FILENAME_T("../mylog.txt"), SPDLOG_FILENAME_T("../mylog"), SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext(".././mylog.txt", ".././mylog", ".txt");
|
test_split_ext(SPDLOG_FILENAME_T(".././mylog.txt"), SPDLOG_FILENAME_T(".././mylog"), SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext(".././mylog.txt/xxx", ".././mylog.txt/xxx", "");
|
test_split_ext(SPDLOG_FILENAME_T(".././mylog.txt/xxx"), SPDLOG_FILENAME_T(".././mylog.txt/xxx"), SPDLOG_FILENAME_T(""));
|
||||||
test_split_ext("/mylog.txt", "/mylog", ".txt");
|
test_split_ext(SPDLOG_FILENAME_T("/mylog.txt"), SPDLOG_FILENAME_T("/mylog"), SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext("//mylog.txt", "//mylog", ".txt");
|
test_split_ext(SPDLOG_FILENAME_T("//mylog.txt"), SPDLOG_FILENAME_T("//mylog"), SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext("", "", "");
|
test_split_ext(SPDLOG_FILENAME_T(""), SPDLOG_FILENAME_T(""), SPDLOG_FILENAME_T(""));
|
||||||
test_split_ext(".", ".", "");
|
test_split_ext(SPDLOG_FILENAME_T("."), SPDLOG_FILENAME_T("."), SPDLOG_FILENAME_T(""));
|
||||||
test_split_ext("..txt", ".", ".txt");
|
test_split_ext(SPDLOG_FILENAME_T("..txt"), SPDLOG_FILENAME_T("."), SPDLOG_FILENAME_T(".txt"));
|
||||||
}
|
}
|
||||||
|
@@ -3,10 +3,13 @@
|
|||||||
*/
|
*/
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
|
#define SIMPLE_LOG "test_logs/simple_log"
|
||||||
|
#define ROTATING_LOG "test_logs/rotating_log"
|
||||||
|
|
||||||
TEST_CASE("simple_file_logger", "[simple_logger]]")
|
TEST_CASE("simple_file_logger", "[simple_logger]]")
|
||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
std::string filename = "test_logs/simple_log";
|
spdlog::filename_t filename = SPDLOG_FILENAME_T(SIMPLE_LOG);
|
||||||
|
|
||||||
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
|
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
|
||||||
logger->set_pattern("%v");
|
logger->set_pattern("%v");
|
||||||
@@ -15,29 +18,29 @@ TEST_CASE("simple_file_logger", "[simple_logger]]")
|
|||||||
logger->info("Test message {}", 2);
|
logger->info("Test message {}", 2);
|
||||||
|
|
||||||
logger->flush();
|
logger->flush();
|
||||||
require_message_count(filename, 2);
|
require_message_count(SIMPLE_LOG, 2);
|
||||||
using spdlog::details::os::default_eol;
|
using spdlog::details::os::default_eol;
|
||||||
REQUIRE(file_contents(filename) == fmt::format("Test message 1{}Test message 2{}", default_eol, default_eol));
|
REQUIRE(file_contents(SIMPLE_LOG) == fmt::format("Test message 1{}Test message 2{}", default_eol, default_eol));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("flush_on", "[flush_on]]")
|
TEST_CASE("flush_on", "[flush_on]]")
|
||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
std::string filename = "test_logs/simple_log";
|
spdlog::filename_t filename = SPDLOG_FILENAME_T(SIMPLE_LOG);
|
||||||
|
|
||||||
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
|
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
|
||||||
logger->set_pattern("%v");
|
logger->set_pattern("%v");
|
||||||
logger->set_level(spdlog::level::trace);
|
logger->set_level(spdlog::level::trace);
|
||||||
logger->flush_on(spdlog::level::info);
|
logger->flush_on(spdlog::level::info);
|
||||||
logger->trace("Should not be flushed");
|
logger->trace("Should not be flushed");
|
||||||
REQUIRE(count_lines(filename) == 0);
|
REQUIRE(count_lines(SIMPLE_LOG) == 0);
|
||||||
|
|
||||||
logger->info("Test message {}", 1);
|
logger->info("Test message {}", 1);
|
||||||
logger->info("Test message {}", 2);
|
logger->info("Test message {}", 2);
|
||||||
|
|
||||||
require_message_count(filename, 3);
|
require_message_count(SIMPLE_LOG, 3);
|
||||||
using spdlog::details::os::default_eol;
|
using spdlog::details::os::default_eol;
|
||||||
REQUIRE(file_contents(filename) ==
|
REQUIRE(file_contents(SIMPLE_LOG) ==
|
||||||
fmt::format("Should not be flushed{}Test message 1{}Test message 2{}", default_eol, default_eol, default_eol));
|
fmt::format("Should not be flushed{}Test message 1{}Test message 2{}", default_eol, default_eol, default_eol));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +48,7 @@ TEST_CASE("rotating_file_logger1", "[rotating_logger]]")
|
|||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
size_t max_size = 1024 * 10;
|
size_t max_size = 1024 * 10;
|
||||||
std::string basename = "test_logs/rotating_log";
|
spdlog::filename_t basename = SPDLOG_FILENAME_T(ROTATING_LOG);
|
||||||
auto logger = spdlog::rotating_logger_mt("logger", basename, max_size, 0);
|
auto logger = spdlog::rotating_logger_mt("logger", basename, max_size, 0);
|
||||||
|
|
||||||
for (int i = 0; i < 10; ++i)
|
for (int i = 0; i < 10; ++i)
|
||||||
@@ -54,14 +57,14 @@ TEST_CASE("rotating_file_logger1", "[rotating_logger]]")
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger->flush();
|
logger->flush();
|
||||||
require_message_count(basename, 10);
|
require_message_count(ROTATING_LOG, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
|
TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
|
||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
size_t max_size = 1024 * 10;
|
size_t max_size = 1024 * 10;
|
||||||
std::string basename = "test_logs/rotating_log";
|
spdlog::filename_t basename = SPDLOG_FILENAME_T(ROTATING_LOG);
|
||||||
|
|
||||||
{
|
{
|
||||||
// make an initial logger to create the first output file
|
// make an initial logger to create the first output file
|
||||||
@@ -83,7 +86,7 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
|
|||||||
|
|
||||||
logger->flush();
|
logger->flush();
|
||||||
|
|
||||||
require_message_count(basename, 10);
|
require_message_count(ROTATING_LOG, 10);
|
||||||
|
|
||||||
for (int i = 0; i < 1000; i++)
|
for (int i = 0; i < 1000; i++)
|
||||||
{
|
{
|
||||||
@@ -92,7 +95,6 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger->flush();
|
logger->flush();
|
||||||
REQUIRE(get_filesize(basename) <= max_size);
|
REQUIRE(get_filesize(ROTATING_LOG) <= max_size);
|
||||||
auto filename1 = basename + ".1";
|
REQUIRE(get_filesize(ROTATING_LOG ".1") <= max_size);
|
||||||
REQUIRE(get_filesize(filename1) <= max_size);
|
|
||||||
}
|
}
|
||||||
|
@@ -8,11 +8,13 @@
|
|||||||
#error "Invalid SPDLOG_ACTIVE_LEVEL in test. Should be SPDLOG_LEVEL_DEBUG"
|
#error "Invalid SPDLOG_ACTIVE_LEVEL in test. Should be SPDLOG_LEVEL_DEBUG"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define TEST_FILENAME "test_logs/simple_log"
|
||||||
|
|
||||||
TEST_CASE("debug and trace w/o format string", "[macros]]")
|
TEST_CASE("debug and trace w/o format string", "[macros]]")
|
||||||
{
|
{
|
||||||
|
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
std::string filename = "test_logs/simple_log";
|
spdlog::filename_t filename = SPDLOG_FILENAME_T(TEST_FILENAME);
|
||||||
|
|
||||||
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
|
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
|
||||||
logger->set_pattern("%v");
|
logger->set_pattern("%v");
|
||||||
@@ -23,8 +25,8 @@ TEST_CASE("debug and trace w/o format string", "[macros]]")
|
|||||||
logger->flush();
|
logger->flush();
|
||||||
|
|
||||||
using spdlog::details::os::default_eol;
|
using spdlog::details::os::default_eol;
|
||||||
REQUIRE(ends_with(file_contents(filename), fmt::format("Test message 2{}", default_eol)));
|
REQUIRE(ends_with(file_contents(TEST_FILENAME), fmt::format("Test message 2{}", default_eol)));
|
||||||
REQUIRE(count_lines(filename) == 1);
|
REQUIRE(count_lines(TEST_FILENAME) == 1);
|
||||||
|
|
||||||
spdlog::set_default_logger(logger);
|
spdlog::set_default_logger(logger);
|
||||||
|
|
||||||
@@ -32,8 +34,8 @@ TEST_CASE("debug and trace w/o format string", "[macros]]")
|
|||||||
SPDLOG_DEBUG("Test message {}", 4);
|
SPDLOG_DEBUG("Test message {}", 4);
|
||||||
logger->flush();
|
logger->flush();
|
||||||
|
|
||||||
require_message_count(filename, 2);
|
require_message_count(TEST_FILENAME, 2);
|
||||||
REQUIRE(ends_with(file_contents(filename), fmt::format("Test message 4{}", default_eol)));
|
REQUIRE(ends_with(file_contents(TEST_FILENAME), fmt::format("Test message 4{}", default_eol)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("disable param evaluation", "[macros]")
|
TEST_CASE("disable param evaluation", "[macros]")
|
||||||
|
@@ -55,6 +55,14 @@ TEST_CASE("level_to_string_view", "[convert_to_string_view")
|
|||||||
REQUIRE(spdlog::level::to_string_view(spdlog::level::off) == "off");
|
REQUIRE(spdlog::level::to_string_view(spdlog::level::off) == "off");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("set_level_to_string_view", "[set_string_view")
|
||||||
|
{
|
||||||
|
spdlog::level::set_string_view(spdlog::level::info, "INF");
|
||||||
|
REQUIRE(spdlog::level::to_string_view(spdlog::level::info) == "INF");
|
||||||
|
spdlog::level::set_string_view(spdlog::level::info, "info"); // set it back
|
||||||
|
REQUIRE(spdlog::level::to_string_view(spdlog::level::info) == "info");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("to_short_c_str", "[convert_to_short_c_str]")
|
TEST_CASE("to_short_c_str", "[convert_to_short_c_str]")
|
||||||
{
|
{
|
||||||
REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::trace)) == "T");
|
REQUIRE(std::string(spdlog::level::to_short_c_str(spdlog::level::trace)) == "T");
|
||||||
|
@@ -372,7 +372,7 @@ TEST_CASE("clone-custom_formatter", "[pattern_formatter]")
|
|||||||
//
|
//
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static const char *const test_path = "\\a\\b\\myfile.cpp";
|
static const char *const test_path = "\\a\\b\\c/myfile.cpp";
|
||||||
#else
|
#else
|
||||||
static const char *const test_path = "/a/b//myfile.cpp";
|
static const char *const test_path = "/a/b//myfile.cpp";
|
||||||
#endif
|
#endif
|
||||||
|
@@ -103,7 +103,7 @@ TEST_CASE("disable automatic registration", "[registry]")
|
|||||||
spdlog::set_level(log_level);
|
spdlog::set_level(log_level);
|
||||||
// but disable automatic registration
|
// but disable automatic registration
|
||||||
spdlog::set_automatic_registration(false);
|
spdlog::set_automatic_registration(false);
|
||||||
auto logger1 = spdlog::create<spdlog::sinks::daily_file_sink_st>(tested_logger_name, "filename", 11, 59);
|
auto logger1 = spdlog::create<spdlog::sinks::daily_file_sink_st>(tested_logger_name, SPDLOG_FILENAME_T("filename"), 11, 59);
|
||||||
auto logger2 = spdlog::create_async<spdlog::sinks::stdout_color_sink_mt>(tested_logger_name2);
|
auto logger2 = spdlog::create_async<spdlog::sinks::stdout_color_sink_mt>(tested_logger_name2);
|
||||||
// loggers should not be part of the registry
|
// loggers should not be part of the registry
|
||||||
REQUIRE_FALSE(spdlog::get(tested_logger_name));
|
REQUIRE_FALSE(spdlog::get(tested_logger_name));
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifdef _WIN32
|
||||||
|
#include <Windows.h>
|
||||||
|
#else
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -82,7 +84,7 @@ bool ends_with(std::string const &value, std::string const &ending)
|
|||||||
std::size_t count_files(const std::string &folder)
|
std::size_t count_files(const std::string &folder)
|
||||||
{
|
{
|
||||||
size_t counter = 0;
|
size_t counter = 0;
|
||||||
WIN32_FIND_DATA ffd;
|
WIN32_FIND_DATAA ffd;
|
||||||
|
|
||||||
// Start iterating over the files in the folder directory.
|
// Start iterating over the files in the folder directory.
|
||||||
HANDLE hFind = ::FindFirstFileA((folder + "\\*").c_str(), &ffd);
|
HANDLE hFind = ::FindFirstFileA((folder + "\\*").c_str(), &ffd);
|
||||||
@@ -92,7 +94,7 @@ std::size_t count_files(const std::string &folder)
|
|||||||
{
|
{
|
||||||
if (ffd.cFileName[0] != '.')
|
if (ffd.cFileName[0] != '.')
|
||||||
counter++;
|
counter++;
|
||||||
} while (::FindNextFile(hFind, &ffd) != 0);
|
} while (::FindNextFileA(hFind, &ffd) != 0);
|
||||||
::FindClose(hFind);
|
::FindClose(hFind);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user