Hide spdlog

This commit is contained in:
Johan Mabille 2022-03-25 18:08:43 +01:00
parent bdb9f1325a
commit 0fb7d5efb2
16 changed files with 282 additions and 221 deletions

View File

@ -16,8 +16,6 @@
#include <yaml-cpp/yaml.h>
#include "spdlog/common.h"
#include <functional>
@ -64,8 +62,6 @@ namespace YAML
{
static Node encode(const mamba::RCConfigLevel& rhs)
{
using namespace spdlog::level;
switch (rhs)
{
case mamba::RCConfigLevel::kHomeDir:

View File

@ -5,9 +5,9 @@
#include <string>
#include <vector>
#include "spdlog/spdlog.h"
#include <yaml-cpp/yaml.h>
#include "mamba/core/common_types.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/mamba_fs.hpp"
@ -350,24 +350,25 @@ namespace YAML
};
template <>
struct convert<spdlog::level::level_enum>
struct convert<mamba::log_level>
{
static Node encode(const spdlog::level::level_enum& rhs)
{
using namespace spdlog::level;
private:
static inline const std::array<std::string, 7> log_level_names
= { "trace", "debug", "info", "warning", "error", "critical", "off" };
return Node(to_string_view(rhs).data());
public:
static Node encode(const mamba::log_level& rhs)
{
return Node(log_level_names[static_cast<size_t>(rhs)]);
}
static bool decode(const Node& node, spdlog::level::level_enum& rhs)
static bool decode(const Node& node, mamba::log_level& rhs)
{
using namespace spdlog::level;
auto name = node.as<std::string>();
auto it = std::find(std::begin(level_string_views), std::end(level_string_views), name);
if (it != std::end(level_string_views))
auto it = std::find(log_level_names.begin(), log_level_names.end(), name);
if (it != log_level_names.end())
{
rhs = static_cast<level_enum>(it - std::begin(level_string_views));
rhs = static_cast<mamba::log_level>(it - log_level_names.begin());
return true;
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2019, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.
#ifndef MAMBA_CORE_COMMON_TYPES_HPP
#define MAMBA_CORE_COMMON_TYPES_HPP
namespace mamba
{
enum class log_level
{
trace,
debug,
info,
warn,
err,
critical,
off
};
}
#endif

View File

@ -7,10 +7,9 @@
#ifndef MAMBA_CORE_CONTEXT_HPP
#define MAMBA_CORE_CONTEXT_HPP
#include "mamba/core/common_types.hpp"
#include "mamba/core/mamba_fs.hpp"
#include "spdlog/spdlog.h"
#include <map>
#include <string>
#include <vector>
@ -126,12 +125,11 @@ namespace mamba
int verbosity = 0;
void set_verbosity(int lvl);
void set_log_level(const spdlog::level::level_enum& level);
void set_log_level(log_level level);
spdlog::level::level_enum log_level = spdlog::level::level_enum::warn;
log_level logging_level = log_level::warn;
std::string log_pattern = "%^%-9!l%-8n%$ %v";
std::size_t log_backtrace = 0;
std::shared_ptr<Logger> logger;
bool dev = false;
bool on_ci = false;
@ -223,10 +221,13 @@ namespace mamba
Context& operator=(Context&&) = delete;
const void debug_print();
void dump_backtrace_no_guards();
private:
Context();
~Context() = default;
std::shared_ptr<Logger> logger;
};
} // namespace mamba

View File

@ -11,19 +11,13 @@
#include "nlohmann/json.hpp"
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include <chrono>
#include <iosfwd>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "mamba/core/common_types.hpp"
namespace mamba
{
@ -103,6 +97,7 @@ namespace mamba
};
class ProgressBarManager;
class ConsoleData;
class Console
{
@ -141,18 +136,11 @@ namespace mamba
private:
Console();
~Console() = default;
~Console();
void deactivate_progress_bar(std::size_t idx, const std::string_view& msg = "");
std::mutex m_mutex;
std::unique_ptr<ProgressBarManager> p_progress_bar_manager;
std::string json_hier;
unsigned int json_index;
nlohmann::json json_log;
static std::vector<std::string> m_buffer;
ConsoleData* p_data;
friend class ProgressProxy;
};
@ -160,7 +148,7 @@ namespace mamba
class MessageLogger
{
public:
MessageLogger(const char* file, int line, spdlog::level::level_enum level);
MessageLogger(const char* file, int line, log_level level);
~MessageLogger();
std::stringstream& stream();
@ -172,24 +160,12 @@ namespace mamba
private:
std::string m_file;
int m_line;
spdlog::level::level_enum m_level;
log_level m_level;
std::stringstream m_stream;
static std::mutex m_mutex;
static bool use_buffer;
static std::vector<std::pair<std::string, spdlog::level::level_enum>> m_buffer;
static void emit(const std::string& msg, const spdlog::level::level_enum& level);
static void emit(const std::string& msg, const log_level& level);
};
class Logger : public spdlog::logger
{
public:
Logger(const std::string& name, const std::string& pattern, const std::string& eol);
void dump_backtrace_no_guards();
};
} // namespace mamba
#undef LOG
@ -201,11 +177,11 @@ namespace mamba
#undef LOG_CRITICAL
#define LOG(severity) mamba::MessageLogger(__FILE__, __LINE__, severity).stream()
#define LOG_TRACE LOG(spdlog::level::trace)
#define LOG_DEBUG LOG(spdlog::level::debug)
#define LOG_INFO LOG(spdlog::level::info)
#define LOG_WARNING LOG(spdlog::level::warn)
#define LOG_ERROR LOG(spdlog::level::err)
#define LOG_CRITICAL LOG(spdlog::level::critical)
#define LOG_TRACE LOG(mamba::log_level::trace)
#define LOG_DEBUG LOG(mamba::log_level::debug)
#define LOG_INFO LOG(mamba::log_level::info)
#define LOG_WARNING LOG(mamba::log_level::warn)
#define LOG_ERROR LOG(mamba::log_level::err)
#define LOG_CRITICAL LOG(mamba::log_level::critical)
#endif // MAMBA_OUTPUT_HPP

View File

@ -10,6 +10,7 @@
#include <cstddef>
#include <chrono>
#include <functional>
#include <string>
namespace mamba
{
@ -93,4 +94,3 @@ namespace mamba
}
#endif

View File

@ -13,6 +13,8 @@
#include <nlohmann/json.hpp>
#include "spdlog/spdlog.h"
#include "mamba/api/configuration.hpp"
#include "mamba/api/info.hpp"
#include "mamba/api/install.hpp"
@ -580,28 +582,28 @@ namespace mamba
}
}
spdlog::level::level_enum log_level_fallback_hook()
mamba::log_level log_level_fallback_hook()
{
auto& ctx = Context::instance();
if (ctx.json)
return spdlog::level::off;
return mamba::log_level::off;
else if (Configuration::instance().at("verbose").configured())
{
switch (ctx.verbosity)
{
case 0:
return spdlog::level::warn;
return mamba::log_level::warn;
case 1:
return spdlog::level::info;
return mamba::log_level::info;
case 2:
return spdlog::level::debug;
return mamba::log_level::debug;
default:
return spdlog::level::trace;
return mamba::log_level::trace;
}
}
else
return spdlog::level::warn;
return mamba::log_level::warn;
}
void verbose_hook(std::uint8_t& lvl)
@ -1387,7 +1389,7 @@ namespace mamba
.set_env_var_names()
.description("Only display what would have been done"));
insert(Configurable("log_level", &ctx.log_level)
insert(Configurable("log_level", &ctx.logging_level)
.group("Output, Prompt and Flow Control")
.set_rc_configurable()
.set_env_var_names()
@ -1660,12 +1662,12 @@ namespace mamba
Console::print(banner());
auto& ctx = Context::instance();
spdlog::set_level(ctx.log_level);
ctx.set_log_level(ctx.logging_level);
spdlog::apply_all([&](std::shared_ptr<spdlog::logger> l) { l->flush(); });
spdlog::flush_on(spdlog::level::off);
Context::instance().logger->dump_backtrace_no_guards();
Context::instance().dump_backtrace_no_guards();
if (ctx.log_backtrace > 0)
spdlog::enable_backtrace(ctx.log_backtrace);
else

View File

@ -4,12 +4,14 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <regex>
#include <iostream>
#include "mamba/api/list.hpp"
#include "mamba/core/channel.hpp"
#include "mamba/api/configuration.hpp"
#include "mamba/core/prefix_data.hpp"
namespace mamba
{
void list(const std::string& regex)

View File

@ -12,8 +12,46 @@
#include "termcolor/termcolor.hpp"
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
namespace mamba
{
class Logger : public spdlog::logger
{
public:
Logger(const std::string& name, const std::string& pattern, const std::string& eol);
void dump_backtrace_no_guards();
};
Logger::Logger(const std::string& name, const std::string& pattern, const std::string& eol)
: spdlog::logger(name, std::make_shared<spdlog::sinks::stderr_color_sink_mt>())
{
auto f = std::make_unique<spdlog::pattern_formatter>(
pattern, spdlog::pattern_time_type::local, eol);
set_formatter(std::move(f));
}
void Logger::dump_backtrace_no_guards()
{
using spdlog::details::log_msg;
if (tracer_.enabled())
{
tracer_.foreach_pop(
[this](const log_msg& msg)
{
if (this->should_log(msg.level))
this->sink_it_(msg);
});
}
}
spdlog::level::level_enum convert_log_level(log_level l)
{
return static_cast<spdlog::level::level_enum>(l);
}
Context::Context()
{
on_ci = bool(env::get("CI"));
@ -55,7 +93,7 @@ namespace mamba
spdlog::set_default_logger(l);
logger = std::dynamic_pointer_cast<Logger>(l);
spdlog::set_level(log_level);
spdlog::set_level(convert_log_level(logging_level));
}
Context& Context::instance()
@ -71,37 +109,37 @@ namespace mamba
switch (lvl)
{
case -3:
this->log_level = spdlog::level::off;
this->logging_level = log_level::off;
break;
case -2:
this->log_level = spdlog::level::critical;
this->logging_level = log_level::critical;
break;
case -1:
this->log_level = spdlog::level::err;
this->logging_level = log_level::err;
break;
case 0:
this->log_level = spdlog::level::warn;
this->logging_level = log_level::warn;
break;
case 1:
this->log_level = spdlog::level::info;
this->logging_level = log_level::info;
break;
case 2:
this->log_level = spdlog::level::debug;
this->logging_level = log_level::debug;
break;
case 3:
this->log_level = spdlog::level::trace;
this->logging_level = log_level::trace;
break;
default:
this->log_level = spdlog::level::info;
this->logging_level = log_level::info;
break;
}
spdlog::set_level(log_level);
spdlog::set_level(convert_log_level(logging_level));
}
void Context::set_log_level(const spdlog::level::level_enum& level)
void Context::set_log_level(log_level level)
{
log_level = level;
spdlog::set_level(level);
logging_level = level;
spdlog::set_level(convert_log_level(level));
}
std::vector<std::string> Context::platforms()
@ -199,4 +237,10 @@ namespace mamba
// clang-format on
#undef PRINT_CTX
}
void Context::dump_backtrace_no_guards()
{
logger->dump_backtrace_no_guards();
}
} // namespace mamba

View File

@ -6,6 +6,8 @@
#include <string_view>
#include "spdlog/spdlog.h"
#include "mamba/version.hpp"
#include "mamba/core/fetch.hpp"
#include "mamba/core/context.hpp"

View File

@ -22,6 +22,9 @@
#include <map>
#include <string>
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "progress_bar_impl.hpp"
namespace mamba
@ -252,8 +255,20 @@ namespace mamba
* Console *
***********/
struct ConsoleData
{
std::mutex m_mutex;
std::unique_ptr<ProgressBarManager> p_progress_bar_manager;
std::string json_hier;
unsigned int json_index;
nlohmann::json json_log;
std::vector<std::string> m_buffer;
};
Console::Console()
: m_mutex()
: p_data(new ConsoleData())
{
init_progress_bar_manager(ProgressBarMode::multi);
#ifdef _WIN32
@ -263,6 +278,12 @@ namespace mamba
#endif
}
Console::~Console()
{
delete p_data;
p_data = nullptr;
}
Console& Console::instance()
{
static Console c;
@ -283,28 +304,30 @@ namespace mamba
{
if (!(Context::instance().quiet || Context::instance().json) || force_print)
{
const std::lock_guard<std::mutex> lock(instance().m_mutex);
ConsoleData* data = instance().p_data;
const std::lock_guard<std::mutex> lock(data->m_mutex);
if (instance().p_progress_bar_manager && instance().p_progress_bar_manager->started())
if (data->p_progress_bar_manager && data->p_progress_bar_manager->started())
{
instance().m_buffer.push_back(instance().hide_secrets(str));
data->m_buffer.push_back(hide_secrets(str));
}
else
{
std::cout << instance().hide_secrets(str) << std::endl;
std::cout << hide_secrets(str) << std::endl;
}
}
}
std::vector<std::string> Console::m_buffer({});
// std::vector<std::string> Console::m_buffer({});
void Console::print_buffer(std::ostream& ostream)
{
for (auto& message : m_buffer)
ConsoleData* data = instance().p_data;
for (auto& message : data->m_buffer)
ostream << message << "\n";
const std::lock_guard<std::mutex> lock(instance().m_mutex);
m_buffer.clear();
const std::lock_guard<std::mutex> lock(data->m_mutex);
data->m_buffer.clear();
}
// We use an overload instead of a default argument to avoid exposing std::cin
@ -365,28 +388,28 @@ namespace mamba
if (Context::instance().no_progress_bars)
return ProgressProxy();
else
return p_progress_bar_manager->add_progress_bar(name, expected_total);
return p_data->p_progress_bar_manager->add_progress_bar(name, expected_total);
}
void Console::clear_progress_bars()
{
return p_progress_bar_manager->clear_progress_bars();
return p_data->p_progress_bar_manager->clear_progress_bars();
}
ProgressBarManager& Console::init_progress_bar_manager(ProgressBarMode mode)
{
p_progress_bar_manager = make_progress_bar_manager(mode);
p_progress_bar_manager->register_print_hook(Console::print_buffer);
p_progress_bar_manager->register_print_hook(MessageLogger::print_buffer);
p_progress_bar_manager->register_pre_start_hook(MessageLogger::activate_buffer);
p_progress_bar_manager->register_post_stop_hook(MessageLogger::deactivate_buffer);
p_data->p_progress_bar_manager = make_progress_bar_manager(mode);
p_data->p_progress_bar_manager->register_print_hook(Console::print_buffer);
p_data->p_progress_bar_manager->register_print_hook(MessageLogger::print_buffer);
p_data->p_progress_bar_manager->register_pre_start_hook(MessageLogger::activate_buffer);
p_data->p_progress_bar_manager->register_post_stop_hook(MessageLogger::deactivate_buffer);
return *p_progress_bar_manager;
return *(p_data->p_progress_bar_manager);
}
ProgressBarManager& Console::progress_bar_manager()
{
return *p_progress_bar_manager;
return *(p_data->p_progress_bar_manager);
}
std::string strip_file_prefix(const std::string& file)
@ -400,11 +423,82 @@ namespace mamba
return pos != std::string::npos ? file.substr(pos + 1, std::string::npos) : file;
}
void Console::json_print()
{
if (Context::instance().json)
print(p_data->json_log.unflatten().dump(4), true);
}
// write all the key/value pairs of a JSON object into the current entry, which
// is then a JSON object
void Console::json_write(const nlohmann::json& j)
{
if (Context::instance().json)
{
nlohmann::json tmp = j.flatten();
for (auto it = tmp.begin(); it != tmp.end(); ++it)
p_data->json_log[p_data->json_hier + it.key()] = it.value();
}
}
// append a value to the current entry, which is then a list
void Console::json_append(const std::string& value)
{
if (Context::instance().json)
{
p_data->json_log[p_data->json_hier + '/' + std::to_string(p_data->json_index)] = value;
p_data->json_index += 1;
}
}
// append a JSON object to the current entry, which is then a list
void Console::json_append(const nlohmann::json& j)
{
if (Context::instance().json)
{
nlohmann::json tmp = j.flatten();
for (auto it = tmp.begin(); it != tmp.end(); ++it)
p_data->json_log[p_data->json_hier + '/' + std::to_string(p_data->json_index)
+ it.key()]
= it.value();
p_data->json_index += 1;
}
}
// go down in the hierarchy in the "key" entry, create it if it doesn't exist
void Console::json_down(const std::string& key)
{
if (Context::instance().json)
{
p_data->json_hier += '/' + key;
p_data->json_index = 0;
}
}
// go up in the hierarchy
void Console::json_up()
{
if (Context::instance().json)
p_data->json_hier.erase(p_data->json_hier.rfind('/'));
}
/*****************
* MessageLogger *
*****************/
MessageLogger::MessageLogger(const char* file, int line, spdlog::level::level_enum level)
struct MessageLoggerData
{
static std::mutex m_mutex;
static bool use_buffer;
static std::vector<std::pair<std::string, log_level>> m_buffer;
};
std::mutex MessageLoggerData::m_mutex;
bool MessageLoggerData::use_buffer(false);
std::vector<std::pair<std::string, log_level>> MessageLoggerData::m_buffer({});
MessageLogger::MessageLogger(const char* file, int line, log_level level)
: m_file(strip_file_prefix(file))
, m_line(line)
, m_level(level)
@ -414,44 +508,38 @@ namespace mamba
MessageLogger::~MessageLogger()
{
if (!use_buffer)
if (!MessageLoggerData::use_buffer)
emit(m_stream.str(), m_level);
else
{
const std::lock_guard<std::mutex> lock(m_mutex);
m_buffer.push_back({ m_stream.str(), m_level });
const std::lock_guard<std::mutex> lock(MessageLoggerData::m_mutex);
MessageLoggerData::m_buffer.push_back({ m_stream.str(), m_level });
}
}
std::mutex MessageLogger::m_mutex;
bool MessageLogger::use_buffer(false);
std::vector<std::pair<std::string, spdlog::level::level_enum>> MessageLogger::m_buffer({});
void MessageLogger::emit(const std::string& msg, const spdlog::level::level_enum& level)
void MessageLogger::emit(const std::string& msg, const log_level& level)
{
auto str = Console::hide_secrets(msg);
switch (level)
{
case spdlog::level::critical:
case log_level::critical:
SPDLOG_CRITICAL(prepend(str, "", std::string(4, ' ').c_str()));
if (Context::instance().log_level != spdlog::level::off)
if (Context::instance().logging_level != log_level::off)
spdlog::dump_backtrace();
break;
case spdlog::level::err:
case log_level::err:
SPDLOG_ERROR(prepend(str, "", std::string(4, ' ').c_str()));
break;
case spdlog::level::warn:
case log_level::warn:
SPDLOG_WARN(prepend(str, "", std::string(4, ' ').c_str()));
break;
case spdlog::level::info:
case log_level::info:
SPDLOG_INFO(prepend(str, "", std::string(4, ' ').c_str()));
break;
case spdlog::level::debug:
case log_level::debug:
SPDLOG_DEBUG(prepend(str, "", std::string(4, ' ').c_str()));
break;
case spdlog::level::trace:
case log_level::trace:
SPDLOG_TRACE(prepend(str, "", std::string(4, ' ').c_str()));
break;
default:
@ -466,101 +554,24 @@ namespace mamba
void MessageLogger::activate_buffer()
{
use_buffer = true;
MessageLoggerData::use_buffer = true;
}
void MessageLogger::deactivate_buffer()
{
use_buffer = false;
MessageLoggerData::use_buffer = false;
}
void MessageLogger::print_buffer(std::ostream& /*ostream*/)
{
for (auto& [msg, level] : m_buffer)
for (auto& [msg, level] : MessageLoggerData::m_buffer)
emit(msg, level);
spdlog::apply_all([&](std::shared_ptr<spdlog::logger> l) { l->flush(); });
const std::lock_guard<std::mutex> lock(m_mutex);
m_buffer.clear();
const std::lock_guard<std::mutex> lock(MessageLoggerData::m_mutex);
MessageLoggerData::m_buffer.clear();
}
Logger::Logger(const std::string& name, const std::string& pattern, const std::string& eol)
: spdlog::logger(name, std::make_shared<spdlog::sinks::stderr_color_sink_mt>())
{
auto f = std::make_unique<spdlog::pattern_formatter>(
pattern, spdlog::pattern_time_type::local, eol);
set_formatter(std::move(f));
}
void Logger::dump_backtrace_no_guards()
{
using spdlog::details::log_msg;
if (tracer_.enabled())
{
tracer_.foreach_pop(
[this](const log_msg& msg)
{
if (this->should_log(msg.level))
this->sink_it_(msg);
});
}
}
void Console::json_print()
{
if (Context::instance().json)
print(json_log.unflatten().dump(4), true);
}
// write all the key/value pairs of a JSON object into the current entry, which
// is then a JSON object
void Console::json_write(const nlohmann::json& j)
{
if (Context::instance().json)
{
nlohmann::json tmp = j.flatten();
for (auto it = tmp.begin(); it != tmp.end(); ++it)
json_log[json_hier + it.key()] = it.value();
}
}
// append a value to the current entry, which is then a list
void Console::json_append(const std::string& value)
{
if (Context::instance().json)
{
json_log[json_hier + '/' + std::to_string(json_index)] = value;
json_index += 1;
}
}
// append a JSON object to the current entry, which is then a list
void Console::json_append(const nlohmann::json& j)
{
if (Context::instance().json)
{
nlohmann::json tmp = j.flatten();
for (auto it = tmp.begin(); it != tmp.end(); ++it)
json_log[json_hier + '/' + std::to_string(json_index) + it.key()] = it.value();
json_index += 1;
}
}
// go down in the hierarchy in the "key" entry, create it if it doesn't exist
void Console::json_down(const std::string& key)
{
if (Context::instance().json)
{
json_hier += '/' + key;
json_index = 0;
}
}
// go up in the hierarchy
void Console::json_up()
{
if (Context::instance().json)
json_hier.erase(json_hier.rfind('/'));
}
} // namespace mamba

View File

@ -9,6 +9,8 @@ extern "C"
#include <solv/pool.h>
}
#include "spdlog/spdlog.h"
#include "mamba/core/context.hpp"
#include "mamba/core/pool.hpp"
#include "mamba/core/output.hpp"

