Commit 27f564bb authored by Dominik Charousset's avatar Dominik Charousset

Allow users to print log output inline

parent 4043f82a
...@@ -272,6 +272,7 @@ public: ...@@ -272,6 +272,7 @@ public:
std::string logger_console_format; std::string logger_console_format;
std::string logger_component_filter; std::string logger_component_filter;
atom_value logger_verbosity; atom_value logger_verbosity;
bool logger_inline_output;
// -- backward compatibility ------------------------------------------------- // -- backward compatibility -------------------------------------------------
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define CAF_LOGGER_HPP #define CAF_LOGGER_HPP
#include <thread> #include <thread>
#include <fstream>
#include <cstring> #include <cstring>
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
...@@ -252,6 +253,12 @@ public: ...@@ -252,6 +253,12 @@ public:
} }
private: private:
void handle_event(event& x);
void log_first_line();
void log_last_line();
logger(actor_system& sys); logger(actor_system& sys);
void init(actor_system_config& cfg); void init(actor_system_config& cfg);
...@@ -264,6 +271,7 @@ private: ...@@ -264,6 +271,7 @@ private:
actor_system& system_; actor_system& system_;
int level_; int level_;
bool inline_output_;
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_;
...@@ -274,6 +282,7 @@ private: ...@@ -274,6 +282,7 @@ private:
timestamp t0_; timestamp t0_;
line_format file_format_; line_format file_format_;
line_format console_format_; line_format console_format_;
std::fstream file_;
}; };
std::string to_string(logger::field_type x); std::string to_string(logger::field_type x);
......
...@@ -267,6 +267,7 @@ actor_system::actor_system(actor_system_config& cfg) ...@@ -267,6 +267,7 @@ actor_system::actor_system(actor_system_config& cfg)
// initialize state for each module and give each module the opportunity // initialize state for each module and give each module the opportunity
// to influence the system configuration, e.g., by adding more types // to influence the system configuration, e.g., by adding more types
logger_->init(cfg); logger_->init(cfg);
CAF_SET_LOGGER_SYS(this);
for (auto& mod : modules_) for (auto& mod : modules_)
if (mod) if (mod)
mod->init(cfg); mod->init(cfg);
......
...@@ -128,6 +128,7 @@ actor_system_config::actor_system_config() ...@@ -128,6 +128,7 @@ actor_system_config::actor_system_config()
logger_console = atom("none"); logger_console = atom("none");
logger_console_format = "%m"; logger_console_format = "%m";
logger_verbosity = atom("trace"); logger_verbosity = atom("trace");
logger_inline_output = 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;
...@@ -174,6 +175,8 @@ actor_system_config::actor_system_config() ...@@ -174,6 +175,8 @@ actor_system_config::actor_system_config()
"exclude all listed components from logging") "exclude all listed components from logging")
.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_inline_output, "inline-output",
"sets whether a separate thread is used for I/O")
.add(logger_file_name, "filename", .add(logger_file_name, "filename",
"deprecated (use file-name instead)") "deprecated (use file-name instead)")
.add(logger_component_filter, "filter", .add(logger_component_filter, "filter",
......
...@@ -165,7 +165,12 @@ actor_id logger::thread_local_aid(actor_id aid) { ...@@ -165,7 +165,12 @@ actor_id logger::thread_local_aid(actor_id aid) {
void logger::log(event* x) { void logger::log(event* x) {
CAF_ASSERT(x->level >= 0 && x->level <= 4); CAF_ASSERT(x->level >= 0 && x->level <= 4);
if (!inline_output_) {
queue_.synchronized_enqueue(queue_mtx_, queue_cv_,x); queue_.synchronized_enqueue(queue_mtx_, queue_cv_,x);
} else {
std::unique_ptr<event> ptr{x};
handle_event(*ptr);
}
} }
void logger::set_current_actor_system(actor_system* x) { void logger::set_current_actor_system(actor_system* x) {
...@@ -199,14 +204,15 @@ logger::~logger() { ...@@ -199,14 +204,15 @@ logger::~logger() {
system_.logger_dtor_cv_.notify_one(); system_.logger_dtor_cv_.notify_one();
} }
logger::logger(actor_system& sys) : system_(sys) { logger::logger(actor_system& sys) : system_(sys), inline_output_(false) {
// nop // nop
} }
void logger::init(actor_system_config& cfg) { void logger::init(actor_system_config& cfg) {
CAF_IGNORE_UNUSED(cfg); CAF_IGNORE_UNUSED(cfg);
#if defined(CAF_LOG_LEVEL) #if defined(CAF_LOG_LEVEL)
// Parse the configured log leve. inline_output_ = cfg.logger_inline_output;
// Parse the configured log level.
switch (static_cast<uint64_t>(cfg.logger_verbosity)) { switch (static_cast<uint64_t>(cfg.logger_verbosity)) {
case atom_uint("error"): case atom_uint("error"):
case atom_uint("ERROR"): case atom_uint("ERROR"):
...@@ -368,60 +374,7 @@ logger::line_format logger::parse_format(const char* format_str) { ...@@ -368,60 +374,7 @@ logger::line_format logger::parse_format(const char* format_str) {
void logger::run() { void logger::run() {
#if defined(CAF_LOG_LEVEL) #if defined(CAF_LOG_LEVEL)
t0_ = make_timestamp(); log_first_line();
std::fstream file;
if (system_.config().logger_file_name.empty()) {
// No need to continue if console and log file are disabled.
if (!(system_.config().logger_console == atom("UNCOLORED")
|| system_.config().logger_console == atom("COLORED")))
return;
} else {
auto f = system_.config().logger_file_name;
// 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 t0_str = timestamp_to_string(t0_);
f.replace(i, i + sizeof(ts) - 1, t0_str);
}
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);
}
file.open(f, std::ios::out | std::ios::app);
if (!file) {
std::cerr << "unable to open log file " << f << std::endl;
return;
}
}
if (file) {
// log first entry
std::string msg = "level = ";
msg += to_string(system_.config().logger_verbosity);
msg += ", node = ";
msg += to_string(system_.node());
event tmp{nullptr,
nullptr,
CAF_LOG_LEVEL_INFO,
CAF_LOG_COMPONENT,
CAF_PRETTY_FUN,
__FILE__,
__LINE__,
std::move(msg),
std::this_thread::get_id(),
0,
make_timestamp()};
render(file, file_format_, tmp);
}
// receive log entries from other threads and actors // receive log entries from other threads and actors
std::unique_ptr<event> ptr; std::unique_ptr<event> ptr;
for (;;) { for (;;) {
...@@ -431,15 +384,21 @@ void logger::run() { ...@@ -431,15 +384,21 @@ void logger::run() {
ptr.reset(queue_.try_pop()); ptr.reset(queue_.try_pop());
CAF_ASSERT(ptr != nullptr); CAF_ASSERT(ptr != nullptr);
// empty message means: shut down // empty message means: shut down
if (ptr->message.empty()) { if (ptr->message.empty())
break; break;
handle_event(*ptr);
} }
if (file) log_last_line();
render(file, file_format_, *ptr);; #endif
}
void logger::handle_event(event& x) {
if (file_)
render(file_, file_format_, x);
if (system_.config().logger_console == atom("UNCOLORED")) { if (system_.config().logger_console == atom("UNCOLORED")) {
render(std::clog, console_format_, *ptr); render(std::clog, console_format_, x);
} else if (system_.config().logger_console == atom("COLORED")) { } else if (system_.config().logger_console == atom("COLORED")) {
switch (ptr->level) { switch (x.level) {
default: default:
break; break;
case CAF_LOG_LEVEL_ERROR: case CAF_LOG_LEVEL_ERROR:
...@@ -458,11 +417,31 @@ void logger::run() { ...@@ -458,11 +417,31 @@ void logger::run() {
std::clog << term::blue; std::clog << term::blue;
break; break;
} }
render(std::clog, console_format_, *ptr); render(std::clog, console_format_, x);
std::clog << term::reset_endl; std::clog << term::reset_endl;
} }
} }
if (file) {
void logger::log_first_line() {
std::string msg = "level = ";
msg += to_string(system_.config().logger_verbosity);
msg += ", node = ";
msg += to_string(system_.node());
event tmp{nullptr,
nullptr,
CAF_LOG_LEVEL_INFO,
CAF_LOG_COMPONENT,
CAF_PRETTY_FUN,
__FILE__,
__LINE__,
std::move(msg),
std::this_thread::get_id(),
0,
make_timestamp()};
handle_event(tmp);
}
void logger::log_last_line() {
event tmp{nullptr, event tmp{nullptr,
nullptr, nullptr,
CAF_LOG_LEVEL_INFO, CAF_LOG_LEVEL_INFO,
...@@ -474,9 +453,7 @@ void logger::run() { ...@@ -474,9 +453,7 @@ void logger::run() {
std::this_thread::get_id(), std::this_thread::get_id(),
0, 0,
make_timestamp()}; make_timestamp()};
render(file, file_format_, tmp); handle_event(tmp);
}
#endif
} }
void logger::start() { void logger::start() {
...@@ -485,12 +462,53 @@ void logger::start() { ...@@ -485,12 +462,53 @@ void logger::start() {
auto verbosity = system_.config().logger_verbosity; auto verbosity = system_.config().logger_verbosity;
if (verbosity == atom("quiet") || verbosity == atom("QUIET")) if (verbosity == atom("quiet") || verbosity == atom("QUIET"))
return; return;
t0_ = make_timestamp();
if (system_.config().logger_file_name.empty()) {
// No need to continue if console and log file are disabled.
if (!(system_.config().logger_console == atom("UNCOLORED")
|| system_.config().logger_console == atom("COLORED")))
return;
} else {
auto f = system_.config().logger_file_name;
// 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 t0_str = timestamp_to_string(t0_);
f.replace(i, i + sizeof(ts) - 1, t0_str);
}
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);
}
file_.open(f, std::ios::out | std::ios::app);
if (!file_) {
std::cerr << "unable to open log file " << f << std::endl;
return;
}
}
if (inline_output_)
log_first_line();
else
thread_ = std::thread{[this] { this->run(); }}; thread_ = std::thread{[this] { this->run(); }};
#endif #endif
} }
void logger::stop() { void logger::stop() {
#if defined(CAF_LOG_LEVEL) #if defined(CAF_LOG_LEVEL)
if (inline_output_) {
log_last_line();
return;
}
if (!thread_.joinable()) if (!thread_.joinable())
return; return;
// an empty string means: shut down // an empty string means: shut down
......
...@@ -112,8 +112,10 @@ void test_coordinator::stop() { ...@@ -112,8 +112,10 @@ void test_coordinator::stop() {
} }
void test_coordinator::enqueue(resumable* ptr) { void test_coordinator::enqueue(resumable* ptr) {
CAF_LOG_TRACE("");
if (inline_enqueues_ > 0) { if (inline_enqueues_ > 0) {
--inline_enqueues_; --inline_enqueues_;
CAF_LOG_DEBUG("inline actor execution, remaining:" << inline_enqueues_);
dummy_worker worker{this}; dummy_worker worker{this};
switch (ptr->resume(&worker, 1)) { switch (ptr->resume(&worker, 1)) {
case resumable::resume_later: case resumable::resume_later:
......
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