mirror of
https://github.com/gabime/spdlog.git
synced 2025-03-02 04:05:50 +08:00
wip
This commit is contained in:
parent
daf1b97b8f
commit
1c58ca4b5e
@ -1,4 +1,4 @@
|
|||||||
//
|
//
|
||||||
// Copyright(c) 2015 Gabi Melman.
|
// Copyright(c) 2015 Gabi Melman.
|
||||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
@ -7,6 +7,8 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include "spdlog/details/windows_include.h"
|
||||||
|
|
||||||
void load_levels_example();
|
void load_levels_example();
|
||||||
void stdout_logger_example();
|
void stdout_logger_example();
|
||||||
void basic_example();
|
void basic_example();
|
||||||
@ -32,9 +34,26 @@ void replace_default_logger_example();
|
|||||||
#include "spdlog/version.h"
|
#include "spdlog/version.h"
|
||||||
|
|
||||||
int main(int, char *[]) {
|
int main(int, char *[]) {
|
||||||
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
// Log levels can be loaded from argv/env using "SPDLOG_LEVEL"
|
// Log levels can be loaded from argv/env using "SPDLOG_LEVEL"
|
||||||
load_levels_example();
|
|
||||||
SPDLOG_INFO("This message should be displayed..");
|
//spdlog::filename_t x = L"logs/hourlyעכעכ.txt";
|
||||||
|
std::filesystem::path const x{L"\xd83d\x4000"};
|
||||||
|
try {
|
||||||
|
auto my_s = spdlog::details::os::filename_to_str(x);
|
||||||
|
spdlog::info("mystring: {}", my_s);
|
||||||
|
|
||||||
|
|
||||||
|
auto s = x.u8string();
|
||||||
|
spdlog::info("u8string: {}", s);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
SPDLOG_INFO("EXCEPTION {}", e.what());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
spdlog::info("Welcome to spdlog version {}.{}.{} !", SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH);
|
spdlog::info("Welcome to spdlog version {}.{}.{} !", SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH);
|
||||||
spdlog::warn("Easy padding in numbers like {:08d}", 12);
|
spdlog::warn("Easy padding in numbers like {:08d}", 12);
|
||||||
spdlog::critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
|
spdlog::critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
|
||||||
@ -114,9 +133,12 @@ void rotating_example() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include "spdlog/sinks/daily_file_sink.h"
|
#include "spdlog/sinks/daily_file_sink.h"
|
||||||
|
#include "spdlog/sinks/hourly_file_sink.h"
|
||||||
void daily_example() {
|
void daily_example() {
|
||||||
|
using namespace spdlog::sinks;
|
||||||
// Create a daily logger - a new file is created every day on 2:30am.
|
// Create a daily logger - a new file is created every day on 2:30am.
|
||||||
auto daily_logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
|
auto daily_logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
|
||||||
|
auto hourly_logger = spdlog::hourly_logger_mt("hourly_logger", L"logs/hourlyגבי.txt", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "spdlog/sinks/callback_sink.h"
|
#include "spdlog/sinks/callback_sink.h"
|
||||||
@ -283,10 +305,7 @@ public:
|
|||||||
dest.append(some_txt.data(), some_txt.data() + some_txt.size());
|
dest.append(some_txt.data(), some_txt.data() + some_txt.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]] std::unique_ptr<custom_flag_formatter> clone() const override { return std::make_unique<my_formatter_flag>(); }
|
||||||
std::unique_ptr<custom_flag_formatter> clone() const override {
|
|
||||||
return std::make_unique<my_formatter_flag>();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void custom_flags_example() {
|
void custom_flags_example() {
|
||||||
@ -299,16 +318,20 @@ void custom_flags_example() {
|
|||||||
void file_events_example() {
|
void file_events_example() {
|
||||||
// pass the spdlog::file_event_handlers to file sinks for open/close log file notifications
|
// pass the spdlog::file_event_handlers to file sinks for open/close log file notifications
|
||||||
spdlog::file_event_handlers handlers;
|
spdlog::file_event_handlers handlers;
|
||||||
handlers.before_open = [](spdlog::filename_t filename) { spdlog::info("Before opening {}", filename); };
|
handlers.before_open = [](spdlog::filename_t filename) {
|
||||||
|
// spdlog::info("Before opening {}", filename);
|
||||||
|
};
|
||||||
handlers.after_open = [](spdlog::filename_t filename, std::FILE *fstream) {
|
handlers.after_open = [](spdlog::filename_t filename, std::FILE *fstream) {
|
||||||
spdlog::info("After opening {}", filename);
|
// spdlog::info("After opening {}", filename);
|
||||||
fputs("After opening\n", fstream);
|
fputs("After opening\n", fstream);
|
||||||
};
|
};
|
||||||
handlers.before_close = [](spdlog::filename_t filename, std::FILE *fstream) {
|
handlers.before_close = [](spdlog::filename_t filename, std::FILE *fstream) {
|
||||||
spdlog::info("Before closing {}", filename);
|
// spdlog::info("Before closing {}", filename);
|
||||||
fputs("Before closing\n", fstream);
|
fputs("Before closing\n", fstream);
|
||||||
};
|
};
|
||||||
handlers.after_close = [](spdlog::filename_t filename) { spdlog::info("After closing {}", filename); };
|
handlers.after_close = [](spdlog::filename_t filename) {
|
||||||
|
// spdlog::info("After closing {}", filename);
|
||||||
|
};
|
||||||
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/events-sample.txt", true, handlers);
|
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/events-sample.txt", true, handlers);
|
||||||
spdlog::logger my_logger("some_logger", file_sink);
|
spdlog::logger my_logger("some_logger", file_sink);
|
||||||
my_logger.info("Some log line");
|
my_logger.info("Some log line");
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
#include "./source_loc.h"
|
#include "./source_loc.h"
|
||||||
|
|
||||||
@ -47,8 +48,13 @@ namespace sinks {
|
|||||||
class sink;
|
class sink;
|
||||||
}
|
}
|
||||||
|
|
||||||
using filename_t = std::string;
|
using filename_t = std::filesystem::path;
|
||||||
#define SPDLOG_FILENAME_T(s) s
|
#ifdef _WIN32 // Add L prefix to string literals on Windows when dealing with filenames
|
||||||
|
#define SPDLOG_FILENAME_T_INNER(s) L##s
|
||||||
|
#define SPDLOG_FILENAME_T(s) SPDLOG_FILENAME_T_INNER(s)
|
||||||
|
#else
|
||||||
|
#define SPDLOG_FILENAME_T(s) s
|
||||||
|
#endif
|
||||||
|
|
||||||
using log_clock = std::chrono::system_clock;
|
using log_clock = std::chrono::system_clock;
|
||||||
using sink_ptr = std::shared_ptr<sinks::sink>;
|
using sink_ptr = std::shared_ptr<sinks::sink>;
|
||||||
@ -64,7 +70,6 @@ using wmemory_buf_t = fmt::basic_memory_buffer<wchar_t, 250>;
|
|||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
using format_string_t = fmt::format_string<Args...>;
|
using format_string_t = fmt::format_string<Args...>;
|
||||||
|
|
||||||
#define SPDLOG_BUF_TO_STRING(x) fmt::to_string(x)
|
|
||||||
#define SPDLOG_LEVEL_TRACE 0
|
#define SPDLOG_LEVEL_TRACE 0
|
||||||
#define SPDLOG_LEVEL_DEBUG 1
|
#define SPDLOG_LEVEL_DEBUG 1
|
||||||
#define SPDLOG_LEVEL_INFO 2
|
#define SPDLOG_LEVEL_INFO 2
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ctime> // std::time_t
|
#include <ctime> // std::time_t
|
||||||
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
namespace spdlog {
|
namespace spdlog {
|
||||||
@ -24,7 +23,7 @@ SPDLOG_API std::tm gmtime() noexcept;
|
|||||||
// eol definition and folder separator for the current os
|
// eol definition and folder separator for the current os
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
constexpr static const char *default_eol = "\r\n";
|
constexpr static const char *default_eol = "\r\n";
|
||||||
constexpr static const filename_t::value_type folder_seps_filename[] = SPDLOG_FILENAME_T("\\/");
|
constexpr static const filename_t::value_type folder_seps_filename[] = L"\\/";
|
||||||
#else
|
#else
|
||||||
constexpr static const char *default_eol = "\n";
|
constexpr static const char *default_eol = "\n";
|
||||||
constexpr static const filename_t::value_type folder_seps_filename[] = SPDLOG_FILENAME_T("/");
|
constexpr static const filename_t::value_type folder_seps_filename[] = SPDLOG_FILENAME_T("/");
|
||||||
@ -33,14 +32,15 @@ constexpr static const filename_t::value_type folder_seps_filename[] = SPDLOG_FI
|
|||||||
// 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);
|
||||||
|
|
||||||
// Remove filename. return 0 on success
|
// Remove filename. return true on success
|
||||||
SPDLOG_API int remove(const filename_t &filename) noexcept;
|
SPDLOG_API bool remove(const filename_t &filename);
|
||||||
|
|
||||||
// Remove file if exists. return 0 on success
|
// Remove file if exists. return 0 on success
|
||||||
// Note: Non atomic (might return failure to delete if concurrently deleted by other process/thread)
|
// Note: Non atomic (might return failure to delete if concurrently deleted by other process/thread)
|
||||||
SPDLOG_API int remove_if_exists(const filename_t &filename) noexcept;
|
SPDLOG_API bool remove_if_exists(const filename_t &filename) ;
|
||||||
|
|
||||||
SPDLOG_API int rename(const filename_t &filename1, const filename_t &filename2) noexcept;
|
// Rename file. return true on success
|
||||||
|
SPDLOG_API bool rename(const filename_t &filename1, const filename_t &filename2) noexcept;
|
||||||
|
|
||||||
// Return if file exists.
|
// Return if file exists.
|
||||||
SPDLOG_API bool path_exists(const filename_t &filename) noexcept;
|
SPDLOG_API bool path_exists(const filename_t &filename) noexcept;
|
||||||
@ -63,6 +63,7 @@ SPDLOG_API size_t thread_id() noexcept;
|
|||||||
// See https://github.com/gabime/spdlog/issues/609
|
// See https://github.com/gabime/spdlog/issues/609
|
||||||
SPDLOG_API void sleep_for_millis(unsigned int milliseconds) noexcept;
|
SPDLOG_API void sleep_for_millis(unsigned int milliseconds) noexcept;
|
||||||
|
|
||||||
|
// Try tp convert wstring filename to string. Return "??" if failed
|
||||||
SPDLOG_API std::string filename_to_str(const filename_t &filename);
|
SPDLOG_API std::string filename_to_str(const filename_t &filename);
|
||||||
|
|
||||||
SPDLOG_API int pid() noexcept;
|
SPDLOG_API int pid() noexcept;
|
||||||
|
@ -11,41 +11,45 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
#include "./base_sink.h"
|
||||||
#include "../details/circular_q.h"
|
#include "../details/circular_q.h"
|
||||||
#include "../details/file_helper.h"
|
#include "../details/file_helper.h"
|
||||||
#include "../details/null_mutex.h"
|
#include "../details/null_mutex.h"
|
||||||
#include "../details/os.h"
|
#include "../details/os.h"
|
||||||
#include "../details/synchronous_factory.h"
|
#include "../details/synchronous_factory.h"
|
||||||
#include "./base_sink.h"
|
|
||||||
|
|
||||||
namespace spdlog {
|
namespace spdlog {
|
||||||
namespace sinks {
|
namespace sinks {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generator of daily log file names in format basename.YYYY-MM-DD.ext
|
* Generator of daily log file names in format basename_YYYY-MM-DD.ext
|
||||||
*/
|
*/
|
||||||
struct daily_filename_calculator {
|
struct daily_filename_calculator {
|
||||||
// Create filename for the form basename.YYYY-MM-DD
|
|
||||||
static filename_t calc_filename(const filename_t &filename, const tm &now_tm) {
|
static filename_t calc_filename(const filename_t &filename, const tm &now_tm) {
|
||||||
filename_t basename, ext;
|
filename_t basename, ext;
|
||||||
std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
|
std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
|
||||||
return fmt_lib::format(SPDLOG_FMT_STRING(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}{}")), basename, now_tm.tm_year + 1900,
|
std::basic_ostringstream<filename_t::value_type> oss;
|
||||||
now_tm.tm_mon + 1, now_tm.tm_mday, ext);
|
auto sep = SPDLOG_FILENAME_T('-');
|
||||||
|
oss << basename.native() << SPDLOG_FILENAME_T('_') << std::setfill(SPDLOG_FILENAME_T('0')) << std::setw(4)
|
||||||
|
<< now_tm.tm_year + 1900 << sep
|
||||||
|
<< std::setw(2) << now_tm.tm_mon + 1 << sep << std::setw(2) << now_tm.tm_mday << ext.native();
|
||||||
|
return oss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generator of daily log file names with strftime format.
|
* Generator of daily log file names with strftime format.
|
||||||
* Usages:
|
* Usages:
|
||||||
* auto sink =
|
*
|
||||||
* std::make_shared<spdlog::sinks::daily_file_format_sink_mt>("myapp-%Y-%m-%d:%H:%M:%S.log", hour,
|
* std::make_shared<spdlog::sinks::daily_file_format_sink_mt>("myapp-%Y-%m-%d:%H:%M:%S.log", hour, minute);
|
||||||
* minute);" auto logger = spdlog::daily_logger_format_mt("loggername, "myapp-%Y-%m-%d:%X.log",
|
* or
|
||||||
* hour, minute)"
|
* spdlog::daily_logger_format_mt("loggername, "myapp-%Y-%m-%d:%X.log", hour, minute)"
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct daily_filename_format_calculator {
|
struct daily_filename_format_calculator {
|
||||||
static filename_t calc_filename(const filename_t &file_path, const tm &now_tm) {
|
static filename_t calc_filename(const filename_t &file_path, const tm &now_tm) {
|
||||||
std::stringstream stream;
|
std::basic_ostringstream<filename_t::value_type> stream;
|
||||||
stream << std::put_time(&now_tm, file_path.c_str());
|
stream << std::put_time(&now_tm, file_path.c_str());
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
@ -164,7 +168,7 @@ private:
|
|||||||
if (filenames_q_.full()) {
|
if (filenames_q_.full()) {
|
||||||
auto old_filename = std::move(filenames_q_.front());
|
auto old_filename = std::move(filenames_q_.front());
|
||||||
filenames_q_.pop_front();
|
filenames_q_.pop_front();
|
||||||
bool ok = remove_if_exists(old_filename) == 0;
|
bool ok = remove_if_exists(old_filename);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
filenames_q_.push_back(std::move(current_file));
|
filenames_q_.push_back(std::move(current_file));
|
||||||
throw_spdlog_ex("Failed removing daily file " + filename_to_str(old_filename), errno);
|
throw_spdlog_ex("Failed removing daily file " + filename_to_str(old_filename), errno);
|
||||||
|
@ -29,8 +29,12 @@ struct hourly_filename_calculator {
|
|||||||
static filename_t calc_filename(const filename_t &filename, const tm &now_tm) {
|
static filename_t calc_filename(const filename_t &filename, const tm &now_tm) {
|
||||||
filename_t basename, ext;
|
filename_t basename, ext;
|
||||||
std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
|
std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
|
||||||
return fmt_lib::format(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}{}"), basename, now_tm.tm_year + 1900,
|
std::basic_ostringstream<filename_t::value_type> oss;
|
||||||
now_tm.tm_mon + 1, now_tm.tm_mday, now_tm.tm_hour, ext);
|
auto sep = SPDLOG_FILENAME_T('-');
|
||||||
|
oss << basename.native() << sep << std::setfill(SPDLOG_FILENAME_T('0')) << std::setw(4) << now_tm.tm_year + 1900 << sep
|
||||||
|
<< std::setw(2) << now_tm.tm_mon + 1 << sep << std::setw(2) << now_tm.tm_mday << sep << std::setw(2) << now_tm.tm_hour
|
||||||
|
<< ext.native();
|
||||||
|
return oss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ private:
|
|||||||
|
|
||||||
// delete the target if exists, and rename the src file to target
|
// delete the target if exists, and rename the src file to target
|
||||||
// return true on success, false otherwise.
|
// return true on success, false otherwise.
|
||||||
static bool rename_file_(const filename_t &src_filename, const filename_t &target_filename);
|
static bool rename_file_(const filename_t &src_filename, const filename_t &target_filename) noexcept;
|
||||||
|
|
||||||
filename_t base_filename_;
|
filename_t base_filename_;
|
||||||
std::size_t max_size_;
|
std::size_t max_size_;
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
#include "spdlog/details/file_helper.h"
|
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include "spdlog/details/file_helper.h"
|
||||||
#include "spdlog/common.h"
|
#include "spdlog/common.h"
|
||||||
#include "spdlog/details/os.h"
|
#include "spdlog/details/os.h"
|
||||||
|
|
||||||
@ -112,7 +113,7 @@ const filename_t &file_helper::filename() const { return filename_; }
|
|||||||
//
|
//
|
||||||
// "mylog.txt" => ("mylog", ".txt")
|
// "mylog.txt" => ("mylog", ".txt")
|
||||||
// "mylog" => ("mylog", "")
|
// "mylog" => ("mylog", "")
|
||||||
// "mylog." => ("mylog.", "")
|
// "mylog." => ("mylog", ".")
|
||||||
// "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt")
|
// "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt")
|
||||||
//
|
//
|
||||||
// the starting dot in filenames is ignored (hidden files):
|
// the starting dot in filenames is ignored (hidden files):
|
||||||
@ -120,23 +121,10 @@ const filename_t &file_helper::filename() const { return filename_; }
|
|||||||
// ".mylog" => (".mylog". "")
|
// ".mylog" => (".mylog". "")
|
||||||
// "my_folder/.mylog" => ("my_folder/.mylog", "")
|
// "my_folder/.mylog" => ("my_folder/.mylog", "")
|
||||||
// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
|
// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
|
||||||
std::tuple<filename_t, filename_t> file_helper::split_by_extension(const filename_t &fname) {
|
std::tuple<filename_t, filename_t> file_helper::split_by_extension(const filename_t &fname) {
|
||||||
auto ext_index = fname.rfind('.');
|
const auto ext = fname.extension();
|
||||||
|
auto without_ext = filename_t(fname).replace_extension();
|
||||||
// no valid extension found - return whole path and empty string as
|
return std::make_tuple(without_ext, ext);
|
||||||
// extension
|
|
||||||
if (ext_index == filename_t::npos || ext_index == 0 || ext_index == fname.size() - 1) {
|
|
||||||
return std::make_tuple(fname, filename_t());
|
|
||||||
}
|
|
||||||
|
|
||||||
// treat cases like "/etc/rc.d/somelogfile or "/abc/.hiddenfile"
|
|
||||||
auto folder_index = fname.find_last_of(details::os::folder_seps_filename);
|
|
||||||
if (folder_index != filename_t::npos && folder_index >= ext_index - 1) {
|
|
||||||
return std::make_tuple(fname, filename_t());
|
|
||||||
}
|
|
||||||
|
|
||||||
// finally - return a valid base and extension tuple
|
|
||||||
return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace details
|
} // namespace details
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include "spdlog/common.h"
|
#include "spdlog/common.h"
|
||||||
#include "spdlog/details/os.h"
|
#include "spdlog/details/os.h"
|
||||||
@ -63,7 +63,7 @@ std::tm gmtime() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode) {
|
bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode) {
|
||||||
*fp = ::_fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO);
|
*fp = ::_wfsopen((filename.c_str()), mode.c_str(), _SH_DENYNO);
|
||||||
#if defined(SPDLOG_PREVENT_CHILD_FD)
|
#if defined(SPDLOG_PREVENT_CHILD_FD)
|
||||||
if (*fp != nullptr) {
|
if (*fp != nullptr) {
|
||||||
auto file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(::_fileno(*fp)));
|
auto file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(::_fileno(*fp)));
|
||||||
@ -76,19 +76,27 @@ bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode) {
|
|||||||
return *fp == nullptr;
|
return *fp == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int remove(const filename_t &filename) noexcept { return std::remove(filename.c_str()); }
|
bool remove(const filename_t &filename) { return std::filesystem::remove(filename); }
|
||||||
|
|
||||||
int remove_if_exists(const filename_t &filename) noexcept { return path_exists(filename) ? remove(filename) : 0; }
|
bool remove_if_exists(const filename_t &filename) {
|
||||||
|
if (path_exists(filename)) {
|
||||||
|
return os::remove(filename);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int rename(const filename_t &filename1, const filename_t &filename2) noexcept {
|
bool rename(const filename_t &filename1, const filename_t &filename2) noexcept {
|
||||||
return std::rename(filename1.c_str(), filename2.c_str());
|
if (!std::filesystem::is_regular_file(filename1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::error_code ec;
|
||||||
|
std::filesystem::rename(filename1, filename2, ec);
|
||||||
|
return !ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if path exists (file or directory)
|
// Return true if path exists (file or directory)
|
||||||
bool path_exists(const filename_t &filename) noexcept {
|
bool path_exists(const filename_t &filename) noexcept { return std::filesystem::exists(filename); }
|
||||||
struct _stat buffer;
|
|
||||||
return (::_stat(filename.c_str(), &buffer) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
// avoid warning about unreachable statement at the end of filesize()
|
// avoid warning about unreachable statement at the end of filesize()
|
||||||
@ -158,7 +166,19 @@ size_t thread_id() noexcept {
|
|||||||
// See https://github.com/gabime/spdlog/issues/609
|
// See https://github.com/gabime/spdlog/issues/609
|
||||||
void sleep_for_millis(unsigned int milliseconds) noexcept { ::Sleep(milliseconds); }
|
void sleep_for_millis(unsigned int milliseconds) noexcept { ::Sleep(milliseconds); }
|
||||||
|
|
||||||
std::string filename_to_str(const filename_t &filename) { return filename; }
|
// Try tp convert wstring filename to string. Return "??" if failed
|
||||||
|
std::string filename_to_str(const filename_t &filename) {
|
||||||
|
static_assert(std::is_same_v<filename_t::value_type, wchar_t>, "filename_t type must be wchar_t");
|
||||||
|
try {
|
||||||
|
memory_buf_t buf;
|
||||||
|
wstr_to_utf8buf(filename.wstring(), buf);
|
||||||
|
return std::string(buf.data(), buf.size());
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
return "??";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int pid() noexcept { return static_cast<int>(::GetCurrentProcessId()); }
|
int pid() noexcept { return static_cast<int>(::GetCurrentProcessId()); }
|
||||||
|
|
||||||
@ -193,7 +213,7 @@ void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw_spdlog_ex(fmt_lib::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError()));
|
throw spdlog_ex("WideCharToMultiByte failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target) {
|
void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target) {
|
||||||
@ -223,44 +243,13 @@ void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// return true on success
|
// return true on success
|
||||||
static bool mkdir_(const filename_t &path) { return ::_mkdir(path.c_str()) == 0; }
|
// static bool mkdir_(const filename_t &path) { return ::_mkdir(path.c_str()) == 0; }
|
||||||
|
|
||||||
// create the given directory - and all directories leading to it
|
// create the given directory - and all directories leading to it
|
||||||
// return true on success or if the directory already exists
|
// return true on success or if the directory already exists
|
||||||
bool create_dir(const filename_t &path) {
|
bool create_dir(const filename_t &path) {
|
||||||
if (path_exists(path)) {
|
std::error_code ec;
|
||||||
return true;
|
return std::filesystem::create_directories(path, ec) || !ec;
|
||||||
}
|
|
||||||
|
|
||||||
if (path.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t search_offset = 0;
|
|
||||||
do {
|
|
||||||
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
|
|
||||||
if (token_pos == filename_t::npos) {
|
|
||||||
token_pos = path.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto subdir = path.substr(0, token_pos);
|
|
||||||
|
|
||||||
// if subdir is just a drive letter, add a slash e.g. "c:"=>"c:\",
|
|
||||||
// otherwise path_exists(subdir) returns false (issue #3079)
|
|
||||||
const bool is_drive = subdir.length() == 2 && subdir[1] == ':';
|
|
||||||
if (is_drive) {
|
|
||||||
subdir += '\\';
|
|
||||||
token_pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!subdir.empty() && !path_exists(subdir) && !mkdir_(subdir)) {
|
|
||||||
return false; // return error if failed creating dir
|
|
||||||
}
|
|
||||||
search_offset = token_pos + 1;
|
|
||||||
} while (search_offset < path.size());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return directory name from given path or empty string
|
// Return directory name from given path or empty string
|
||||||
@ -268,10 +257,7 @@ bool create_dir(const filename_t &path) {
|
|||||||
// "abc/" => "abc"
|
// "abc/" => "abc"
|
||||||
// "abc" => ""
|
// "abc" => ""
|
||||||
// "abc///" => "abc//"
|
// "abc///" => "abc//"
|
||||||
filename_t dir_name(const filename_t &path) {
|
filename_t dir_name(const filename_t &path) { return path.parent_path(); }
|
||||||
auto pos = path.find_last_of(folder_seps_filename);
|
|
||||||
return pos != filename_t::npos ? path.substr(0, pos) : filename_t{};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getenv(const char *field) {
|
std::string getenv(const char *field) {
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "spdlog/common.h"
|
#include "spdlog/common.h"
|
||||||
#include "spdlog/details/file_helper.h"
|
#include "spdlog/details/file_helper.h"
|
||||||
@ -51,8 +52,11 @@ filename_t rotating_file_sink<Mutex>::calc_filename(const filename_t &filename,
|
|||||||
|
|
||||||
filename_t basename;
|
filename_t basename;
|
||||||
filename_t ext;
|
filename_t ext;
|
||||||
std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
|
std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
|
||||||
return fmt_lib::format(SPDLOG_FMT_STRING(SPDLOG_FILENAME_T("{}.{}{}")), basename, index, ext);
|
std::basic_ostringstream<filename_t::value_type> oss;
|
||||||
|
oss << basename.native() << "." << index << ext.native();
|
||||||
|
return oss.str();
|
||||||
|
//return fmt_lib::format(SPDLOG_FMT_STRING(SPDLOG_FILENAME_T("{}.{}{}")), basename, index, ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Mutex>
|
template <typename Mutex>
|
||||||
@ -130,10 +134,8 @@ void rotating_file_sink<Mutex>::rotate_() {
|
|||||||
// delete the target if exists, and rename the src file to target
|
// delete the target if exists, and rename the src file to target
|
||||||
// return true on success, false otherwise.
|
// return true on success, false otherwise.
|
||||||
template <typename Mutex>
|
template <typename Mutex>
|
||||||
bool rotating_file_sink<Mutex>::rename_file_(const filename_t &src_filename, const filename_t &target_filename) {
|
bool rotating_file_sink<Mutex>::rename_file_(const filename_t &src_filename, const filename_t &target_filename) noexcept{
|
||||||
// try to delete the target file in case it already exists.
|
return details::os::rename(src_filename, target_filename);
|
||||||
(void)details::os::remove(target_filename);
|
|
||||||
return details::os::rename(src_filename, target_filename) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sinks
|
} // namespace sinks
|
||||||
|
@ -43,32 +43,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(SPDLOG_FILENAME_T("")).empty());
|
#ifdef WIN32
|
||||||
REQUIRE(dir_name(SPDLOG_FILENAME_T("dir")).empty());
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\)")) == SPDLOG_FILENAME_T("dir"));
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\)")) == SPDLOG_FILENAME_T("dir"));
|
||||||
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\\\)")) == SPDLOG_FILENAME_T(R"(dir\\)"));
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\\\)")) == SPDLOG_FILENAME_T(R"(dir)"));
|
||||||
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\file)")) == SPDLOG_FILENAME_T("dir"));
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\file)")) == SPDLOG_FILENAME_T("dir"));
|
||||||
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir/file)")) == SPDLOG_FILENAME_T("dir"));
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir/file)")) == SPDLOG_FILENAME_T("dir"));
|
||||||
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\file.txt)")) == SPDLOG_FILENAME_T("dir"));
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\file.txt)")) == SPDLOG_FILENAME_T("dir"));
|
||||||
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir/file)")) == SPDLOG_FILENAME_T("dir"));
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir/file)")) == SPDLOG_FILENAME_T("dir"));
|
||||||
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\file.txt\)")) == SPDLOG_FILENAME_T(R"(dir\file.txt)"));
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(dir\file.txt\)")) == SPDLOG_FILENAME_T(R"(dir\file.txt)"));
|
||||||
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(\dir\file.txt)")) == SPDLOG_FILENAME_T(R"(\dir)"));
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(\dir\file.txt)")) == SPDLOG_FILENAME_T(R"(\dir)"));
|
||||||
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(\\dir\file.txt)")) == SPDLOG_FILENAME_T(R"(\\dir)"));
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(\\dir\file.txt)")) == SPDLOG_FILENAME_T(R"(\\dir\)"));
|
||||||
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(..\file.txt)")) == SPDLOG_FILENAME_T(".."));
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(..\file.txt)")) == SPDLOG_FILENAME_T(".."));
|
||||||
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(.\file.txt)")) == SPDLOG_FILENAME_T("."));
|
REQUIRE(dir_name(SPDLOG_FILENAME_T(R"(.\file.txt)")) == SPDLOG_FILENAME_T("."));
|
||||||
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(SPDLOG_FILENAME_T(R"(c:\\a\b\c\d\file.txt)")) == SPDLOG_FILENAME_T(R"(c:\\a\b\c\d)"));
|
||||||
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(SPDLOG_FILENAME_T(R"(c://a/b/c/d/file.txt)")) == SPDLOG_FILENAME_T(R"(c://a/b/c/d)"));
|
||||||
#endif
|
#endif
|
||||||
|
REQUIRE(dir_name(SPDLOG_FILENAME_T("")).empty());
|
||||||
|
REQUIRE(dir_name(SPDLOG_FILENAME_T("dir")).empty());
|
||||||
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///")) == 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")) == 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"));
|
||||||
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/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("//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(".."));
|
||||||
REQUIRE(dir_name(SPDLOG_FILENAME_T("./file.txt")) == SPDLOG_FILENAME_T("."));
|
REQUIRE(dir_name(SPDLOG_FILENAME_T("./file.txt")) == SPDLOG_FILENAME_T("."));
|
||||||
}
|
}
|
||||||
@ -122,15 +121,4 @@ TEST_CASE("create_abs_path2", "[create_dir]") {
|
|||||||
REQUIRE(create_dir(abs_path) == true);
|
REQUIRE(create_dir(abs_path) == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("non_existing_drive", "[create_dir]") {
|
|
||||||
prepare_logdir();
|
|
||||||
spdlog::filename_t path;
|
|
||||||
|
|
||||||
auto non_existing_drive = find_non_existing_drive();
|
|
||||||
path += non_existing_drive;
|
|
||||||
path += SPDLOG_FILENAME_T(":\\");
|
|
||||||
REQUIRE(create_dir(path) == false);
|
|
||||||
path += SPDLOG_FILENAME_T("subdir");
|
|
||||||
REQUIRE(create_dir(path) == false);
|
|
||||||
}
|
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
#include "spdlog/sinks/daily_file_sink.h"
|
#include "spdlog/sinks/daily_file_sink.h"
|
||||||
#include "spdlog/sinks/rotating_file_sink.h"
|
#include "spdlog/sinks/rotating_file_sink.h"
|
||||||
|
|
||||||
using filename_memory_buf_t = spdlog::memory_buf_t;
|
using file_t_sstream = std::basic_stringstream<spdlog::filename_t::value_type>;
|
||||||
|
using spdlog::details::os::filename_to_str;
|
||||||
|
|
||||||
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>;
|
||||||
@ -15,10 +16,12 @@ TEST_CASE("daily_logger with dateonly calculator", "[daily_logger]") {
|
|||||||
|
|
||||||
// calculate filename (time based)
|
// calculate filename (time based)
|
||||||
spdlog::filename_t basename = SPDLOG_FILENAME_T("test_logs/daily_dateonly");
|
spdlog::filename_t basename = SPDLOG_FILENAME_T("test_logs/daily_dateonly");
|
||||||
std::tm tm = spdlog::details::os::localtime();
|
std::tm now_tm = spdlog::details::os::localtime();
|
||||||
filename_memory_buf_t w;
|
|
||||||
spdlog::fmt_lib::format_to(std::back_inserter(w), SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}"), basename, tm.tm_year + 1900,
|
|
||||||
tm.tm_mon + 1, tm.tm_mday);
|
|
||||||
|
//spdlog::fmt_lib::format_to(std::back_inserter(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) {
|
||||||
@ -26,39 +29,17 @@ TEST_CASE("daily_logger with dateonly calculator", "[daily_logger]") {
|
|||||||
}
|
}
|
||||||
logger->flush();
|
logger->flush();
|
||||||
|
|
||||||
require_message_count(SPDLOG_BUF_TO_STRING(w), 10);
|
// calcluate expected filename and check if it exists with the expected message count
|
||||||
|
file_t_sstream stream;
|
||||||
|
auto sep = SPDLOG_FILENAME_T('-');
|
||||||
|
stream << basename.native() << SPDLOG_FILENAME_T('_') << std::setfill(SPDLOG_FILENAME_T('0')) << std::setw(4)
|
||||||
|
<< now_tm.tm_year + 1900 << sep << std::setw(2) << now_tm.tm_mon + 1 << sep << std::setw(2) << now_tm.tm_mday;
|
||||||
|
|
||||||
|
require_message_count(filename_to_str(stream.str()), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct custom_daily_file_name_calculator {
|
|
||||||
static spdlog::filename_t calc_filename(const spdlog::filename_t &basename, const tm &now_tm) {
|
|
||||||
filename_memory_buf_t w;
|
|
||||||
spdlog::fmt_lib::format_to(std::back_inserter(w), SPDLOG_FILENAME_T("{}{:04d}{:02d}{:02d}"), basename,
|
|
||||||
now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday);
|
|
||||||
|
|
||||||
return SPDLOG_BUF_TO_STRING(w);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_CASE("daily_logger with custom calculator", "[daily_logger]") {
|
|
||||||
using sink_type = spdlog::sinks::daily_file_sink<std::mutex, custom_daily_file_name_calculator>;
|
|
||||||
|
|
||||||
prepare_logdir();
|
|
||||||
|
|
||||||
// calculate filename (time based)
|
|
||||||
spdlog::filename_t basename = SPDLOG_FILENAME_T("test_logs/daily_dateonly");
|
|
||||||
std::tm tm = spdlog::details::os::localtime();
|
|
||||||
filename_memory_buf_t w;
|
|
||||||
spdlog::fmt_lib::format_to(std::back_inserter(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);
|
|
||||||
for (int i = 0; i < 10; ++i) {
|
|
||||||
logger->info("Test message {}", i);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger->flush();
|
|
||||||
require_message_count(SPDLOG_BUF_TO_STRING(w), 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* File name calculations
|
* File name calculations
|
||||||
@ -86,13 +67,19 @@ 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 now = spdlog::details::os::localtime();
|
||||||
auto filename =
|
auto filename =
|
||||||
spdlog::sinks::daily_filename_calculator::calc_filename(SPDLOG_FILENAME_T("daily.txt"), spdlog::details::os::localtime());
|
spdlog::sinks::daily_filename_calculator::calc_filename(SPDLOG_FILENAME_T("daily.txt"), now);
|
||||||
// date regex based on https://www.regular-expressions.info/dates.html
|
|
||||||
std::basic_regex<spdlog::filename_t::value_type> re(
|
file_t_sstream stream;
|
||||||
SPDLOG_FILENAME_T(R"(^daily_(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])\.txt$)"));
|
stream << "daily_" << now.tm_year + 1900 << "-" << std::setw(2) << std::setfill(SPDLOG_FILENAME_T('0')) << now.tm_mon + 1 << "-"
|
||||||
std::match_results<spdlog::filename_t::const_iterator> match;
|
<< std::setw(2) << std::setfill(SPDLOG_FILENAME_T('0')) << now.tm_mday << ".txt";
|
||||||
REQUIRE(std::regex_match(filename, match, re));
|
REQUIRE(filename == std::filesystem::path(stream.str()));
|
||||||
|
//// date regex based on https://www.regular-expressions.info/dates.html
|
||||||
|
//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::match_results<spdlog::filename_t::const_iterator> match;
|
||||||
|
//REQUIRE(std::regex_match(filename, match, re));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -101,8 +88,13 @@ TEST_CASE("daily_file_sink::daily_filename_format_calculator", "[daily_file_sink
|
|||||||
// example-YYYY-MM-DD.log
|
// example-YYYY-MM-DD.log
|
||||||
auto filename = spdlog::sinks::daily_filename_format_calculator::calc_filename(SPDLOG_FILENAME_T("example-%Y-%m-%d.log"), tm);
|
auto filename = spdlog::sinks::daily_filename_format_calculator::calc_filename(SPDLOG_FILENAME_T("example-%Y-%m-%d.log"), tm);
|
||||||
|
|
||||||
REQUIRE(filename == spdlog::fmt_lib::format(SPDLOG_FILENAME_T("example-{:04d}-{:02d}-{:02d}.log"), tm.tm_year + 1900,
|
// calc excpected filename
|
||||||
tm.tm_mon + 1, tm.tm_mday));
|
file_t_sstream stream;
|
||||||
|
stream << "example-" << tm.tm_year + 1900 << "-" << std::setw(2) << std::setfill(SPDLOG_FILENAME_T('0')) << tm.tm_mon + 1
|
||||||
|
<< "-" << std::setw(2) << std::setfill(SPDLOG_FILENAME_T('0')) << tm.tm_mday << ".log";
|
||||||
|
|
||||||
|
|
||||||
|
REQUIRE(filename == std::filesystem::path(stream.str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test removal of old files */
|
/* Test removal of old files */
|
||||||
|
@ -82,7 +82,7 @@ TEST_CASE("file_helper_split_by_extension", "[file_helper::split_by_extension()]
|
|||||||
test_split_ext(SPDLOG_FILENAME_T("/aaa/bb.d/mylog"), SPDLOG_FILENAME_T("/aaa/bb.d/mylog"), SPDLOG_FILENAME_T(""));
|
test_split_ext(SPDLOG_FILENAME_T("/aaa/bb.d/mylog"), SPDLOG_FILENAME_T("/aaa/bb.d/mylog"), SPDLOG_FILENAME_T(""));
|
||||||
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(SPDLOG_FILENAME_T("/aaa/bb.d/mylog.txt"), SPDLOG_FILENAME_T("/aaa/bb.d/mylog"), SPDLOG_FILENAME_T(".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(SPDLOG_FILENAME_T("aaa/bbb/ccc/mylog.txt"), SPDLOG_FILENAME_T("aaa/bbb/ccc/mylog"), SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext(SPDLOG_FILENAME_T("aaa/bbb/ccc/mylog."), SPDLOG_FILENAME_T("aaa/bbb/ccc/mylog."), SPDLOG_FILENAME_T(""));
|
test_split_ext(SPDLOG_FILENAME_T("aaa/bbb/ccc/mylog."), SPDLOG_FILENAME_T("aaa/bbb/ccc/mylog"), SPDLOG_FILENAME_T("."));
|
||||||
test_split_ext(SPDLOG_FILENAME_T("aaa/bbb/ccc/.mylog.txt"), SPDLOG_FILENAME_T("aaa/bbb/ccc/.mylog"),
|
test_split_ext(SPDLOG_FILENAME_T("aaa/bbb/ccc/.mylog.txt"), SPDLOG_FILENAME_T("aaa/bbb/ccc/.mylog"),
|
||||||
SPDLOG_FILENAME_T(".txt"));
|
SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext(SPDLOG_FILENAME_T("/aaa/bbb/ccc/mylog.txt"), SPDLOG_FILENAME_T("/aaa/bbb/ccc/mylog"),
|
test_split_ext(SPDLOG_FILENAME_T("/aaa/bbb/ccc/mylog.txt"), SPDLOG_FILENAME_T("/aaa/bbb/ccc/mylog"),
|
||||||
@ -92,7 +92,7 @@ TEST_CASE("file_helper_split_by_extension", "[file_helper::split_by_extension()]
|
|||||||
test_split_ext(SPDLOG_FILENAME_T(".././mylog.txt"), SPDLOG_FILENAME_T(".././mylog"), SPDLOG_FILENAME_T(".txt"));
|
test_split_ext(SPDLOG_FILENAME_T(".././mylog.txt"), SPDLOG_FILENAME_T(".././mylog"), SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext(SPDLOG_FILENAME_T(".././mylog.txt/xxx"), SPDLOG_FILENAME_T(".././mylog.txt/xxx"), SPDLOG_FILENAME_T(""));
|
test_split_ext(SPDLOG_FILENAME_T(".././mylog.txt/xxx"), SPDLOG_FILENAME_T(".././mylog.txt/xxx"), SPDLOG_FILENAME_T(""));
|
||||||
test_split_ext(SPDLOG_FILENAME_T("/mylog.txt"), SPDLOG_FILENAME_T("/mylog"), SPDLOG_FILENAME_T(".txt"));
|
test_split_ext(SPDLOG_FILENAME_T("/mylog.txt"), SPDLOG_FILENAME_T("/mylog"), SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext(SPDLOG_FILENAME_T("//mylog.txt"), SPDLOG_FILENAME_T("//mylog"), SPDLOG_FILENAME_T(".txt"));
|
test_split_ext(SPDLOG_FILENAME_T("///mylog.txt"), SPDLOG_FILENAME_T("///mylog"), SPDLOG_FILENAME_T(".txt"));
|
||||||
test_split_ext(SPDLOG_FILENAME_T(""), SPDLOG_FILENAME_T(""), SPDLOG_FILENAME_T(""));
|
test_split_ext(SPDLOG_FILENAME_T(""), SPDLOG_FILENAME_T(""), SPDLOG_FILENAME_T(""));
|
||||||
test_split_ext(SPDLOG_FILENAME_T("."), SPDLOG_FILENAME_T("."), SPDLOG_FILENAME_T(""));
|
test_split_ext(SPDLOG_FILENAME_T("."), SPDLOG_FILENAME_T("."), SPDLOG_FILENAME_T(""));
|
||||||
test_split_ext(SPDLOG_FILENAME_T("..txt"), SPDLOG_FILENAME_T("."), SPDLOG_FILENAME_T(".txt"));
|
test_split_ext(SPDLOG_FILENAME_T("..txt"), SPDLOG_FILENAME_T("."), SPDLOG_FILENAME_T(".txt"));
|
||||||
|
Loading…
Reference in New Issue
Block a user