auto create log dir

This commit is contained in:
gabime 2019-10-20 17:40:56 +03:00
parent 4858d7e454
commit 9b7812a0f2
18 changed files with 141 additions and 64 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -29,9 +29,16 @@ SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate)
{ {
close(); close();
auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab"); auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
auto folder_name = os::dir_name(fname);
_filename = fname; _filename = fname;
for (int tries = 0; tries < open_tries; ++tries) for (int tries = 0; tries < open_tries; ++tries)
{ {
if (!folder_name.empty())
{
os::create_dir(folder_name);
}
if (!os::fopen_s(&fd_, fname, mode)) if (!os::fopen_s(&fd_, fname, mode))
{ {
return; return;
@ -129,5 +136,6 @@ SPDLOG_INLINE std::tuple<filename_t, filename_t> file_helper::split_by_extension
// finally - return a valid base and extension tuple // finally - return a valid base and extension tuple
return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index)); return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index));
} }
} // namespace details } // namespace details
} // namespace spdlog } // namespace spdlog

View File

@ -16,6 +16,7 @@
#include <cstring> #include <cstring>
#include <ctime> #include <ctime>
#include <string> #include <string>
#include <sstream>
#include <thread> #include <thread>
#include <array> #include <array>
#include <sys/stat.h> #include <sys/stat.h>
@ -196,7 +197,7 @@ SPDLOG_INLINE bool file_exists(const filename_t &filename) SPDLOG_NOEXCEPT
#else #else
auto attribs = GetFileAttributesA(filename.c_str()); auto attribs = GetFileAttributesA(filename.c_str());
#endif #endif
return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY)); return attribs != INVALID_FILE_ATTRIBUTES;
#else // common linux/unix all have the stat system call #else // common linux/unix all have the stat system call
struct stat buffer; struct stat buffer;
return (::stat(filename.c_str(), &buffer) == 0); return (::stat(filename.c_str(), &buffer) == 0);
@ -460,6 +461,72 @@ SPDLOG_INLINE void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target)
} }
#endif // (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32) #endif // (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)
// return true on success
SPDLOG_INLINE bool mkdir_(const filename_t &path)
{
#ifdef _WIN32
#ifdef SPDLOG_WCHAR_FILENAMES
return ::_wmkdir(path.c_str()) == 0;
#else
return ::_mkdir(path.c_str()) == 0;
#endif
#else
return ::mkdir(path.c_str(), mode_t(0755)) == 0;
#endif
}
// create the given directory - and all directories leading to it
// return true on success
SPDLOG_INLINE bool create_dir(filename_t path)
{
if (file_exists(path))
{
return true;
}
using char_type = filename_t::value_type;
std::basic_istringstream<char_type> istream(path);
filename_t token;
filename_t cur_dir;
char_type sep = '/';
#ifdef _WIN32
// support forward slash in windows
std::replace(path.begin(), path.end(), char_type('\\'), sep);
#endif
while (std::getline(istream, token, sep))
{
if (!token.empty())
{
cur_dir += token;
if (!file_exists(cur_dir) && !mkdir_(cur_dir))
{
return false;
}
}
cur_dir += sep;
}
return true;
}
// Return directory name from given path or empty string
// "abc/file" => "abc"
// "abc/" => "abc"
// "abc" => ""
// "abc///" => "abc"
SPDLOG_INLINE filename_t dir_name(filename_t path)
{
using char_type = filename_t::value_type;
char_type sep = '/';
#ifdef _WIN32
// support forward slash in windows
std::replace(path.begin(), path.end(), char_type('\\'), sep);
#endif
auto pos = path.find_last_of(sep);
return pos != filename_t::npos ? path.substr(0, pos) : filename_t{};
}
} // namespace os } // namespace os
} // namespace details } // namespace details
} // namespace spdlog } // namespace spdlog

View File

