mirror of
https://github.com/gabime/spdlog.git
synced 2025-09-29 01:29:35 +08:00
Use std filesystem (#3284)
* Use std::filesystem for path names and impl
This commit is contained in:
@@ -5,14 +5,14 @@
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <chrono>
|
||||
#include <string_view>
|
||||
|
||||
#include "./source_loc.h"
|
||||
|
||||
@@ -47,9 +47,6 @@ namespace sinks {
|
||||
class sink;
|
||||
}
|
||||
|
||||
using filename_t = std::string;
|
||||
#define SPDLOG_FILENAME_T(s) s
|
||||
|
||||
using log_clock = std::chrono::system_clock;
|
||||
using sink_ptr = std::shared_ptr<sinks::sink>;
|
||||
using sinks_init_list = std::initializer_list<sink_ptr>;
|
||||
@@ -64,7 +61,6 @@ using wmemory_buf_t = fmt::basic_memory_buffer<wchar_t, 250>;
|
||||
template <typename... 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_DEBUG 1
|
||||
#define SPDLOG_LEVEL_INFO 2
|
||||
@@ -102,7 +98,7 @@ constexpr std::array<std::string_view, levels_count> short_level_names{"T", "D",
|
||||
return level_string_views.at(level_to_number(lvl));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const std::string_view to_short_string_view(spdlog::level lvl) noexcept {
|
||||
[[nodiscard]] constexpr std::string_view to_short_string_view(spdlog::level lvl) noexcept {
|
||||
return short_level_names.at(level_to_number(lvl));
|
||||
}
|
||||
|
||||
@@ -140,33 +136,4 @@ private:
|
||||
[[noreturn]] SPDLOG_API void throw_spdlog_ex(const std::string &msg, int last_errno);
|
||||
[[noreturn]] SPDLOG_API void throw_spdlog_ex(std::string msg);
|
||||
|
||||
struct file_event_handlers {
|
||||
file_event_handlers()
|
||||
: before_open(nullptr),
|
||||
after_open(nullptr),
|
||||
before_close(nullptr),
|
||||
after_close(nullptr) {}
|
||||
|
||||
std::function<void(const filename_t &filename)> before_open;
|
||||
std::function<void(const filename_t &filename, std::FILE *file_stream)> after_open;
|
||||
std::function<void(const filename_t &filename, std::FILE *file_stream)> before_close;
|
||||
std::function<void(const filename_t &filename)> after_close;
|
||||
};
|
||||
|
||||
namespace details {
|
||||
|
||||
// to_string_view
|
||||
|
||||
[[nodiscard]] constexpr spdlog::string_view_t to_string_view(const memory_buf_t &buf) noexcept {
|
||||
return spdlog::string_view_t{buf.data(), buf.size()};
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr spdlog::string_view_t to_string_view(spdlog::string_view_t str) noexcept { return str; }
|
||||
|
||||
template <typename T, typename... Args>
|
||||
[[nodiscard]] constexpr fmt::basic_string_view<T> to_string_view(fmt::basic_format_string<T, Args...> fmt) noexcept {
|
||||
return fmt;
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
} // namespace spdlog
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include <tuple>
|
||||
|
||||
#include "../common.h"
|
||||
#include "../file_event_handlers.h"
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
@@ -32,21 +33,6 @@ public:
|
||||
size_t size() const;
|
||||
const filename_t &filename() const;
|
||||
|
||||
//
|
||||
// return file path and its extension:
|
||||
//
|
||||
// "mylog.txt" => ("mylog", ".txt")
|
||||
// "mylog" => ("mylog", "")
|
||||
// "mylog." => ("mylog.", "")
|
||||
// "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt")
|
||||
//
|
||||
// the starting dot in filenames is ignored (hidden files):
|
||||
//
|
||||
// ".mylog" => (".mylog". "")
|
||||
// "my_folder/.mylog" => ("my_folder/.mylog", "")
|
||||
// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
|
||||
static std::tuple<filename_t, filename_t> split_by_extension(const filename_t &fname);
|
||||
|
||||
private:
|
||||
const int open_tries_ = 5;
|
||||
const unsigned int open_interval_ = 10;
|
||||
|
@@ -4,8 +4,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <ctime> // std::time_t
|
||||
|
||||
#include <tuple>
|
||||
#include "../common.h"
|
||||
#include "../filename_t.h"
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
@@ -24,27 +25,13 @@ SPDLOG_API std::tm gmtime() noexcept;
|
||||
// eol definition and folder separator for the current os
|
||||
#ifdef _WIN32
|
||||
constexpr static const char *default_eol = "\r\n";
|
||||
constexpr static const filename_t::value_type folder_seps_filename[] = SPDLOG_FILENAME_T("\\/");
|
||||
#else
|
||||
constexpr static const char *default_eol = "\n";
|
||||
constexpr static const filename_t::value_type folder_seps_filename[] = SPDLOG_FILENAME_T("/");
|
||||
#endif
|
||||
|
||||
// fopen_s on non windows for writing
|
||||
SPDLOG_API bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode);
|
||||
|
||||
// Remove filename. return 0 on success
|
||||
SPDLOG_API int remove(const filename_t &filename) noexcept;
|
||||
|
||||
// Remove file if exists. return 0 on success
|
||||
// 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 int rename(const filename_t &filename1, const filename_t &filename2) noexcept;
|
||||
|
||||
// Return if file exists.
|
||||
SPDLOG_API bool path_exists(const filename_t &filename) noexcept;
|
||||
|
||||
// Return file size according to open FILE* object
|
||||
SPDLOG_API size_t filesize(FILE *f);
|
||||
|
||||
@@ -63,8 +50,7 @@ SPDLOG_API size_t thread_id() noexcept;
|
||||
// See https://github.com/gabime/spdlog/issues/609
|
||||
SPDLOG_API void sleep_for_millis(unsigned int milliseconds) noexcept;
|
||||
|
||||
SPDLOG_API std::string filename_to_str(const filename_t &filename);
|
||||
|
||||
// Return pid
|
||||
SPDLOG_API int pid() noexcept;
|
||||
|
||||
// Determine if the terminal supports colors
|
||||
@@ -80,16 +66,6 @@ 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
|
||||
|
||||
// Return directory name from given path or empty string
|
||||
// "abc/file" => "abc"
|
||||
// "abc/" => "abc"
|
||||
// "abc" => ""
|
||||
// "abc///" => "abc//"
|
||||
SPDLOG_API filename_t dir_name(const filename_t &path);
|
||||
|
||||
// Create a dir from the given path.
|
||||
// Return true if succeeded or if this dir already exists.
|
||||
SPDLOG_API bool create_dir(const filename_t &path);
|
||||
|
||||
// non thread safe, cross platform getenv/getenv_s
|
||||
// return empty string if field not found
|
||||
@@ -103,6 +79,52 @@ SPDLOG_API bool fsync(FILE *fp);
|
||||
// Return true on success.
|
||||
SPDLOG_API bool fwrite_bytes(const void *ptr, const size_t n_bytes, FILE *fp);
|
||||
|
||||
//
|
||||
// std::filesystem wrapper functions
|
||||
//
|
||||
|
||||
// Return directory name from given path or empty string
|
||||
// "abc/file" => "abc"
|
||||
// "abc/" => "abc"
|
||||
// "abc" => ""
|
||||
SPDLOG_API filename_t dir_name(const filename_t &path);
|
||||
|
||||
// Create a dir from the given path.
|
||||
// Return true if succeeded or if this dir already exists.
|
||||
SPDLOG_API bool create_dir(const filename_t &path);
|
||||
|
||||
// Remove filename. return true on success
|
||||
SPDLOG_API bool remove(const filename_t &filename);
|
||||
|
||||
// Remove file if exists. return 0 on success
|
||||
// Note: Non atomic (might return failure to delete if concurrently deleted by other process/thread)
|
||||
SPDLOG_API bool remove_if_exists(const filename_t &filename);
|
||||
|
||||
// Rename file. return true on success
|
||||
SPDLOG_API bool rename(const filename_t &filename1, const filename_t &filename2) noexcept;
|
||||
|
||||
// Return if file exists.
|
||||
SPDLOG_API bool path_exists(const filename_t &filename) noexcept;
|
||||
|
||||
|
||||
// Return file path and its extension:
|
||||
//
|
||||
// "mylog.txt" => ("mylog", ".txt")
|
||||
// "mylog" => ("mylog", "")
|
||||
// "mylog." => ("mylog.", "")
|
||||
// "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt")
|
||||
//
|
||||
// the starting dot in filenames is ignored (hidden files):
|
||||
//
|
||||
// ".mylog" => (".mylog". "")
|
||||
// "my_folder/.mylog" => ("my_folder/.mylog", "")
|
||||
// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
|
||||
SPDLOG_API std::tuple<filename_t, filename_t> split_by_extension(const filename_t &fname);
|
||||
|
||||
// Try tp convert filename to string. Return "??" if failed
|
||||
SPDLOG_API std::string filename_to_str(const filename_t &filename);
|
||||
|
||||
|
||||
} // namespace os
|
||||
} // namespace details
|
||||
} // namespace spdlog
|
||||
|
19
include/spdlog/file_event_handlers.h
Normal file
19
include/spdlog/file_event_handlers.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include "./filename_t.h"
|
||||
|
||||
namespace spdlog {
|
||||
struct file_event_handlers {
|
||||
file_event_handlers()
|
||||
: before_open(nullptr),
|
||||
after_open(nullptr),
|
||||
before_close(nullptr),
|
||||
after_close(nullptr) {}
|
||||
|
||||
std::function<void(const filename_t &filename)> before_open;
|
||||
std::function<void(const filename_t &filename, std::FILE *file_stream)> after_open;
|
||||
std::function<void(const filename_t &filename, std::FILE *file_stream)> before_close;
|
||||
std::function<void(const filename_t &filename)> after_close;
|
||||
};
|
||||
} // namespace spdlog
|
18
include/spdlog/filename_t.h
Normal file
18
include/spdlog/filename_t.h
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#ifdef _WIN32
|
||||
// In windows, add L prefix for filename literals (e.g. L"filename.txt")
|
||||
#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
|
||||
|
||||
namespace spdlog {
|
||||
using filename_t = std::filesystem::path;
|
||||
} // namespace spdlog
|
@@ -6,3 +6,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "fmt/format.h"
|
||||
#include "fmt/xchar.h"
|
||||
|
@@ -11,41 +11,43 @@
|
||||
#include <string>
|
||||
|
||||
#include "../common.h"
|
||||
#include "./base_sink.h"
|
||||
#include "../details/circular_q.h"
|
||||
#include "../details/file_helper.h"
|
||||
#include "../details/null_mutex.h"
|
||||
#include "../details/os.h"
|
||||
#include "../details/synchronous_factory.h"
|
||||
#include "./base_sink.h"
|
||||
|
||||
|
||||
namespace spdlog {
|
||||
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 {
|
||||
// Create filename for the form basename.YYYY-MM-DD
|
||||
struct daily_filename_calculator {
|
||||
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_lib::format(SPDLOG_FMT_STRING(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}{}")), basename, now_tm.tm_year + 1900,
|
||||
now_tm.tm_mon + 1, now_tm.tm_mday, ext);
|
||||
std::tie(basename, ext) = details::os::split_by_extension(filename);
|
||||
std::basic_ostringstream<filename_t::value_type> oss;
|
||||
oss << basename.native() << '_' << std::setfill(SPDLOG_FILENAME_T('0')) << std::setw(4) << now_tm.tm_year + 1900 << '-'
|
||||
<< std::setw(2) << now_tm.tm_mon + 1 << '-' << std::setw(2) << now_tm.tm_mday << ext.native();
|
||||
return oss.str();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* 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)"
|
||||
*
|
||||
* std::make_shared<spdlog::sinks::daily_file_format_sink_mt>("myapp-%Y-%m-%d:%H:%M:%S.log", hour, minute);
|
||||
* or
|
||||
* 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 &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());
|
||||
return stream.str();
|
||||
}
|
||||
@@ -164,7 +166,7 @@ private:
|
||||
if (filenames_q_.full()) {
|
||||
auto old_filename = std::move(filenames_q_.front());
|
||||
filenames_q_.pop_front();
|
||||
bool ok = remove_if_exists(old_filename) == 0;
|
||||
bool ok = remove_if_exists(old_filename);
|
||||
if (!ok) {
|
||||
filenames_q_.push_back(std::move(current_file));
|
||||
throw_spdlog_ex("Failed removing daily file " + filename_to_str(old_filename), errno);
|
||||
|
@@ -22,15 +22,17 @@ namespace spdlog {
|
||||
namespace sinks {
|
||||
|
||||
/*
|
||||
* Generator of Hourly log file names in format basename.YYYY-MM-DD-HH.ext
|
||||
* 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_lib::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);
|
||||
std::tie(basename, ext) = details::os::split_by_extension(filename);
|
||||
std::basic_ostringstream<filename_t::value_type> oss;
|
||||
oss << basename.native() << '_' << std::setfill(SPDLOG_FILENAME_T('0')) << std::setw(4) << now_tm.tm_year + 1900 << '-'
|
||||
<< std::setw(2) << now_tm.tm_mon + 1 << '-' << std::setw(2) << now_tm.tm_mday << '_' << 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
|
||||
// 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_;
|
||||
std::size_t max_size_;
|
||||
|
Reference in New Issue
Block a user