Commit c736d978 authored by Dominik Charousset's avatar Dominik Charousset Committed by Dominik Charousset

Allow apps to always use the caf::logger

Currently, the CAF logger is only available if CAF was compiled with
non-quiet log level. This change allows applications to use the CAF
logger regardless of the build config.
parent fe48cbb6
......@@ -320,6 +320,8 @@ private:
void init(actor_system_config& cfg);
bool open_file();
// -- event handling ---------------------------------------------------------
void handle_event(const event& x);
......@@ -375,6 +377,9 @@ private:
// Filled with log events by other threads.
detail::ringbuffer<event, queue_size> queue_;
// Stores the assembled name of the log file.
std::string file_name_;
// Executes `logger::run`.
std::thread thread_;
};
......@@ -435,25 +440,6 @@ bool operator==(const logger::field& x, const logger::field& y);
// -- logging macros -----------------------------------------------------------
#if CAF_LOG_LEVEL == CAF_LOG_LEVEL_QUIET
#define CAF_LOG_IMPL(unused1, unused2, unused3)
// placeholder macros when compiling without logging
inline caf::actor_id caf_set_aid_dummy() { return 0; }
#define CAF_PUSH_AID(unused) CAF_VOID_STMT
#define CAF_PUSH_AID_FROM_PTR(unused) CAF_VOID_STMT
#define CAF_SET_AID(unused) caf_set_aid_dummy()
#define CAF_SET_LOGGER_SYS(unused) CAF_VOID_STMT
#define CAF_LOG_TRACE(unused)
#else // CAF_LOG_LEVEL == CAF_LOG_LEVEL_QUIET
#define CAF_LOG_IMPL(component, loglvl, message) \
do { \
auto CAF_UNIFYN(caf_logger) = caf::logger::current_logger(); \
......@@ -518,8 +504,6 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; }
#define CAF_LOG_ERROR(output) \
CAF_LOG_IMPL(CAF_LOG_COMPONENT, CAF_LOG_LEVEL_ERROR, output)
#endif // CAF_LOG_LEVEL == CAF_LOG_LEVEL_QUIET
#ifndef CAF_LOG_INFO
#define CAF_LOG_INFO(output) CAF_VOID_STMT
#define CAF_LOG_INFO_IF(cond, output) CAF_VOID_STMT
......
......@@ -188,8 +188,6 @@ string_view reduce_symbol(std::ostream& out, string_view symbol) {
return symbol;
}
#if CAF_LOG_LEVEL >= 0
#if defined(CAF_NO_THREAD_LOCAL)
pthread_key_t s_key;
......@@ -232,17 +230,6 @@ inline logger* get_current_logger() {
#endif // CAF_NO_THREAD_LOCAL
#else // CAF_LOG_LEVEL
inline void set_current_logger(logger*) {
// nop
}
inline logger* get_current_logger() {
return nullptr;
}
#endif // CAF_LOG_LEVEL
} // namespace <anonymous>
logger::config::config()
......@@ -358,7 +345,7 @@ bool logger::accepts(unsigned level, atom_value cname) {
[=](atom_value name) { return name == cname; });
}
logger::logger(actor_system& sys) : system_(sys) {
logger::logger(actor_system& sys) : system_(sys), t0_(make_timestamp()) {
// nop
}
......@@ -404,6 +391,17 @@ void logger::init(actor_system_config& cfg) {
}
}
bool logger::open_file() {
if (file_verbosity() == CAF_LOG_LEVEL_QUIET || file_name_.empty())
return false;
file_.open(file_name_, std::ios::out | std::ios::app);
if (!file_) {
std::cerr << "unable to open log file " << file_name_ << std::endl;
return false;
}
return true;
}
void logger::render_fun_prefix(std::ostream& out, const event& x) {
// Extract the prefix of a function name. For example:
// virtual std::vector<int> my::namespace::foo(int);
......@@ -550,6 +548,8 @@ void logger::run() {
queue_.wait_nonempty();
if (queue_.front().message.empty())
return;
if (!open_file() && console_verbosity() == CAF_LOG_LEVEL_QUIET)
return;
log_first_line();
// Loop until receiving an empty message.
for (;;) {
......@@ -635,49 +635,48 @@ void logger::start() {
parent_thread_ = std::this_thread::get_id();
if (verbosity() == CAF_LOG_LEVEL_QUIET)
return;
t0_ = make_timestamp();
auto f = get_or(system_.config(), "logger.file-name",
file_name_ = get_or(system_.config(), "logger.file-name",
defaults::logger::file_name);
if (f.empty()) {
if (file_name_.empty()) {
// No need to continue if console and log file are disabled.
if (console_verbosity() == CAF_LOG_LEVEL_QUIET)
return;
} else {
// Replace placeholders.
const char pid[] = "[PID]";
auto i = std::search(f.begin(), f.end(), std::begin(pid),
auto i = std::search(file_name_.begin(), file_name_.end(), std::begin(pid),
std::end(pid) - 1);
if (i != f.end()) {
if (i != file_name_.end()) {
auto id = std::to_string(detail::get_process_id());
f.replace(i, i + sizeof(pid) - 1, id);
file_name_.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()) {
i = std::search(file_name_.begin(), file_name_.end(), std::begin(ts),
std::end(ts) - 1);
if (i != file_name_.end()) {
auto t0_str = timestamp_to_string(t0_);
f.replace(i, i + sizeof(ts) - 1, t0_str);
file_name_.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()) {
i = std::search(file_name_.begin(), file_name_.end(), std::begin(node),
std::end(node) - 1);
if (i != file_name_.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;
file_name_.replace(i, i + sizeof(node) - 1, nid);
}
}
if (cfg_.inline_output)
if (cfg_.inline_output) {
// Open file immediately for inline output.
open_file();
log_first_line();
else
} else {
thread_ = std::thread{[this] {
detail::set_thread_name("caf.logger");
this->system_.thread_started();
this->run();
this->system_.thread_terminates();
}};
}
}
void logger::stop() {
......
......@@ -121,7 +121,7 @@ CAF_TEST(counting_system_without_actor) {
assumed_init_calls = 1;
assumed_thread_count = get_or(cfg, "scheduler.max-threads",
defaults::scheduler::max_threads)
+ 1; // caf.clock thread
+ 2; // caf.clock and caf.logger
auto& sched = sys.scheduler();
if (sched.detaches_utility_actors())
assumed_thread_count += sched.num_utility_actors();
......@@ -131,7 +131,7 @@ CAF_TEST(counting_system_with_actor) {
assumed_init_calls = 1;
assumed_thread_count = get_or(cfg, "scheduler.max-threads",
defaults::scheduler::max_threads)
+ 2; // caf.clock thread plus detached actor
+ 3; // caf.clock, caf.logger, and detached actor
auto& sched = sys.scheduler();
if (sched.detaches_utility_actors())
assumed_thread_count += sched.num_utility_actors();
......
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