Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use std filesystem #3284

Merged
merged 23 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ endif()
option(SPDLOG_PREVENT_CHILD_FD "Prevent from child processes to inherit log file descriptors" OFF)
option(SPDLOG_NO_THREAD_ID "prevent spdlog from querying the thread id on each log call if thread id is not needed" OFF)
option(SPDLOG_DISABLE_DEFAULT_LOGGER "Disable default logger creation" OFF)
option(SPDLOG_NO_TLS "Disable thread local storage" OFF)

# clang-tidy
option(SPDLOG_TIDY "run clang-tidy" OFF)
Expand Down Expand Up @@ -198,6 +199,7 @@ set(SPDLOG_SRCS
"src/spdlog.cpp"
"src/cfg/helpers.cpp"
"src/details/file_helper.cpp"
"src/details/os_filesystem.cpp"
"src/details/log_msg.cpp"
"src/details/log_msg_buffer.cpp"
"src/details/periodic_worker.cpp"
Expand Down Expand Up @@ -307,8 +309,13 @@ endif()
# ---------------------------------------------------------------------------------------
# spdlog private defines according to the options
# ---------------------------------------------------------------------------------------
foreach(SPDLOG_OPTION SPDLOG_CLOCK_COARSE SPDLOG_PREVENT_CHILD_FD SPDLOG_NO_THREAD_ID SPDLOG_DISABLE_DEFAULT_LOGGER
SPDLOG_FWRITE_UNLOCKED)
foreach(SPDLOG_OPTION
SPDLOG_CLOCK_COARSE
SPDLOG_PREVENT_CHILD_FD
SPDLOG_NO_THREAD_ID
SPDLOG_DISABLE_DEFAULT_LOGGER
SPDLOG_NO_TLS
SPDLOG_FWRITE_UNLOCKED)
if(${SPDLOG_OPTION})
target_compile_definitions(spdlog PRIVATE ${SPDLOG_OPTION})
endif()
Expand Down
14 changes: 7 additions & 7 deletions example/example.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//
//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)

Expand Down Expand Up @@ -299,16 +299,16 @@ void custom_flags_example() {
void file_events_example() {
// pass the spdlog::file_event_handlers to file sinks for open/close log file notifications
spdlog::file_event_handlers handlers;
handlers.before_open = [](spdlog::filename_t filename) { spdlog::info("Before opening {}", filename); };
handlers.after_open = [](spdlog::filename_t filename, std::FILE *fstream) {
spdlog::info("After opening {}", filename);
handlers.before_open = [](spdlog::filename_t) { spdlog::info("Before opening logfile"); };
handlers.after_open = [](spdlog::filename_t, std::FILE *fstream) {
spdlog::info("After opening logfile");
fputs("After opening\n", fstream);
};
handlers.before_close = [](spdlog::filename_t filename, std::FILE *fstream) {
spdlog::info("Before closing {}", filename);
handlers.before_close = [](spdlog::filename_t, std::FILE *fstream) {
spdlog::info("Before closing logfile");
fputs("Before closing\n", fstream);
};
handlers.after_close = [](spdlog::filename_t filename) { spdlog::info("After closing {}", filename); };
handlers.after_close = [](spdlog::filename_t) { spdlog::info("After closing logfile"); };
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);
my_logger.info("Some log line");
Expand Down
39 changes: 3 additions & 36 deletions include/spdlog/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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>;
Expand All @@ -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
Expand Down Expand Up @@ -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));
}

Expand Down Expand Up @@ -140,33 +136,4 @@ class SPDLOG_API spdlog_ex : public std::exception {
[[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
16 changes: 1 addition & 15 deletions include/spdlog/details/file_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <tuple>

#include "../common.h"
#include "../file_event_handlers.h"

namespace spdlog {
namespace details {
Expand All @@ -32,21 +33,6 @@ class SPDLOG_API file_helper {
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;
Expand Down
76 changes: 49 additions & 27 deletions include/spdlog/details/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
#pragma once

#include <ctime> // std::time_t

#include <tuple>
#include "../common.h"
#include "../filename_t.h"

namespace spdlog {
namespace details {
Expand All @@ -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);

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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 changes: 19 additions & 0 deletions include/spdlog/file_event_handlers.h
Original file line number Diff line number Diff line change
@@ -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 changes: 18 additions & 0 deletions include/spdlog/filename_t.h
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions include/spdlog/fmt/fmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
#pragma once

#include "fmt/format.h"
#include "fmt/xchar.h"
28 changes: 15 additions & 13 deletions include/spdlog/sinks/daily_file_sink.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down Expand Up @@ -164,7 +166,7 @@ class daily_file_sink final : public base_sink<Mutex> {
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);
Expand Down
Loading
Loading