Commit a6b7d52c authored by Dominik Charousset's avatar Dominik Charousset Committed by GitHub

Merge pull request #523 from actor-framework/topic/logger-configuration

Make logger more configurable
parents b9ee7c0a 4c2a3a6f
...@@ -34,6 +34,7 @@ set (LIBCAF_CORE_SRCS ...@@ -34,6 +34,7 @@ set (LIBCAF_CORE_SRCS
src/behavior_impl.cpp src/behavior_impl.cpp
src/blocking_actor.cpp src/blocking_actor.cpp
src/blocking_behavior.cpp src/blocking_behavior.cpp
src/color.cpp
src/concatenated_tuple.cpp src/concatenated_tuple.cpp
src/config_option.cpp src/config_option.cpp
src/continue_helper.cpp src/continue_helper.cpp
......
...@@ -252,6 +252,13 @@ public: ...@@ -252,6 +252,13 @@ public:
size_t work_stealing_relaxed_steal_interval; size_t work_stealing_relaxed_steal_interval;
size_t work_stealing_relaxed_sleep_duration_us; size_t work_stealing_relaxed_sleep_duration_us;
// -- config parameters for the logger ---------------------------------------
std::string logger_filename;
atom_value logger_verbosity;
atom_value logger_console;
std::string logger_filter;
// -- config parameters of the middleman ------------------------------------- // -- config parameters of the middleman -------------------------------------
atom_value middleman_network_backend; atom_value middleman_network_backend;
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2016 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_COLOR_HPP
#define CAF_COLOR_HPP
namespace caf {
enum color_face {
normal,
bold
};
enum color_value {
reset,
black,
red,
green,
yellow,
blue,
magenta,
cyan,
white
};
const char* color(color_value value, color_face face = normal);
} // namespace caf
#endif // CAF_COLOR_HPP
...@@ -17,8 +17,8 @@ ...@@ -17,8 +17,8 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#ifndef CAF_DETAIL_LOGGING_HPP #ifndef CAF_LOGGER_HPP
#define CAF_DETAIL_LOGGING_HPP #define CAF_LOGGER_HPP
#include <thread> #include <thread>
#include <cstring> #include <cstring>
...@@ -64,8 +64,12 @@ public: ...@@ -64,8 +64,12 @@ public:
struct event { struct event {
event* next; event* next;
event* prev; event* prev;
int level;
const char* component;
std::string prefix;
std::string msg; std::string msg;
explicit event(std::string log_message = ""); explicit event(int l = 0, char const* c = "", std::string p = "",
std::string m = "");
}; };
template <class T> template <class T>
...@@ -167,6 +171,7 @@ private: ...@@ -167,6 +171,7 @@ private:
void stop(); void stop();
actor_system& system_; actor_system& system_;
int level_;
detail::shared_spinlock aids_lock_; detail::shared_spinlock aids_lock_;
std::unordered_map<std::thread::id, actor_id> aids_; std::unordered_map<std::thread::id, actor_id> aids_;
std::thread thread_; std::thread thread_;
...@@ -187,18 +192,6 @@ private: ...@@ -187,18 +192,6 @@ private:
#define CAF_LOG_LEVEL_DEBUG 3 #define CAF_LOG_LEVEL_DEBUG 3
#define CAF_LOG_LEVEL_TRACE 4 #define CAF_LOG_LEVEL_TRACE 4
#define CAF_PRINT_ERROR_IMPL(nclass, nfun, message) \
do { \
caf::logger::line_builder lb; \
lb << message; \
if (nclass.empty()) \
printf("[ERROR] in %s:%d %s::%s: %s\n", __FILE__, __LINE__, \
nclass.c_str(), nfun, lb.get().c_str()); \
else \
printf("[ERROR] in %s:%d %s: %s\n", __FILE__, __LINE__, \
nfun, lb.get().c_str()); \
} while (false)
#define CAF_ARG(argument) caf::logger::make_arg_wrapper(#argument, argument) #define CAF_ARG(argument) caf::logger::make_arg_wrapper(#argument, argument)
#ifdef CAF_MSVC #ifdef CAF_MSVC
...@@ -286,6 +279,8 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; } ...@@ -286,6 +279,8 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; }
# define CAF_LOG_WARNING(output) CAF_LOG_IMPL(CAF_LOG_LEVEL_WARNING, output) # define CAF_LOG_WARNING(output) CAF_LOG_IMPL(CAF_LOG_LEVEL_WARNING, output)
#endif #endif
#define CAF_LOG_ERROR(output) CAF_LOG_IMPL(CAF_LOG_LEVEL_ERROR, output)
#endif // CAF_LOG_LEVEL #endif // CAF_LOG_LEVEL
#ifndef CAF_LOG_INFO #ifndef CAF_LOG_INFO
...@@ -300,11 +295,9 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; } ...@@ -300,11 +295,9 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; }
# define CAF_LOG_WARNING(output) CAF_VOID_STMT # define CAF_LOG_WARNING(output) CAF_VOID_STMT
#endif #endif
#define CAF_LOG_ERROR(output) \ #ifndef CAF_LOG_ERROR
do { \ # define CAF_LOG_ERROR(output) CAF_VOID_STMT
CAF_PRINT_ERROR_IMPL(CAF_GET_CLASS_NAME, __func__, output); \ #endif
CAF_LOG_IMPL(CAF_LOG_LEVEL_ERROR, output); \
} while (false)
#ifdef CAF_LOG_LEVEL #ifdef CAF_LOG_LEVEL
...@@ -329,4 +322,4 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; } ...@@ -329,4 +322,4 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; }
#endif // CAF_LOG_LEVEL #endif // CAF_LOG_LEVEL
#endif // CAF_DETAIL_LOGGING_HPP #endif // CAF_LOGGER_HPP
...@@ -242,12 +242,13 @@ actor_system::actor_system(actor_system_config& cfg) ...@@ -242,12 +242,13 @@ actor_system::actor_system(actor_system_config& cfg)
if (mod) if (mod)
mod->init(cfg); mod->init(cfg);
groups_.init(cfg); groups_.init(cfg);
// start logger before spawning actors (since that uses the logger)
logger_.start();
// spawn config and spawn servers (lazily to not access the scheduler yet) // spawn config and spawn servers (lazily to not access the scheduler yet)
static constexpr auto Flags = hidden + lazy_init; static constexpr auto Flags = hidden + lazy_init;
spawn_serv_ = actor_cast<strong_actor_ptr>(spawn<Flags>(spawn_serv_impl)); spawn_serv_ = actor_cast<strong_actor_ptr>(spawn<Flags>(spawn_serv_impl));
config_serv_ = actor_cast<strong_actor_ptr>(spawn<Flags>(config_serv_impl)); config_serv_ = actor_cast<strong_actor_ptr>(spawn<Flags>(config_serv_impl));
// fire up remaining modules // fire up remaining modules
logger_.start();
registry_.start(); registry_.start();
registry_.put(atom("SpawnServ"), spawn_serv_); registry_.put(atom("SpawnServ"), spawn_serv_);
registry_.put(atom("ConfigServ"), config_serv_); registry_.put(atom("ConfigServ"), config_serv_);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <limits> #include <limits>
#include <thread> #include <thread>
#include <fstream> #include <fstream>
#include <sstream>
#include "caf/message_builder.hpp" #include "caf/message_builder.hpp"
...@@ -95,6 +96,8 @@ actor_system_config::actor_system_config() ...@@ -95,6 +96,8 @@ actor_system_config::actor_system_config()
work_stealing_moderate_sleep_duration_us = 50; work_stealing_moderate_sleep_duration_us = 50;
work_stealing_relaxed_steal_interval = 1; work_stealing_relaxed_steal_interval = 1;
work_stealing_relaxed_sleep_duration_us = 10000; work_stealing_relaxed_sleep_duration_us = 10000;
logger_filename = "actor_log_[PID]_[TIMESTAMP]_[NODE].log";
logger_console = atom("NONE");
middleman_network_backend = atom("default"); middleman_network_backend = atom("default");
middleman_enable_automatic_connections = false; middleman_enable_automatic_connections = false;
middleman_max_consecutive_reads = 50; middleman_max_consecutive_reads = 50;
...@@ -128,6 +131,15 @@ actor_system_config::actor_system_config() ...@@ -128,6 +131,15 @@ actor_system_config::actor_system_config()
"sets the frequency of steal attempts during relaxed polling") "sets the frequency of steal attempts during relaxed polling")
.add(work_stealing_relaxed_sleep_duration_us, "relaxed-sleep-duration", .add(work_stealing_relaxed_sleep_duration_us, "relaxed-sleep-duration",
"sets the sleep interval between poll attempts during relaxed polling"); "sets the sleep interval between poll attempts during relaxed polling");
opt_group{options_, "logger"}
.add(logger_filename, "filename",
"sets the filesystem path of the log file")
.add(logger_verbosity, "verbosity",
"sets the verbosity (QUIET|ERROR|WARNING|INFO|DEBUG|TRACE)")
.add(logger_console, "console",
"enables logging to the console via std::clog")
.add(logger_filter, "filter",
"sets a component filter for console log messages");
opt_group{options_, "middleman"} opt_group{options_, "middleman"}
.add(middleman_network_backend, "network-backend", .add(middleman_network_backend, "network-backend",
"sets the network backend to either 'default' or 'asio' (if available)") "sets the network backend to either 'default' or 'asio' (if available)")
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2016 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/color.hpp"
#include "caf/config.hpp"
namespace caf {
const char* color(color_value value, color_face face) {
#ifdef CAF_MSVC
return "";
#else
const char* colors[9][2] = {
{"\033[0m", "\033[0m"}, // reset
{"\033[30m", "\033[1m\033[30m"}, // black
{"\033[31m", "\033[1m\033[31m"}, // red
{"\033[32m", "\033[1m\033[32m"}, // green
{"\033[33m", "\033[1m\033[33m"}, // yellow
{"\033[34m", "\033[1m\033[34m"}, // blue
{"\033[35m", "\033[1m\033[35m"}, // magenta
{"\033[36m", "\033[1m\033[36m"}, // cyan
{"\033[37m", "\033[1m\033[37m"} // white
};
return colors[static_cast<size_t>(value)][static_cast<size_t>(face)];
#endif
}
} // namespace caf
...@@ -36,9 +36,11 @@ ...@@ -36,9 +36,11 @@
#include "caf/string_algorithms.hpp" #include "caf/string_algorithms.hpp"
#include "caf/color.hpp"
#include "caf/locks.hpp" #include "caf/locks.hpp"
#include "caf/actor_proxy.hpp" #include "caf/actor_proxy.hpp"
#include "caf/actor_system.hpp" #include "caf/actor_system.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/detail/get_process_id.hpp" #include "caf/detail/get_process_id.hpp"
#include "caf/detail/single_reader_queue.hpp" #include "caf/detail/single_reader_queue.hpp"
...@@ -59,8 +61,6 @@ constexpr const char* log_level_name[] = { ...@@ -59,8 +61,6 @@ constexpr const char* log_level_name[] = {
static_assert(CAF_LOG_LEVEL >= 0 && CAF_LOG_LEVEL <= 4, static_assert(CAF_LOG_LEVEL >= 0 && CAF_LOG_LEVEL <= 4,
"assertion: 0 <= CAF_LOG_LEVEL <= 4"); "assertion: 0 <= CAF_LOG_LEVEL <= 4");
constexpr int global_log_level = CAF_LOG_LEVEL;
#ifdef CAF_MSVC #ifdef CAF_MSVC
thread_local thread_local
#else #else
...@@ -125,10 +125,13 @@ void prettify_type_name(std::string& class_name, const char* c_class_name) { ...@@ -125,10 +125,13 @@ void prettify_type_name(std::string& class_name, const char* c_class_name) {
} // namespace <anonymous> } // namespace <anonymous>
logger::event::event(std::string x) logger::event::event(int l, const char* c, std::string p, std::string m)
: next(nullptr), : next(nullptr),
prev(nullptr), prev(nullptr),
msg(std::move(x)) { level(l),
component(c),
prefix(std::move(p)),
msg(std::move(m)) {
// nop // nop
} }
...@@ -224,6 +227,8 @@ void logger::log(int level, const char* component, ...@@ -224,6 +227,8 @@ void logger::log(int level, const char* component,
const char* c_full_file_name, int line_num, const char* c_full_file_name, int line_num,
const std::string& msg) { const std::string& msg) {
CAF_ASSERT(level >= 0 && level <= 4); CAF_ASSERT(level >= 0 && level <= 4);
if (level > level_)
return;
std::string file_name; std::string file_name;
std::string full_file_name = c_full_file_name; std::string full_file_name = c_full_file_name;
auto ri = find(full_file_name.rbegin(), full_file_name.rend(), '/'); auto ri = find(full_file_name.rbegin(), full_file_name.rend(), '/');
...@@ -238,12 +243,13 @@ void logger::log(int level, const char* component, ...@@ -238,12 +243,13 @@ void logger::log(int level, const char* component,
} }
auto t0 = std::chrono::high_resolution_clock::now().time_since_epoch(); auto t0 = std::chrono::high_resolution_clock::now().time_since_epoch();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(t0).count(); auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(t0).count();
std::ostringstream line; std::ostringstream prefix;
line << ms << " " << component << " " << log_level_name[level] << " " prefix << ms << " " << component << " " << log_level_name[level] << " "
<< "actor" << thread_local_aid() << " " << std::this_thread::get_id() << "actor" << thread_local_aid() << " " << std::this_thread::get_id()
<< " " << class_name << " " << function_name << " " << file_name << ":" << " " << class_name << " " << function_name
<< line_num << " " << msg << std::endl; << " " << file_name << ":" << line_num;
queue_.synchronized_enqueue(queue_mtx_, queue_cv_, new event{line.str()}); queue_.synchronized_enqueue(queue_mtx_, queue_cv_,
new event{level, component, prefix.str(), msg});
} }
void logger::set_current_actor_system(actor_system* x) { void logger::set_current_actor_system(actor_system* x) {
...@@ -273,11 +279,27 @@ logger::logger(actor_system& sys) : system_(sys) { ...@@ -273,11 +279,27 @@ logger::logger(actor_system& sys) : system_(sys) {
} }
void logger::run() { void logger::run() {
std::ostringstream fname; auto f = system_.config().logger_filename;
fname << "actor_log_" << detail::get_process_id() << "_" << time(0) // Replace placeholders.
<< "_" << to_string(system_.node()) const char pid[] = "[PID]";
<< ".log"; auto i = std::search(f.begin(), f.end(), std::begin(pid), std::end(pid) - 1);
std::fstream out(fname.str().c_str(), std::ios::out | std::ios::app); if (i != f.end()) {
auto id = std::to_string(detail::get_process_id());
f.replace(i, i + sizeof(pid) - 1, id);
}
const char ts[] = "[TIMESTAMP]";
i = std::search(f.begin(), f.end(), std::begin(ts), std::end(ts) - 1);
if (i != f.end()) {
auto now = std::to_string(time(0));
f.replace(i, i + sizeof(ts) - 1, now);
}
const char node[] = "[NODE]";
i = std::search(f.begin(), f.end(), std::begin(node), std::end(node) - 1);
if (i != f.end()) {
auto nid = to_string(system_.node());
f.replace(i, i + sizeof(node) - 1, nid);
}
std::fstream file(f, std::ios::out | std::ios::app);
std::unique_ptr<event> ptr; std::unique_ptr<event> ptr;
for (;;) { for (;;) {
// make sure we have data to read // make sure we have data to read
...@@ -286,28 +308,74 @@ void logger::run() { ...@@ -286,28 +308,74 @@ void logger::run() {
ptr.reset(queue_.try_pop()); ptr.reset(queue_.try_pop());
CAF_ASSERT(ptr != nullptr); CAF_ASSERT(ptr != nullptr);
if (ptr->msg.empty()) { if (ptr->msg.empty()) {
out.close(); file.close();
return; return;
} }
out << ptr->msg << std::flush; file << ptr->prefix << ' ' << ptr->msg << std::endl;
// TODO: once we've phased out GCC 4.8, we can upgarde this to a regex.
if (!system_.config().logger_filter.empty()
&& ptr->component != system_.config().logger_filter)
continue;
if (system_.config().logger_console == atom("UNCOLORED")) {
std::clog << ptr->msg << std::endl;
} else if (system_.config().logger_console == atom("COLORED")) {
switch (ptr->level) {
default:
break;
case CAF_LOG_LEVEL_ERROR:
std::clog << color(red);
break;
case CAF_LOG_LEVEL_WARNING:
std::clog << color(yellow);
break;
case CAF_LOG_LEVEL_INFO:
std::clog << color(green);
break;
case CAF_LOG_LEVEL_DEBUG:
std::clog << color(cyan);
break;
case CAF_LOG_LEVEL_TRACE:
std::clog << color(blue);
break;
}
std::clog << ptr->msg << color(reset) << std::endl;
}
} }
} }
void logger::start() { void logger::start() {
#if defined(CAF_LOG_LEVEL) && CAF_LOG_LEVEL >= CAF_LOG_LEVEL_INFO #if defined(CAF_LOG_LEVEL)
const char* log_level_table[] = {"ERROR", "WARN", "INFO", "DEBUG", "TRACE"}; auto& lvl = system_.config().logger_verbosity;
if (lvl == atom("QUIET"))
return;
if (lvl == atom("ERROR"))
level_ = CAF_LOG_LEVEL_ERROR;
else if (lvl == atom("WARNING"))
level_ = CAF_LOG_LEVEL_WARNING;
else if (lvl == atom("INFO"))
level_ = CAF_LOG_LEVEL_INFO;
else if (lvl == atom("DEBUG"))
level_ = CAF_LOG_LEVEL_DEBUG;
else if (lvl == atom("TRACE"))
level_ = CAF_LOG_LEVEL_TRACE;
else
level_ = CAF_LOG_LEVEL;
thread_ = std::thread{[this] { this->run(); }}; thread_ = std::thread{[this] { this->run(); }};
std::string msg = "ENTRY log level = "; std::string msg = "ENTRY log level = ";
msg += log_level_table[global_log_level]; const char* levels[] = {"ERROR", "WARNING", "INFO", "DEBUG", "TRACE"};
msg += levels[level_];
log(CAF_LOG_LEVEL_INFO, "caf", "caf::logger", "run", __FILE__, __LINE__, msg); log(CAF_LOG_LEVEL_INFO, "caf", "caf::logger", "run", __FILE__, __LINE__, msg);
#endif #endif
} }
void logger::stop() { void logger::stop() {
#if defined(CAF_LOG_LEVEL) && CAF_LOG_LEVEL >= CAF_LOG_LEVEL_INFO #if defined(CAF_LOG_LEVEL)
log(CAF_LOG_LEVEL_INFO, "caf", "caf::logger", "run", __FILE__, __LINE__, "EXIT"); if (!thread_.joinable())
return;
log(CAF_LOG_LEVEL_INFO, "caf", "caf::logger", "run", __FILE__, __LINE__,
"EXIT");
// an empty string means: shut down // an empty string means: shut down
queue_.synchronized_enqueue(queue_mtx_, queue_cv_, new event{""}); queue_.synchronized_enqueue(queue_mtx_, queue_cv_, new event);
thread_.join(); thread_.join();
#endif #endif
} }
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <iostream> #include <iostream>
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/color.hpp"
#include "caf/optional.hpp" #include "caf/optional.hpp"
#include "caf/deep_to_string.hpp" #include "caf/deep_to_string.hpp"
...@@ -213,23 +214,6 @@ private: ...@@ -213,23 +214,6 @@ private:
std::mutex file_mtx_; std::mutex file_mtx_;
}; };
enum color_face {
normal,
bold
};
enum color_value {
reset,
black,
red,
green,
yellow,
blue,
magenta,
cyan,
white
};
/// Drives unit test execution. /// Drives unit test execution.
class engine { class engine {
public: public:
...@@ -310,17 +294,7 @@ private: ...@@ -310,17 +294,7 @@ private:
int argc_ = 0; int argc_ = 0;
char** argv_ = nullptr; char** argv_ = nullptr;
char* path_ = nullptr; char* path_ = nullptr;
const char* colors_[9][2] = { bool colorize_ = false;
{"\033[0m", "\033[0m"}, // reset
{"\033[30m", "\033[1m\033[30m"}, // black
{"\033[31m", "\033[1m\033[31m"}, // red
{"\033[32m", "\033[1m\033[32m"}, // green
{"\033[33m", "\033[1m\033[33m"}, // yellow
{"\033[34m", "\033[1m\033[34m"}, // blue
{"\033[35m", "\033[1m\033[35m"}, // magenta
{"\033[36m", "\033[1m\033[36m"}, // cyan
{"\033[37m", "\033[1m\033[37m"} // white
};
const char* check_file_ = "<none>"; const char* check_file_ = "<none>";
size_t check_line_ = 0; size_t check_line_ = 0;
test* current_test_ = nullptr; test* current_test_ = nullptr;
...@@ -413,8 +387,8 @@ using caf_test_case_auto_fixture = caf::test::dummy_fixture; ...@@ -413,8 +387,8 @@ using caf_test_case_auto_fixture = caf::test::dummy_fixture;
#define CAF_TEST_PRINT(level, msg, colorcode) \ #define CAF_TEST_PRINT(level, msg, colorcode) \
(::caf::test::logger::instance(). level () \ (::caf::test::logger::instance(). level () \
<< ::caf::test::engine::color(::caf::test:: colorcode ) \ << ::caf::test::engine::color(::caf:: colorcode ) \
<< " -> " << ::caf::test::engine::color(::caf::test::reset) << msg \ << " -> " << ::caf::test::engine::color(::caf::reset) << msg \
<< " [line " << __LINE__ << "]\n") << " [line " << __LINE__ << "]\n")
#define CAF_TEST_PRINT_ERROR(msg) CAF_TEST_PRINT(info, msg, red) #define CAF_TEST_PRINT_ERROR(msg) CAF_TEST_PRINT(info, msg, red)
......
...@@ -316,13 +316,7 @@ bool engine::run(bool colorize, ...@@ -316,13 +316,7 @@ bool engine::run(bool colorize,
// nothing to do // nothing to do
return true; return true;
} }
if (!colorize) { instance().colorize_ = colorize;
for (size_t i = 0; i <= static_cast<size_t>(white); ++i) {
for (size_t j = 0; j <= static_cast<size_t>(bold); ++j) {
instance().colors_[i][j] = "";
}
}
}
if (!logger::init(verbosity_console, verbosity_file, log_file)) { if (!logger::init(verbosity_console, verbosity_file, log_file)) {
return false; return false;
} }
...@@ -475,7 +469,7 @@ bool engine::run(bool colorize, ...@@ -475,7 +469,7 @@ bool engine::run(bool colorize,
} }
const char* engine::color(color_value v, color_face t) { const char* engine::color(color_value v, color_face t) {
return instance().colors_[static_cast<size_t>(v)][static_cast<size_t>(t)]; return instance().colorize_ ? caf::color(v, t) : "";
} }
const char* engine::last_check_file() { const char* engine::last_check_file() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment