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
src/behavior_impl.cpp
src/blocking_actor.cpp
src/blocking_behavior.cpp
src/color.cpp
src/concatenated_tuple.cpp
src/config_option.cpp
src/continue_helper.cpp
......
......@@ -255,9 +255,8 @@ public:
// -- config parameters for the logger ---------------------------------------
std::string logger_filename;
std::string logger_verbosity;
bool logger_console;
bool logger_colorize;
atom_value logger_verbosity;
atom_value logger_console;
// -- 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 @@
#include "caf/actor_system_config.hpp"
#include <ctime>
#include <limits>
#include <thread>
#include <fstream>
......@@ -27,7 +26,6 @@
#include "caf/message_builder.hpp"
#include "caf/detail/get_process_id.hpp"
#include "caf/detail/parse_ini.hpp"
namespace caf {
......@@ -98,14 +96,8 @@ actor_system_config::actor_system_config()
work_stealing_moderate_sleep_duration_us = 50;
work_stealing_relaxed_steal_interval = 1;
work_stealing_relaxed_sleep_duration_us = 10000;
std::ostringstream default_filename;
default_filename << "actor_log_" << detail::get_process_id()
<< "_" << time(0)
<< "_[NODE]" // dynamic placeholder for the node ID
<< ".log";
logger_filename = default_filename.str();
logger_console = false;
logger_colorize = false;
logger_filename = "actor_log_[PID]_[TIMESTAMP]_[NODE].log";
logger_console = atom("NONE");
middleman_network_backend = atom("default");
middleman_enable_automatic_connections = false;
middleman_max_consecutive_reads = 50;
......@@ -145,9 +137,7 @@ actor_system_config::actor_system_config()
.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_colorize, "colorize",
"colorizes console output (ignored on Windows)");
"enables logging to the console via std::clog");
opt_group{options_, "middleman"}
.add(middleman_network_backend, "network-backend",
"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 @@
#include "caf/logger.hpp"
#include <ctime>
#include <thread>
#include <cstring>
#include <fstream>
......@@ -35,11 +36,13 @@
#include "caf/string_algorithms.hpp"
#include "caf/color.hpp"
#include "caf/locks.hpp"
#include "caf/actor_proxy.hpp"
#include "caf/actor_system.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/detail/get_process_id.hpp"
#include "caf/detail/single_reader_queue.hpp"
namespace caf {
......@@ -54,31 +57,6 @@ constexpr const char* log_level_name[] = {
"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
static_assert(CAF_LOG_LEVEL >= 0 && CAF_LOG_LEVEL <= 4,
"assertion: 0 <= CAF_LOG_LEVEL <= 4");
......@@ -247,7 +225,7 @@ void logger::log(int level, const char* component,
const std::string& class_name, const char* function_name,
const char* c_full_file_name, int line_num,
const std::string& msg) {
CAF_ASSERT(level <= 4);
CAF_ASSERT(level >= 0 && level <= 4);
if (level > level_)
return;
std::string file_name;
......@@ -300,15 +278,27 @@ logger::logger(actor_system& sys) : system_(sys) {
}
void logger::run() {
auto filename = system_.config().logger_filename;
// Replace node ID placeholder.
auto placeholder = std::string{"[NODE]"};
auto i = filename.find(placeholder);
if (i != std::string::npos) {
auto f = system_.config().logger_filename;
// Replace placeholders.
const char pid[] = "[PID]";
auto i = std::search(f.begin(), f.end(), std::begin(pid), std::end(pid) - 1);
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());
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;
for (;;) {
// make sure we have data to read
......@@ -321,57 +311,53 @@ void logger::run() {
return;
}
out << ptr->prefix << ' ' << ptr->msg << std::endl;
if (system_.config().logger_console) {
#ifndef CAF_MSVC
if (system_.config().logger_colorize) {
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;
std::clog << color(red);
break;
case CAF_LOG_LEVEL_WARNING:
std::clog << color::yellow;
std::clog << color(yellow);
break;
case CAF_LOG_LEVEL_INFO:
std::clog << color::green;
std::clog << color(green);
break;
case CAF_LOG_LEVEL_DEBUG:
std::clog << color::cyan;
std::clog << color(cyan);
break;
case CAF_LOG_LEVEL_TRACE:
std::clog << color::blue;
std::clog << color(blue);
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() {
#if defined(CAF_LOG_LEVEL)
const char* levels[] = {"ERROR", "WARNING", "INFO", "DEBUG", "TRACE"};
auto& lvl = system_.config().logger_verbosity;
if (lvl == "QUIET")
if (lvl == atom("QUIET"))
return;
if (lvl.empty()) {
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
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_ = static_cast<int>(std::distance(std::begin(levels), i));
CAF_ASSERT(level_ >= CAF_LOG_LEVEL_ERROR && level_ <= CAF_LOG_LEVEL_TRACE);
}
level_ = CAF_LOG_LEVEL;
thread_ = std::thread{[this] { this->run(); }};
std::string msg = "ENTRY 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);
#endif
......@@ -384,7 +370,7 @@ void logger::stop() {
log(CAF_LOG_LEVEL_INFO, "caf", "caf::logger", "run", __FILE__, __LINE__,
"EXIT");
// 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();
#endif
}
......
......@@ -32,6 +32,7 @@
#include <iostream>
#include "caf/fwd.hpp"
#include "caf/color.hpp"
#include "caf/optional.hpp"
#include "caf/deep_to_string.hpp"
......@@ -213,23 +214,6 @@ private:
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.
class engine {
public:
......@@ -310,17 +294,7 @@ private:
int argc_ = 0;
char** argv_ = nullptr;
char* path_ = nullptr;
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
};
bool colorize_ = false;
const char* check_file_ = "<none>";
size_t check_line_ = 0;
test* current_test_ = nullptr;
......@@ -413,8 +387,8 @@ using caf_test_case_auto_fixture = caf::test::dummy_fixture;
#define CAF_TEST_PRINT(level, msg, colorcode) \
(::caf::test::logger::instance(). level () \
<< ::caf::test::engine::color(::caf::test:: colorcode ) \
<< " -> " << ::caf::test::engine::color(::caf::test::reset) << msg \
<< ::caf::test::engine::color(::caf:: colorcode ) \
<< " -> " << ::caf::test::engine::color(::caf::reset) << msg \
<< " [line " << __LINE__ << "]\n")
#define CAF_TEST_PRINT_ERROR(msg) CAF_TEST_PRINT(info, msg, red)
......
......@@ -316,13 +316,7 @@ bool engine::run(bool colorize,
// nothing to do
return true;
}
if (!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] = "";
}
}
}
instance().colorize_ = colorize;
if (!logger::init(verbosity_console, verbosity_file, log_file)) {
return false;
}
......@@ -475,7 +469,7 @@ bool engine::run(bool colorize,
}
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() {
......
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