Commit e7aa36c2 authored by Dominik Charousset's avatar Dominik Charousset

Streamline logging implementation

- use `deep_to_string` for building log lines whenever possible
- remove unused state in line builder and unit test output stream
- add a new arg wrapper to log ranges from iterator pairs
- provide a to_string for arg wrappers to avoid code duplication
parent ac0246da
...@@ -18,25 +18,76 @@ ...@@ -18,25 +18,76 @@
#pragma once #pragma once
#include <string>
#include "caf/deep_to_string.hpp"
namespace caf { namespace caf {
namespace detail { namespace detail {
/// Enables automagical string conversion for `CAF_ARG`. /// Enables automagical string conversion for `CAF_ARG`.
template <class T> template <class T>
struct arg_wrapper { struct single_arg_wrapper {
const char* name; const char* name;
const T& value; const T& value;
arg_wrapper(const char* x, const T& y) : name(x), value(y) { single_arg_wrapper(const char* x, const T& y) : name(x), value(y) {
// nop // nop
} }
}; };
template <class T>
std::string to_string(const single_arg_wrapper<T>& x) {
std::string result = x.name;
result += " = ";
result += deep_to_string(x.value);
return result;
}
template <class Iterator>
struct range_arg_wrapper {
const char* name;
Iterator first;
Iterator last;
range_arg_wrapper(const char* x, Iterator begin, Iterator end)
: name(x),
first(begin),
last(end) {
// nop
}
};
template <class Iterator>
std::string to_string(const range_arg_wrapper<Iterator>& x) {
std::string result = x.name;
result += " = ";
struct dummy {
Iterator first;
Iterator last;
Iterator begin() const {
return first;
}
Iterator end() const {
return last;
}
};
dummy y{x.first, x.last};
result += deep_to_string(y);
return result;
}
/// Used to implement `CAF_ARG`. /// Used to implement `CAF_ARG`.
template <class T> template <class T>
arg_wrapper<T> make_arg_wrapper(const char* name, const T& value) { single_arg_wrapper<T> make_arg_wrapper(const char* name, const T& value) {
return {name, value}; return {name, value};
} }
/// Used to implement `CAF_ARG`.
template <class Iterator>
range_arg_wrapper<Iterator> make_arg_wrapper(const char* name, Iterator first,
Iterator last) {
return {name, first, last};
}
} // namespace detail } // namespace detail
} // namespace caf } // namespace caf
...@@ -168,36 +168,26 @@ public: ...@@ -168,36 +168,26 @@ public:
line_builder(); line_builder();
template <class T> template <class T>
line_builder& operator<<(const T& x) { detail::enable_if_t<!std::is_pointer<T>::value, line_builder&>
operator<<(const T& x) {
if (!str_.empty()) if (!str_.empty())
str_ += " "; str_ += " ";
str_ += deep_to_string(x); str_ += deep_to_string(x);
behind_arg_ = false;
return *this; return *this;
} }
template <class T> line_builder& operator<<(const local_actor* self);
line_builder& operator<<(const detail::arg_wrapper<T>& x) {
if (behind_arg_)
str_ += ", ";
else if (!str_.empty())
str_ += " ";
str_ += x.name;
str_ += " = ";
str_ += deep_to_string(x.value);
behind_arg_ = true;
return *this;
}
line_builder& operator<<(const std::string& str); line_builder& operator<<(const std::string& str);
line_builder& operator<<(const char* str); line_builder& operator<<(const char* str);
line_builder& operator<<(char x);
std::string get() const; std::string get() const;
private: private:
std::string str_; std::string str_;
bool behind_arg_;
}; };
/// Returns the ID of the actor currently associated to the calling thread. /// Returns the ID of the actor currently associated to the calling thread.
...@@ -337,6 +327,9 @@ bool operator==(const logger::field& x, const logger::field& y); ...@@ -337,6 +327,9 @@ bool operator==(const logger::field& x, const logger::field& y);
#define CAF_ARG2(argname, argval) caf::detail::make_arg_wrapper(argname, argval) #define CAF_ARG2(argname, argval) caf::detail::make_arg_wrapper(argname, argval)
#define CAF_ARG3(argname, first, last) \
caf::detail::make_arg_wrapper(argname, first, last)
#ifdef CAF_MSVC #ifdef CAF_MSVC
#define CAF_PRETTY_FUN __FUNCSIG__ #define CAF_PRETTY_FUN __FUNCSIG__
#else // CAF_MSVC #else // CAF_MSVC
......
...@@ -28,13 +28,14 @@ ...@@ -28,13 +28,14 @@
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/term.hpp"
#include "caf/locks.hpp"
#include "caf/timestamp.hpp"
#include "caf/actor_proxy.hpp" #include "caf/actor_proxy.hpp"
#include "caf/actor_system.hpp" #include "caf/actor_system.hpp"
#include "caf/string_algorithms.hpp"
#include "caf/actor_system_config.hpp" #include "caf/actor_system_config.hpp"
#include "caf/local_actor.hpp"
#include "caf/locks.hpp"
#include "caf/string_algorithms.hpp"
#include "caf/term.hpp"
#include "caf/timestamp.hpp"
#include "caf/intrusive/task_result.hpp" #include "caf/intrusive/task_result.hpp"
...@@ -128,15 +129,22 @@ logger::event::event(int lvl, const char* cat, const char* fun, const char* fn, ...@@ -128,15 +129,22 @@ logger::event::event(int lvl, const char* cat, const char* fun, const char* fn,
// nop // nop
} }
logger::line_builder::line_builder() : behind_arg_(false) { logger::line_builder::line_builder() {
// nop // nop
} }
logger::line_builder& logger::line_builder::
operator<<(const local_actor* self) {
if (!str_.empty() && str_.back() != ' ')
str_ += " ";
str_ += self->name();
return *this;
}
logger::line_builder& logger::line_builder::operator<<(const std::string& str) { logger::line_builder& logger::line_builder::operator<<(const std::string& str) {
if (!str_.empty()) if (!str_.empty() && str_.back() != ' ')
str_ += " "; str_ += " ";
str_ += str; str_ += str;
behind_arg_ = false;
return *this; return *this;
} }
...@@ -144,7 +152,13 @@ logger::line_builder& logger::line_builder::operator<<(const char* str) { ...@@ -144,7 +152,13 @@ logger::line_builder& logger::line_builder::operator<<(const char* str) {
if (!str_.empty()) if (!str_.empty())
str_ += " "; str_ += " ";
str_ += str; str_ += str;
behind_arg_ = false; return *this;
}
logger::line_builder& logger::line_builder::operator<<(char x) {
if (!str_.empty())
str_ += " ";
str_ += x;
return *this; return *this;
} }
......
...@@ -53,21 +53,12 @@ namespace { ...@@ -53,21 +53,12 @@ namespace {
struct print_with_comma_t { struct print_with_comma_t {
bool first = true; bool first = true;
template <class T> template <class T>
std::ostream& operator()(std::ostream& out, const T& x) { std::ostream& operator()(std::ostream& out, const T& x) {
if (!first) if (!first)
out << ", "; out << ", ";
else else
first = false; first = false;
return out << x; return out << deep_to_string(x);
}
template <class T>
std::ostream& operator()(std::ostream& out, const detail::arg_wrapper<T>& x) {
if (!first)
out << ", ";
else
first = false;
return out << x.name << " = " << deep_to_string(x.value);
} }
}; };
......
...@@ -97,16 +97,7 @@ struct print_with_comma_t { ...@@ -97,16 +97,7 @@ struct print_with_comma_t {
out << ", "; out << ", ";
else else
first = false; first = false;
return out << x; return out << deep_to_string(x);
}
template <class T>
std::ostream& operator()(std::ostream& out, const detail::arg_wrapper<T>& x) {
if (!first)
out << ", ";
else
first = false;
return out << x.name << " = " << deep_to_string(x.value);
} }
}; };
......
...@@ -210,30 +210,29 @@ public: ...@@ -210,30 +210,29 @@ public:
struct reset_flags_t {}; struct reset_flags_t {};
stream& operator<<(reset_flags_t) { stream& operator<<(reset_flags_t) {
behind_text_ = false;
behind_arg_ = false;
return *this; return *this;
} }
template <class T> stream& operator<<(caf::term x) {
stream& operator<<(const T& x) {
parent_.log(lvl_, x); parent_.log(lvl_, x);
behind_text_ = true;
behind_arg_ = false;
return *this; return *this;
} }
template <class T> template <class T>
stream& operator<<(const caf::detail::arg_wrapper<T>& x) { stream& operator<<(const T& x) {
if (behind_arg_) struct simple_fwd_t {
parent_.log(lvl_, ", "); const T& operator()(const T& y) const {
else if (behind_text_) return y;
parent_.log(lvl_, " "); }
parent_.log(lvl_, x.name); };
parent_.log(lvl_, " = "); using fwd =
parent_.log(lvl_, deep_to_string(x.value)); typename std::conditional<
behind_text_ = false; std::is_same<char, T>::value || std::is_convertible<T, std::string>::value,
behind_arg_ = true; simple_fwd_t,
deep_to_string_t
>::type;
fwd f;
parent_.log(lvl_, f(x));
return *this; return *this;
} }
...@@ -245,8 +244,6 @@ public: ...@@ -245,8 +244,6 @@ public:
} }
private: private:
bool behind_text_;
bool behind_arg_;
logger& parent_; logger& parent_;
level lvl_; level lvl_;
}; };
......
...@@ -171,9 +171,7 @@ bool check(test* parent, const char *file, size_t line, ...@@ -171,9 +171,7 @@ bool check(test* parent, const char *file, size_t line,
} // namespace detail } // namespace detail
logger::stream::stream(logger& parent, logger::level lvl) logger::stream::stream(logger& parent, logger::level lvl)
: behind_text_(false), : parent_(parent),
behind_arg_(false),
parent_(parent),
lvl_(lvl) { lvl_(lvl) {
// nop // nop
} }
......
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