@ -89,6 +89,17 @@ bool in_terminal(FILE *file) SPDLOG_NOEXCEPT;
void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target); void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target);
#endif #endif
// Return directory name from given path or empty string
// "abc/file" => "abc"
// "abc/" => "abc"
// "abc" => ""
// "abc///" => "abc"
filename_t dir_name(filename_t path);
// Create a dir from the given path.
// Return true if succeeded or if this dir already exists.
bool create_dir(filename_t path);
} // namespace os } // namespace os
} // namespace details } // namespace details
} // namespace spdlog } // namespace spdlog

View File

@ -25,7 +25,8 @@ set(SPDLOG_UTESTS_SOURCES
test_fmt_helper.cpp test_fmt_helper.cpp
test_stdout_api.cpp test_stdout_api.cpp
test_dup_filter.cpp test_dup_filter.cpp
test_backtrace.cpp) test_backtrace.cpp
test_create_dir.cpp)
if(NOT SPDLOG_NO_EXCEPTIONS) if(NOT SPDLOG_NO_EXCEPTIONS)
list(APPEND SPDLOG_UTESTS_SOURCES test_errors.cpp) list(APPEND SPDLOG_UTESTS_SOURCES test_errors.cpp)
@ -35,7 +36,6 @@ if(systemd_FOUND)
list(APPEND SPDLOG_UTESTS_SOURCES test_systemd.cpp) list(APPEND SPDLOG_UTESTS_SOURCES test_systemd.cpp)
endif() endif()
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs")
enable_testing() enable_testing()
# The compiled library tests # The compiled library tests

View File

@ -35,7 +35,6 @@ if systemd_dep.found()
global_test_deps += systemd_dep global_test_deps += systemd_dep
endif endif
run_command('mkdir', 'logs')
# -------------------------------------- # --------------------------------------
# --- Build the test executables --- # --- Build the test executables ---
# -------------------------------------- # --------------------------------------
@ -49,5 +48,3 @@ foreach i : test_matrix
test_exe = executable(i[0], test_sources, dependencies: global_test_deps + [i[1]]) test_exe = executable(i[0], test_sources, dependencies: global_test_deps + [i[1]])
test('test_' + i[0], test_exe) test('test_' + i[0], test_exe)
endforeach endforeach
run_command(find_program('mkdir'), meson.current_build_dir() + '/logs')

View File

@ -157,7 +157,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 = "logs/async_test.log"; std::string filename = "test_logs/async_test.log";
{ {
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true); auto 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);
@ -179,7 +179,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 = "logs/async_test.log"; std::string filename = "test_logs/async_test.log";
{ {
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true); auto 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);

27
tests/test_create_dir.cpp Normal file
View File

@ -0,0 +1,27 @@
/*
* This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE
*/
#include "includes.h"
using spdlog::details::os::create_dir;
using spdlog::details::os::file_exists;
void test_create_dir(const char *path, const char *normalized_path)
{
auto rv = create_dir(path);
REQUIRE(rv == true);
REQUIRE(file_exists(normalized_path));
}
#include "spdlog/sinks/stdout_color_sinks.h"
TEST_CASE("create_dir", "[create_dir]")
{
prepare_logdir();
test_create_dir("test_logs/dir1/dir1", "test_logs/dir1/dir1");
test_create_dir("test_logs/dir1///dir2", "test_logs/dir1/dir2");
test_create_dir("./test_logs/dir1/dir3", "test_logs/dir1/dir3");
test_create_dir("test_logs/../test_logs/dir1/dir4", "test_logs/dir1/dir4");
test_create_dir("./test_logs/dir1/dir2/dir99/../dir23", "test_logs/dir1/dir2/dir23");
spdlog::drop("test-create-dir");
}

View File

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

View File

