diff --git a/.gitignore b/.gitignore index b88e88c..068c010 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,6 @@ subprojects/Catch2-* subprojects/CLI11-* subprojects/fmt-* subprojects/packagecache +subprojects/spdlog-* subprojects/sqlite-amalgamation-* subprojects/nlohmann_json-* diff --git a/meson.build b/meson.build index 92231fb..1657030 100644 --- a/meson.build +++ b/meson.build @@ -19,6 +19,7 @@ catch_dep = subproject('catch2', default_options: 'werror=false').get_variable(' cli11_dep = subproject('cli11', default_options: 'werror=false').get_variable('CLI11_dep') fmt_dep = subproject('fmt', default_options: 'werror=false').get_variable('fmt_dep') json_dep = subproject('nlohmann_json', default_options: 'werror=false').get_variable('nlohmann_json_dep') +spdlog_dep = subproject('spdlog', default_options: 'werror=false').get_variable('spdlog_dep') sqlite3_dep = subproject('sqlite3', default_options: 'werror=false').get_variable('sqlite3_dep') # the lib dependency is all of the common funtionality shared between the CLI @@ -27,6 +28,7 @@ lib_src = [ 'src/uenv/env.cpp', 'src/uenv/envvars.cpp', 'src/uenv/lex.cpp', + 'src/uenv/log.cpp', 'src/uenv/meta.cpp', 'src/uenv/parse.cpp', 'src/util/strings.cpp', @@ -37,7 +39,7 @@ lib_inc = include_directories('src') lib_dep = declare_dependency( sources: lib_src, - dependencies: [sqlite3_dep, fmt_dep, json_dep], + dependencies: [sqlite3_dep, fmt_dep, spdlog_dep, json_dep], include_directories: lib_inc ) @@ -51,7 +53,7 @@ uenv_dep = [sqlite3_dep] uenv = executable('uenv', sources: uenv_src, - dependencies: [uenv_dep, lib_dep, fmt_dep, cli11_dep], + dependencies: [uenv_dep, lib_dep, fmt_dep, spdlog_dep, cli11_dep], c_args: ['-DVERSION="@0@"'.format(version)], install: true) diff --git a/src/cli/start.cpp b/src/cli/start.cpp index 0cf2bc9..55cc35b 100644 --- a/src/cli/start.cpp +++ b/src/cli/start.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -36,12 +37,13 @@ void start_args::add_cli(CLI::App& cli, int start(const start_args& args, [[maybe_unused]] const global_settings& globals) { - fmt::println("running start with options {}", args); + spdlog::debug("running start with options {}", args); + const auto env = concretise_env(args.uenv_description, args.view_description); if (!env) { - fmt::print("[error] {}\n", env.error()); + spdlog::error("{}", env.error()); return 1; } @@ -49,7 +51,7 @@ int start(const start_args& args, auto env_vars = uenv::getenv(*env); if (auto rval = uenv::setenv(env_vars); !rval) { - fmt::print("[error] setting environment variables {}\n", rval.error()); + spdlog::error("setting environment variables {}", rval.error()); return 1; } @@ -63,15 +65,16 @@ int start(const start_args& args, // find the current shell (zsh, bash, etc) auto shell = util::current_shell(); if (!shell) { - fmt::print("[error] unable to determine the current shell because {}\n", - shell.error()); + spdlog::error("unable to determine the current shell because {}", + shell.error()); + return 1; } - fmt::println("[log] shell found: {}", shell->string()); + spdlog::info("shell found: {}", shell->string()); commands.push_back("--"); commands.push_back(shell->string()); - fmt::print("[log] exec {}\n", fmt::join(commands, " ")); + spdlog::info("exec {}", fmt::join(commands, " ")); return util::exec(commands); } diff --git a/src/cli/uenv.cpp b/src/cli/uenv.cpp index fbff942..4963025 100644 --- a/src/cli/uenv.cpp +++ b/src/cli/uenv.cpp @@ -3,6 +3,9 @@ #include #include #include +#include + +#include #include "start.h" #include "uenv.h" @@ -23,7 +26,19 @@ int main(int argc, char** argv) { CLI11_PARSE(cli, argc, argv); - fmt::print(fmt::emphasis::bold | fg(fmt::color::orange), "{}\n", settings); + // Warnings and errors are always logged. The verbosity level is increased + // with repeated uses of --verbose. + spdlog::level::level_enum console_log_level = spdlog::level::warn; + if (settings.verbose == 1) { + console_log_level = spdlog::level::info; + } else if (settings.verbose == 2) { + console_log_level = spdlog::level::debug; + } else if (settings.verbose >= 3) { + console_log_level = spdlog::level::trace; + } + uenv::init_log(console_log_level, spdlog::level::trace); + + spdlog::debug("{}", settings); switch (settings.mode) { case uenv::mode_start: diff --git a/src/cli/uenv.h b/src/cli/uenv.h index aaaab72..ae39398 100644 --- a/src/cli/uenv.h +++ b/src/cli/uenv.h @@ -15,7 +15,7 @@ constexpr int mode_start = 1; // constexpr int mode_run = 3; struct global_settings { - bool verbose = false; + int verbose = 0; bool no_color = false; int mode = mode_none; diff --git a/src/uenv/env.cpp b/src/uenv/env.cpp index 0cd277b..196b731 100644 --- a/src/uenv/env.cpp +++ b/src/uenv/env.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -61,7 +62,7 @@ concretise_env(const std::string& uenv_args, fmt::format("no mount point provided for {}", desc)); } } - fmt::println("{} will be mounted at {}", desc, mount); + spdlog::info("{} will be mounted at {}", desc, mount); // check that the mount point exists if (!fs::exists(mount)) { @@ -111,13 +112,13 @@ concretise_env(const std::string& uenv_args, name = std::move(result->name); description = std::move(result->description); views = std::move(result->views); - fmt::println("loaded meta with name {}", name); + spdlog::debug("loaded meta with name {}", name); } else { - fmt::println("error loading the uenv meta data in {}: {}", - *env_meta_path, result.error()); + spdlog::error("error loading the uenv meta data in {}: {}", + *env_meta_path, result.error()); } } else { - fmt::println("the meta data file {} does not exist", meta_path); + spdlog::debug("the meta data file {} does not exist", meta_path); description = ""; // generate a unique name for the uenv name = "anonymous"; diff --git a/src/uenv/log.cpp b/src/uenv/log.cpp new file mode 100644 index 0000000..a9d599d --- /dev/null +++ b/src/uenv/log.cpp @@ -0,0 +1,28 @@ +#include + +#include "spdlog/sinks/stdout_color_sinks.h" +#include "spdlog/sinks/syslog_sink.h" +#include + +#include "log.h" + +namespace uenv { +void init_log(spdlog::level::level_enum console_log_level, + spdlog::level::level_enum syslog_log_level) { + auto console_sink = std::make_shared(); + console_sink->set_level(console_log_level); + + auto syslog_sink = std::make_shared( + "uenv", LOG_PID, 0, false); + syslog_sink->set_level(syslog_log_level); + + // The default logger is a combined logger that dispatches to the console + // and syslog. We explicitly set the level to trace to allow all messages to + // pass through the combined logger. The lower level loggers will filter + // messages at their level. + spdlog::set_default_logger(std::make_shared( + "uenv", spdlog::sinks_init_list({console_sink, syslog_sink}))); + spdlog::set_level(spdlog::level::trace); + spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%n] [%^%l%$] %v"); +} +} // namespace uenv diff --git a/src/uenv/log.h b/src/uenv/log.h new file mode 100644 index 0000000..c060f51 --- /dev/null +++ b/src/uenv/log.h @@ -0,0 +1,6 @@ +#include + +namespace uenv { +void init_log(spdlog::level::level_enum console_log_level, + spdlog::level::level_enum syslog_log_level); +} diff --git a/src/util/shell.cpp b/src/util/shell.cpp index 47c7106..d35165f 100644 --- a/src/util/shell.cpp +++ b/src/util/shell.cpp @@ -6,6 +6,7 @@ #include #include +#include #include @@ -41,11 +42,11 @@ int exec(const std::vector& args) { } argv.push_back(nullptr); - fmt::println("running {}", argv[0]); + spdlog::info("running {}", argv[0]); int r = execvp(argv[0], argv.data()); // } // end unsafe - fmt::print("[error] unable to launch a new shell\n"); + spdlog::error("unable to launch a new shell"); return r; } diff --git a/subprojects/spdlog.wrap b/subprojects/spdlog.wrap new file mode 100644 index 0000000..af00d5a --- /dev/null +++ b/subprojects/spdlog.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = spdlog-1.14.1 +source_url = https://github.com/gabime/spdlog/archive/refs/tags/v1.14.1.tar.gz +source_filename = spdlog-1.14.1.tar.gz +source_hash = 1586508029a7d0670dfcb2d97575dcdc242d3868a259742b69f100801ab4e16b +patch_filename = spdlog_1.14.1-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/spdlog_1.14.1-1/get_patch +patch_hash = ae878e732330ea1048f90d7e117c40c0cd2a6fb8ae5492c7955818ce3aaade6c +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/spdlog_1.14.1-1/spdlog-1.14.1.tar.gz +wrapdb_version = 1.14.1-1 + +[provide] +spdlog = spdlog_dep diff --git a/test/unit/main.cpp b/test/unit/main.cpp index 2c344d5..9f94c54 100644 --- a/test/unit/main.cpp +++ b/test/unit/main.cpp @@ -1,2 +1,10 @@ #define CATCH_CONFIG_MAIN #include + +#include + +static struct unit_init_log { + unit_init_log() { + uenv::init_log(spdlog::level::trace, spdlog::level::off); + } +} uil{};