Updated load_env_levels() and load_argv_levels() to return level map

pull/2143/head
gabime 4 years ago
parent 11a98a8cb4
commit c1223a6f04

@ -123,7 +123,7 @@ int main(int argc, char *argv[])
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 logger = std::make_shared<async_logger>("async_logger", std::move(file_sink), std::move(tp), async_overflow_policy::block); auto logger = std::make_shared<async_logger>("async_logger", std::move(file_sink), std::move(tp), async_overflow_policy::block);
bench_mt(howmany, std::move(logger), threads); bench_mt(howmany, std::move(logger), threads);
// verify_file(filename, howmany); //verify_file(filename, howmany);
} }
spdlog::info(""); spdlog::info("");

@ -115,9 +115,18 @@ void daily_example()
#include "spdlog/cfg/env.h" #include "spdlog/cfg/env.h"
void load_levels_example() void load_levels_example()
{ {
// Set the log level to "info" and mylogger to "trace": // Set the default logger level to "info" and mylogger to "trace":
// SPDLOG_LEVEL=info,mylogger=trace && ./example // SPDLOG_LEVEL=info,mylogger=trace && ./example
spdlog::cfg::load_env_levels(); auto levels = spdlog::cfg::load_env_levels();
auto it = levels.find(spdlog::default_logger()->name());
if(it != levels.end())
spdlog::default_logger()->set_level(it->second);
auto my_logger = spdlog::basic_logger_mt("my_logger", "logs/my-logger.txt");
it = levels.find(my_logger->name());
if(it != levels.end())
my_logger ->set_level(it->second);
// or from command line: // or from command line:
// ./example SPDLOG_LEVEL=info,mylogger=trace // ./example SPDLOG_LEVEL=info,mylogger=trace
// #include "spdlog/cfg/argv.h" // for loading levels from argv // #include "spdlog/cfg/argv.h" // for loading levels from argv

@ -20,7 +20,7 @@ namespace spdlog {
namespace cfg { namespace cfg {
// search for SPDLOG_LEVEL= in the args and use it to init the levels // search for SPDLOG_LEVEL= in the args and use it to init the levels
inline void load_argv_levels(int argc, const char **argv) inline level_map load_argv_levels(int argc, const char **argv)
{ {
const std::string spdlog_level_prefix = "SPDLOG_LEVEL="; const std::string spdlog_level_prefix = "SPDLOG_LEVEL=";
for (int i = 1; i < argc; i++) for (int i = 1; i < argc; i++)
@ -29,14 +29,17 @@ inline void load_argv_levels(int argc, const char **argv)
if (arg.find(spdlog_level_prefix) == 0) if (arg.find(spdlog_level_prefix) == 0)
{ {
auto levels_string = arg.substr(spdlog_level_prefix.size()); auto levels_string = arg.substr(spdlog_level_prefix.size());
helpers::load_levels(levels_string); return helpers::load_levels(levels_string);
} }
} }
// the "SPDLOG_LEVEL=" prefix was not found in any of the argv items
return std::unordered_map<std::string, level::level_enum>{};
} }
inline void load_argv_levels(int argc, char **argv) inline level_map load_argv_levels(int argc, char **argv)
{ {
load_argv_levels(argc, const_cast<const char **>(argv)); return load_argv_levels(argc, const_cast<const char **>(argv));
} }
} // namespace cfg } // namespace cfg

@ -24,13 +24,11 @@
namespace spdlog { namespace spdlog {
namespace cfg { namespace cfg {
inline void load_env_levels()
inline std::unordered_map<std::string, level::level_enum> load_env_levels()
{ {
auto env_val = details::os::getenv("SPDLOG_LEVEL"); auto env_val = details::os::getenv("SPDLOG_LEVEL");
if (!env_val.empty()) return helpers::load_levels(env_val);
{
helpers::load_levels(env_val);
}
} }
} // namespace cfg } // namespace cfg

@ -78,17 +78,15 @@ inline std::unordered_map<std::string, std::string> extract_key_vals_(const std:
return rv; return rv;
} }
SPDLOG_INLINE void load_levels(const std::string &input) SPDLOG_INLINE std::unordered_map<std::string, level::level_enum> load_levels(const std::string &input)
{ {
std::unordered_map<std::string, level::level_enum> levels;
if (input.empty() || input.size() > 512) if (input.empty() || input.size() > 512)
{ {
return; return levels;
} }
auto key_vals = extract_key_vals_(input); auto key_vals = extract_key_vals_(input);
std::unordered_map<std::string, level::level_enum> levels;
level::level_enum global_level = level::info;
bool global_level_found = false;
for (auto &name_level : key_vals) for (auto &name_level : key_vals)
{ {
@ -100,19 +98,9 @@ SPDLOG_INLINE void load_levels(const std::string &input)
{ {
continue; continue;
} }
if (logger_name.empty()) // no logger name indicate global level levels[logger_name] = level;
{
global_level_found = true;
global_level = level;
}
else
{
levels[logger_name] = level;
}
} }
return levels;
// TODO what to do here with registry?
//details::registry::instance().set_levels(std::move(levels), global_level_found ? &global_level : nullptr);
} }
} // namespace helpers } // namespace helpers

@ -8,6 +8,9 @@
namespace spdlog { namespace spdlog {
namespace cfg { namespace cfg {
using level_map = std::unordered_map<std::string, level::level_enum>;
namespace helpers { namespace helpers {
// //
// Init levels from given string // Init levels from given string
@ -18,7 +21,7 @@ namespace helpers {
// turn off all logging except for logger1: "off,logger1=debug" // turn off all logging except for logger1: "off,logger1=debug"
// turn off all logging except for logger1 and logger2: "off,logger1=debug,logger2=info" // turn off all logging except for logger1 and logger2: "off,logger1=debug,logger2=info"
// //
SPDLOG_API void load_levels(const std::string &txt); SPDLOG_API level_map load_levels(const std::string &txt);
} // namespace helpers } // namespace helpers
} // namespace cfg } // namespace cfg

@ -29,7 +29,7 @@ set(SPDLOG_UTESTS_SOURCES
test_fmt_helper.cpp test_fmt_helper.cpp
test_stdout_api.cpp test_stdout_api.cpp
test_create_dir.cpp test_create_dir.cpp
# test_cfg.cpp TODO test_cfg.cpp
test_time_point.cpp test_time_point.cpp
test_stopwatch.cpp) test_stopwatch.cpp)

@ -11,173 +11,139 @@ using spdlog::sinks::test_sink_st;
TEST_CASE("env", "[cfg]") TEST_CASE("env", "[cfg]")
{ {
spdlog::drop("l1");
auto l1 = spdlog::create<test_sink_st>("l1");
#ifdef CATCH_PLATFORM_WINDOWS #ifdef CATCH_PLATFORM_WINDOWS
_putenv_s("SPDLOG_LEVEL", "l1=warn"); _putenv_s("SPDLOG_LEVEL", "warn");
#else #else
setenv("SPDLOG_LEVEL", "l1=warn", 1); setenv("SPDLOG_LEVEL", "warn", 1);
#endif #endif
load_env_levels(); auto levels = load_env_levels();
REQUIRE(l1->level() == spdlog::level::warn); auto it = levels.find(spdlog::default_logger()->name());
spdlog::set_default_logger(spdlog::create<test_sink_st>("cfg-default")); REQUIRE(levels == spdlog::cfg::level_map {{"", spdlog::level::warn}});
REQUIRE(spdlog::default_logger()->level() == spdlog::level::info);
} }
TEST_CASE("argv1", "[cfg]") TEST_CASE("argv1", "[cfg]")
{ {
spdlog::drop("l1");
const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=warn"}; const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=warn"};
load_argv_levels(2, argv); auto levels= load_argv_levels(sizeof(argv)/sizeof (const char*), argv);
auto l1 = spdlog::create<spdlog::sinks::test_sink_st>("l1"); REQUIRE(levels == spdlog::cfg::level_map {{"l1", spdlog::level::warn}});
REQUIRE(l1->level() == spdlog::level::warn);
REQUIRE(spdlog::default_logger()->level() == spdlog::level::info);
} }
TEST_CASE("argv2", "[cfg]") TEST_CASE("argv2", "[cfg]")
{ {
spdlog::drop("l1");
const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=warn,trace"}; const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=warn,trace"};
load_argv_levels(2, argv); auto levels = load_argv_levels(sizeof(argv)/sizeof (const char*), argv);
auto l1 = spdlog::create<test_sink_st>("l1"); REQUIRE(levels == spdlog::cfg::level_map {
REQUIRE(l1->level() == spdlog::level::warn); {"l1", spdlog::level::warn},
REQUIRE(spdlog::default_logger()->level() == spdlog::level::trace); {"", spdlog::level::trace}
});
} }
TEST_CASE("argv3", "[cfg]") TEST_CASE("argv3", "[cfg]")
{ {
spdlog::set_level(spdlog::level::trace);
spdlog::drop("l1");
const char *argv[] = {"ignore", "SPDLOG_LEVEL=junk_name=warn"}; const char *argv[] = {"ignore", "SPDLOG_LEVEL=junk_name=warn"};
load_argv_levels(2, argv); auto levels= load_argv_levels(sizeof(argv)/sizeof (const char*), argv);
auto l1 = spdlog::create<test_sink_st>("l1"); REQUIRE(levels == spdlog::cfg::level_map {{"junk_name", spdlog::level::warn}});
REQUIRE(l1->level() == spdlog::level::trace);
REQUIRE(spdlog::default_logger()->level() == spdlog::level::trace);
} }
TEST_CASE("argv4", "[cfg]") TEST_CASE("argv4", "[cfg]")
{ {
spdlog::set_level(spdlog::level::info);
spdlog::drop("l1");
const char *argv[] = {"ignore", "SPDLOG_LEVEL=junk"}; const char *argv[] = {"ignore", "SPDLOG_LEVEL=junk"};
load_argv_levels(2, argv); auto levels= load_argv_levels(sizeof(argv)/sizeof (const char*), argv);
auto l1 = spdlog::create<test_sink_st>("l1"); REQUIRE(levels.empty());
REQUIRE(l1->level() == spdlog::level::info);
} }
TEST_CASE("argv5", "[cfg]") TEST_CASE("argv5", "[cfg]")
{ {
spdlog::set_level(spdlog::level::info);
spdlog::drop("l1");
const char *argv[] = {"ignore", "ignore", "SPDLOG_LEVEL=l1=warn,trace"}; const char *argv[] = {"ignore", "ignore", "SPDLOG_LEVEL=l1=warn,trace"};
load_argv_levels(3, argv); auto levels= load_argv_levels(sizeof(argv)/sizeof (const char*), argv);
auto l1 = spdlog::create<test_sink_st>("l1"); REQUIRE(levels == spdlog::cfg::level_map {
REQUIRE(l1->level() == spdlog::level::warn); {"l1", spdlog::level::warn},
REQUIRE(spdlog::default_logger()->level() == spdlog::level::trace); {"", spdlog::level::trace}
spdlog::set_level(spdlog::level::info); });
} }
TEST_CASE("argv6", "[cfg]") TEST_CASE("argv6", "[cfg]")
{ {
spdlog::set_level(spdlog::level::err); const char *argv[] = {"SPDLOG_LEVEL=info"};
const char *argv[] = {""}; auto levels= load_argv_levels(sizeof(argv)/sizeof (const char*), argv);
load_argv_levels(1, argv); REQUIRE(levels.empty());
REQUIRE(spdlog::default_logger()->level() == spdlog::level::err);
spdlog::set_level(spdlog::level::info);
} }
TEST_CASE("argv7", "[cfg]") TEST_CASE("argv7", "[cfg]")
{ {
spdlog::set_level(spdlog::level::err);
const char *argv[] = {""};
load_argv_levels(0, argv);
REQUIRE(spdlog::default_logger()->level() == spdlog::level::err);
spdlog::set_level(spdlog::level::info);
}
TEST_CASE("level-not-set-test1", "[cfg]")
{
spdlog::drop("l1");
const char *argv[] = {"ignore", ""}; const char *argv[] = {"ignore", ""};
load_argv_levels(2, argv); auto levels= load_argv_levels(sizeof(argv)/sizeof (const char*), argv);
auto l1 = spdlog::create<spdlog::sinks::test_sink_st>("l1"); REQUIRE(levels.empty());
l1->set_level(spdlog::level::trace);
REQUIRE(l1->level() == spdlog::level::trace);
REQUIRE(spdlog::default_logger()->level() == spdlog::level::info);
} }
TEST_CASE("level-not-set-test2", "[cfg]") TEST_CASE("argv8", "[cfg]")
{ {
spdlog::drop("l1"); const char *argv[] = {"ignore"};
spdlog::drop("l2"); auto levels= load_argv_levels(sizeof(argv)/sizeof (const char*), argv);
const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=trace"}; REQUIRE(levels.empty());
}
auto l1 = spdlog::create<spdlog::sinks::test_sink_st>("l1");
l1->set_level(spdlog::level::warn);
auto l2 = spdlog::create<spdlog::sinks::test_sink_st>("l2");
l2->set_level(spdlog::level::warn);
load_argv_levels(2, argv);
REQUIRE(l1->level() == spdlog::level::trace); TEST_CASE("argv9", "[cfg]")
REQUIRE(l2->level() == spdlog::level::warn); {
REQUIRE(spdlog::default_logger()->level() == spdlog::level::info); const char *argv[] = {"ignore", "arg1"};
auto levels= load_argv_levels(sizeof(argv)/sizeof (const char*), argv);
REQUIRE(levels.empty());
} }
TEST_CASE("argv10", "[cfg]")
TEST_CASE("level-not-set-test3", "[cfg]")
{ {
spdlog::drop("l1"); const char *argv[] = {"ignore", "junk", "SPDLOG_LEVEL=info"};
spdlog::drop("l2"); auto levels= load_argv_levels(sizeof(argv)/sizeof (const char*), argv);
const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=trace"}; REQUIRE(levels == spdlog::cfg::level_map {{"", spdlog::level::info}});
load_argv_levels(2, argv);
auto l1 = spdlog::create<spdlog::sinks::test_sink_st>("l1");
auto l2 = spdlog::create<spdlog::sinks::test_sink_st>("l2");
REQUIRE(l1->level() == spdlog::level::trace);
REQUIRE(l2->level() == spdlog::level::info);
REQUIRE(spdlog::default_logger()->level() == spdlog::level::info);
} }
TEST_CASE("level-not-set-test4", "[cfg]") TEST_CASE("argv11", "[cfg]")
{ {
spdlog::drop("l1"); const char *argv[] = {};
spdlog::drop("l2"); auto levels= load_argv_levels(0, argv);
const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=trace,warn"}; REQUIRE(levels.empty());
load_argv_levels(2, argv);
auto l1 = spdlog::create<spdlog::sinks::test_sink_st>("l1");
auto l2 = spdlog::create<spdlog::sinks::test_sink_st>("l2");
REQUIRE(l1->level() == spdlog::level::trace);
REQUIRE(l2->level() == spdlog::level::warn);
REQUIRE(spdlog::default_logger()->level() == spdlog::level::warn);
} }
TEST_CASE("level-not-set-test5", "[cfg]") TEST_CASE("argv12", "[cfg]")
{ {
spdlog::drop("l1"); const char *argv[] = {"ignore", "junk", "SPDLOG_LEVEL=info,l1=debug,l2=warn,l3=off"};
spdlog::drop("l2"); auto levels= load_argv_levels(sizeof(argv)/sizeof (const char*), argv);
const char *argv[] = {"ignore", "SPDLOG_LEVEL=l1=junk,warn"}; REQUIRE(levels == spdlog::cfg::level_map {
{"", spdlog::level::info},
load_argv_levels(2, argv); {"l1", spdlog::level::debug},
{"l2", spdlog::level::warn},
{"l3", spdlog::level::off}
});
}
auto l1 = spdlog::create<spdlog::sinks::test_sink_st>("l1"); TEST_CASE("argv13", "[cfg]")
auto l2 = spdlog::create<spdlog::sinks::test_sink_st>("l2"); {
//test that only first SPDLOG_LEVEL is handled
const char *argv[] = {"ignore", "junk", "SPDLOG_LEVEL=info,l1=debug,l2=warn,l3=off", "SPDLOG_LEVEL=off"};
auto levels= load_argv_levels(sizeof(argv)/sizeof (const char*), argv);
REQUIRE(levels == spdlog::cfg::level_map {
{"", spdlog::level::info},
{"l1", spdlog::level::debug},
{"l2", spdlog::level::warn},
{"l3", spdlog::level::off}
});
}
REQUIRE(l1->level() == spdlog::level::warn); TEST_CASE("argv14", "[cfg]")
REQUIRE(l2->level() == spdlog::level::warn); {
REQUIRE(spdlog::default_logger()->level() == spdlog::level::warn); //test that only first SPDLOG_LEVEL is handled
const char *argv[] = {"ignore", "SPDLOG_LEVEL="};
auto levels= load_argv_levels(sizeof(argv)/sizeof (const char*), argv);
REQUIRE(levels.empty());
} }
TEST_CASE("restore-to-default", "[cfg]") TEST_CASE("argv15", "[cfg]")
{ {
spdlog::drop("l1"); //test that only first SPDLOG_LEVEL is handled
spdlog::drop("l2"); const char *argv[] = {"ignore", "SPDLOG_LEVEL=info,l1=junk,l2=debug"};
const char *argv[] = {"ignore", "SPDLOG_LEVEL=info"}; auto levels= load_argv_levels(sizeof(argv)/sizeof (const char*), argv);
load_argv_levels(2, argv); REQUIRE(levels == spdlog::cfg::level_map {
REQUIRE(spdlog::default_logger()->level() == spdlog::level::info); {"", spdlog::level::info},
{"l2", spdlog::level::debug},
});
} }

Loading…
Cancel
Save