View File

@ -224,4 +224,3 @@ namespace mamba
return p_bar->repr();
}
}

View File

@ -284,14 +284,14 @@ PYBIND11_MODULE(bindings, m)
.value("kStrict", ChannelPriority::kStrict)
.value("kDisabled", ChannelPriority::kDisabled);
py::enum_<spdlog::level::level_enum>(m, "LogLevel")
.value("TRACE", spdlog::level::trace)
.value("DEBUG", spdlog::level::debug)
.value("INFO", spdlog::level::info)
.value("WARNING", spdlog::level::warn)
.value("ERROR", spdlog::level::err)
.value("CRITICAL", spdlog::level::critical)
.value("OFF", spdlog::level::off);
py::enum_<mamba::log_level>(m, "LogLevel")
.value("TRACE", mamba::log_level::trace)
.value("DEBUG", mamba::log_level::debug)
.value("INFO", mamba::log_level::info)
.value("WARNING", mamba::log_level::warn)
.value("ERROR", mamba::log_level::err)
.value("CRITICAL", mamba::log_level::critical)
.value("OFF", mamba::log_level::off);
py::class_<Context, std::unique_ptr<Context, py::nodelete>>(m, "Context")
.def(

View File

@ -48,19 +48,17 @@ init_general_options(CLI::App* subcom)
"Set verbosity (higher verbosity with multiple -v, e.g. -vvv)")
->group(cli_group);
std::map<std::string, spdlog::level::level_enum> le_map
= { { "critical", spdlog::level::critical },
{ "error", spdlog::level::err },
{ "warning", spdlog::level::warn },
{ "info", spdlog::level::info },
{ "debug", spdlog::level::debug },
{ "trace", spdlog::level::trace },
{ "off", spdlog::level::off } };
std::map<std::string, mamba::log_level> le_map = { { "critical", mamba::log_level::critical },
{ "error", mamba::log_level::err },
{ "warning", mamba::log_level::warn },
{ "info", mamba::log_level::info },
{ "debug", mamba::log_level::debug },
{ "trace", mamba::log_level::trace },
{ "off", mamba::log_level::off } };
auto& log_level = config.at("log_level");
subcom
->add_option("--log-level",
log_level.get_cli_config<spdlog::level::level_enum>(),
log_level.description())
->add_option(
"--log-level", log_level.get_cli_config<mamba::log_level>(), log_level.description())
->group(cli_group)
->transform(CLI::CheckedTransformer(le_map, CLI::ignore_case));

View File

@ -1,5 +1,6 @@
#include <csignal>
#include <exception>
#include <thread>
#include "spdlog/fmt/fmt.h"
#include "spdlog/fmt/bundled/color.h"
@ -24,6 +25,8 @@ extern "C"
#include <sys/stat.h>
#include <fcntl.h>
}
#else
#include <process.h>
#endif
#include "run.hpp"