Commit 785cb3bd authored by Matthias Vallentin's avatar Matthias Vallentin

Unify color handling and streamline logger API

parent 700ce256
...@@ -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
......
...@@ -255,9 +255,8 @@ public: ...@@ -255,9 +255,8 @@ public:
// -- config parameters for the logger --------------------------------------- // -- config parameters for the logger ---------------------------------------
std::string logger_filename; std::string logger_filename;
std::string logger_verbosity; atom_value logger_verbosity;
bool logger_console; atom_value logger_console;
bool logger_colorize;
// -- config parameters of the middleman ------------------------------------- // -- config parameters of the middleman -------------------------------------
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include "caf/actor_system_config.hpp" #include "caf/actor_system_config.hpp"
#include <ctime>
#include <limits> #include <limits>
#include <thread> #include <thread>
#include <fstream> #include <fstream>
...@@ -27,7 +26,6 @@ ...@@ -27,7 +26,6 @@
#include "caf/message_builder.hpp" #include "caf/message_builder.hpp"
#include "caf/detail/get_process_id.hpp"
#include "caf/detail/parse_ini.hpp" #include "caf/detail/parse_ini.hpp"
namespace caf { namespace caf {
...@@ -98,14 +96,8 @@ actor_system_config::actor_system_config() ...@@ -98,14 +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;
std::ostringstream default_filename; logger_filename = "actor_log_[PID]_[TIMESTAMP]_[NODE].log";
default_filename << "actor_log_" << detail::get_process_id() logger_console = atom("NONE");
<< "_" << time(0)
<< "_[NODE]" // dynamic placeholder for the node ID
<< ".log";
logger_filename = default_filename.str();
logger_console = false;
logger_colorize = false;
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;
...@@ -145,9 +137,7 @@ actor_system_config::actor_system_config() ...@@ -145,9 +137,7 @@ actor_system_config::actor_system_config()
.add(logger_verbosity, "verbosity", .add(logger_verbosity, "verbosity",
"sets the verbosity (QUIET|ERROR|WARNING|INFO|DEBUG|TRACE)") "sets the verbosity (QUIET|ERROR|WARNING|INFO|DEBUG|TRACE)")
.add(logger_console, "console", .add(logger_console, "console",
"enables logging to the console via std::clog") "enables logging to the console via std::clog");
.add(logger_colorize, "colorize",
"colorizes console output (ignored on Windows)");
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
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "caf/logger.hpp" #include "caf/logger.hpp"
#include <ctime>
#include <thread> #include <thread>
#include <cstring> #include <cstring>
#include <fstream> #include <fstream>
...@@ -35,11 +36,13 @@ ...@@ -35,11 +36,13 @@
#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/actor_system_config.hpp"
#include "caf/detail/get_process_id.hpp"
#include "caf/detail/single_reader_queue.hpp" #include "caf/detail/single_reader_queue.hpp"
namespace caf { namespace caf {
...@@ -54,31 +57,6 @@ constexpr const char* log_level_name[] = { ...@@ -54,31 +57,6 @@ constexpr const char* log_level_name[] = {
"TRACE" "TRACE"
}; };
#ifndef CAF_MSVC
namespace color {
// UNIX terminal color codes
constexpr char reset[] = "\033[0m";
constexpr char black[] = "\033[30m";
constexpr char red[] = "\033[31m";
constexpr char green[] = "\033[32m";
constexpr char yellow[] = "\033[33m";
constexpr char blue[] = "\033[34m";
constexpr char magenta[] = "\033[35m";
constexpr char cyan[] = "\033[36m";
constexpr char white[] = "\033[37m";
constexpr char bold_black[] = "\033[1m\033[30m";
constexpr char bold_red[] = "\033[1m\033[31m";
constexpr char bold_green[] = "\033[1m\033[32m";
constexpr char bold_yellow[] = "\033[1m\033[33m";
constexpr char bold_blue[] = "\033[1m\033[34m";
constexpr char bold_magenta[] = "\033[1m\033[35m";
constexpr char bold_cyan[] = "\033[1m\033[36m";
constexpr char bold_white[] = "\033[1m\033[37m";
} // namespace color
#endif
#ifdef CAF_LOG_LEVEL #ifdef CAF_LOG_LEVEL
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");
...@@ -247,7 +225,7 @@ void logger::log(int level, const char* component, ...@@ -247,7 +225,7 @@ void logger::log(int level, const char* component,
const std::string& class_name, const char* function_name, const std::string& class_name, const char* function_name,
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 <= 4); CAF_ASSERT(level >= 0 && level <= 4);
if (level > level_) if (level > level_)
return; return;
std::string file_name; std::string file_name;
...@@ -300,15 +278,27 @@ logger::logger(actor_system& sys) : system_(sys) { ...@@ -300,15 +278,27 @@ logger::logger(actor_system& sys) : system_(sys) {
} }
void logger::run() { void logger::run() {
auto filename = system_.config().logger_filename; auto f = system_.config().logger_filename;
// Replace node ID placeholder. // Replace placeholders.
auto placeholder = std::string{"[NODE]"}; const char pid[] = "[PID]";
auto i = filename.find(placeholder); auto i = std::search(f.begin(), f.end(), std::begin(pid), std::end(pid) - 1);
if (i != std::string::npos) { 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()); auto nid = to_string(system_.node());
filename.replace(i, placeholder.size(), nid); f.replace(i, i + sizeof(node) - 1, nid);
} }
std::fstream out(filename, std::ios::out | std::ios::app); std::fstream out(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
...@@ -321,57 +311,53 @@ void logger::run() { ...@@ -321,57 +311,53 @@ void logger::run() {
return; return;
} }
out << ptr->prefix << ' ' << ptr->msg << std::endl; out << ptr->prefix << ' ' << ptr->msg << std::endl;
if (system_.config().logger_console) { if (system_.config().logger_console == atom("UNCOLORED")) {
#ifndef CAF_MSVC std::clog << ptr->msg << std::endl;
if (system_.config().logger_colorize) { } else if (system_.config().logger_console == atom("COLORED")) {
switch (ptr->level) { switch (ptr->level) {
default: default:
break; break;
case CAF_LOG_LEVEL_ERROR: case CAF_LOG_LEVEL_ERROR:
std::clog << color::red; std::clog << color(red);
break; break;
case CAF_LOG_LEVEL_WARNING: case CAF_LOG_LEVEL_WARNING:
std::clog << color::yellow; std::clog << color(yellow);
break; break;
case CAF_LOG_LEVEL_INFO: case CAF_LOG_LEVEL_INFO:
std::clog << color::green; std::clog << color(green);
break; break;
case CAF_LOG_LEVEL_DEBUG: case CAF_LOG_LEVEL_DEBUG:
std::clog << color::cyan; std::clog << color(cyan);
break; break;
case CAF_LOG_LEVEL_TRACE: case CAF_LOG_LEVEL_TRACE:
std::clog << color::blue; std::clog << color(blue);
break; break;
}
std::clog << ptr->msg << color::reset << std::endl;
} else {
#endif
std::clog << ptr->msg << std::endl;
#ifndef CAF_MSVC
} }
#endif std::clog << ptr->msg << color(reset) << std::endl;
} }
} }
} }
void logger::start() { void logger::start() {
#if defined(CAF_LOG_LEVEL) #if defined(CAF_LOG_LEVEL)
const char* levels[] = {"ERROR", "WARNING", "INFO", "DEBUG", "TRACE"};
auto& lvl = system_.config().logger_verbosity; auto& lvl = system_.config().logger_verbosity;
if (lvl == "QUIET") if (lvl == atom("QUIET"))
return; return;
if (lvl.empty()) { 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; level_ = CAF_LOG_LEVEL;
} else {
auto i = std::find(std::begin(levels), std::end(levels), lvl);
if (i == std::end(levels))
level_ = CAF_LOG_LEVEL; // ignore invalid log levels
else
level_ = static_cast<int>(std::distance(std::begin(levels), i));
CAF_ASSERT(level_ >= CAF_LOG_LEVEL_ERROR && level_ <= CAF_LOG_LEVEL_TRACE);
}
thread_ = std::thread{[this] { this->run(); }}; thread_ = std::thread{[this] { this->run(); }};
std::string msg = "ENTRY log level = "; std::string msg = "ENTRY log level = ";
const char* levels[] = {"ERROR", "WARNING", "INFO", "DEBUG", "TRACE"};
msg += levels[level_]; 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
...@@ -384,7 +370,7 @@ void logger::stop() { ...@@ -384,7 +370,7 @@ void logger::stop() {
log(CAF_LOG_LEVEL_INFO, "caf", "caf::logger", "run", __FILE__, __LINE__, log(CAF_LOG_LEVEL_INFO, "caf", "caf::logger", "run", __FILE__, __LINE__,
"EXIT"); "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