@ -26,7 +26,7 @@ protected:
TEST_CASE("default_error_handler", "[errors]]") TEST_CASE("default_error_handler", "[errors]]")
{ {
prepare_logdir(); prepare_logdir();
std::string filename = "logs/simple_log.txt"; std::string filename = "test_logs/simple_log.txt";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("test-error", filename, true); auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("test-error", filename, true);
logger->set_pattern("%v"); logger->set_pattern("%v");
@ -43,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 = "logs/simple_log.txt"; std::string filename = "test_logs/simple_log.txt";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename, true); 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(); });
@ -75,15 +75,15 @@ 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 = "logs/simple_async_log.txt"; std::string filename = "test_logs/simple_async_log.txt";
{ {
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);
logger->set_error_handler([=](const std::string &) { logger->set_error_handler([=](const std::string &) {
std::ofstream ofs("logs/custom_err.txt"); std::ofstream ofs("test_logs/custom_err.txt");
if (!ofs) if (!ofs)
{ {
throw std::runtime_error("Failed open logs/custom_err.txt"); throw std::runtime_error("Failed open test_logs/custom_err.txt");
} }
ofs << err_msg; ofs << err_msg;
}); });
@ -94,7 +94,7 @@ TEST_CASE("async_error_handler", "[errors]]")
} }
spdlog::init_thread_pool(128, 1); spdlog::init_thread_pool(128, 1);
REQUIRE(count_lines(filename) == 2); REQUIRE(count_lines(filename) == 2);
REQUIRE(file_contents("logs/custom_err.txt") == err_msg); REQUIRE(file_contents("test_logs/custom_err.txt") == err_msg);
} }
// Make sure async error handler is executed // Make sure async error handler is executed
@ -103,12 +103,13 @@ 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::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 &) {
std::ofstream ofs("logs/custom_err2.txt"); std::ofstream ofs("test_logs/custom_err2.txt");
if (!ofs) if (!ofs)
throw std::runtime_error("Failed open logs/custom_err2.txt"); throw std::runtime_error("Failed open test_logs/custom_err2.txt");
ofs << err_msg; ofs << err_msg;
}); });
logger->info("Hello failure"); logger->info("Hello failure");
@ -116,5 +117,5 @@ TEST_CASE("async_error_handler2", "[errors]]")
} }
spdlog::init_thread_pool(128, 1); spdlog::init_thread_pool(128, 1);
REQUIRE(file_contents("logs/custom_err2.txt") == err_msg); REQUIRE(file_contents("test_logs/custom_err2.txt") == err_msg);
} }

View File

@ -6,7 +6,7 @@
using spdlog::details::file_helper; using spdlog::details::file_helper;
using spdlog::details::log_msg; using spdlog::details::log_msg;
static const std::string target_filename = "logs/file_helper_test.txt"; static const std::string target_filename = "test_logs/file_helper_test.txt";
static void write_with_helper(file_helper &helper, size_t howmany) static void write_with_helper(file_helper &helper, size_t howmany)
{ {

View File

@ -6,7 +6,7 @@
TEST_CASE("simple_file_logger", "[simple_logger]]") TEST_CASE("simple_file_logger", "[simple_logger]]")
{ {
prepare_logdir(); prepare_logdir();
std::string filename = "logs/simple_log"; std::string filename = "test_logs/simple_log";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename); auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
logger->set_pattern("%v"); logger->set_pattern("%v");
@ -22,7 +22,7 @@ TEST_CASE("simple_file_logger", "[simple_logger]]")
TEST_CASE("flush_on", "[flush_on]]") TEST_CASE("flush_on", "[flush_on]]")
{ {
prepare_logdir(); prepare_logdir();
std::string filename = "logs/simple_log"; std::string filename = "test_logs/simple_log";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename); auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
logger->set_pattern("%v"); logger->set_pattern("%v");
@ -42,7 +42,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 = "logs/rotating_log"; std::string basename = "test_logs/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)
@ -59,7 +59,7 @@ 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 = "logs/rotating_log"; std::string basename = "test_logs/rotating_log";
{ {
// make an initial logger to create the first output file // make an initial logger to create the first output file

View File

@ -12,7 +12,7 @@ TEST_CASE("debug and trace w/o format string", "[macros]]")
{ {
prepare_logdir(); prepare_logdir();
std::string filename = "logs/simple_log"; std::string filename = "test_logs/simple_log";
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename); auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename);
logger->set_pattern("%v"); logger->set_pattern("%v");

View File

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