|
|
@@ -21,41 +21,74 @@
|
|
|
#include "logger/message.h"
|
|
|
#include "pattern_layout.h"
|
|
|
|
|
|
-namespace logging {
|
|
|
- std::string fmt_time_with_milis(struct timeval, std::string const &);
|
|
|
- string_generator parse_date_format_string(char const *);
|
|
|
+namespace logging { namespace {
|
|
|
+ struct log_handle_gen : public format::generator_t {
|
|
|
+ std::string str(logpacket const & lp) const override {
|
|
|
+ return lp.logger;
|
|
|
+ }
|
|
|
+ void write(logpacket const & lp, std::ostream & os) const override {
|
|
|
+ os << lp.logger;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ struct level_gen : public format::generator_t {
|
|
|
+ std::string str(logpacket const & lp) const override {
|
|
|
+ return to_string(lp.level, true);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ struct message_gen : public format::generator_t {
|
|
|
+ std::string str(logpacket const & lp) const override {
|
|
|
+ return lp.message.str();
|
|
|
+ }
|
|
|
+ };
|
|
|
|
|
|
+ struct literal_gen : public format::generator_t {
|
|
|
+ literal_gen(std::string const & value) : value(value) {}
|
|
|
+ std::string str(logpacket const & lp) const override {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ void write(logpacket const & lp, std::ostream & os) const override {
|
|
|
+ os << value;
|
|
|
+ }
|
|
|
+ std::string value;
|
|
|
+ };
|
|
|
+
|
|
|
+ struct bounds_gen : public format::generator_t {
|
|
|
+ bounds_gen(format::generator impl, bool is_left, int min, size_t max)
|
|
|
+ : impl(impl), is_left(is_left), min(min), max(max) {}
|
|
|
+ std::string str(logpacket const & lp) const override {
|
|
|
+ return impl->str(lp);
|
|
|
+ }
|
|
|
+ void write(logpacket const & lp, std::ostream & os) const override {
|
|
|
+ auto align = is_left ? std::left : std::right;
|
|
|
+ std::string str = impl->str(lp);
|
|
|
+ if (str.length() > max) {
|
|
|
+ str.erase(str.begin()+max, str.end());
|
|
|
+ }
|
|
|
+ os << align << std::setw(min) << str;
|
|
|
+ }
|
|
|
+ format::generator impl;
|
|
|
+ bool is_left;
|
|
|
+ int min;
|
|
|
+ size_t max;
|
|
|
+ };
|
|
|
+} }
|
|
|
+
|
|
|
+namespace logging {
|
|
|
#define is( chr ) *next == chr
|
|
|
#define is_string( str ) ! strncmp(next, str, strlen(str))
|
|
|
- string_generator date_token(char const * next) {
|
|
|
- std::string predef_format = "%%Y-%%m-%%d %%H:%%M:%%S,%.03d";
|
|
|
- if (is_string("{ISO8601}")) {
|
|
|
- predef_format = "%%Y-%%m-%%dT%%H:%%M:%%S.%.03dZ";
|
|
|
- } else if (is_string("{ABSOLUTE}")) {
|
|
|
- predef_format = "%%H:%%M:%%S,%.03d";
|
|
|
- } else if (is_string("{DATE}")) {
|
|
|
- predef_format = "%%d %%b %%Y %%H:%%M:%%S,%.03d";
|
|
|
- } else if (is('{')) {
|
|
|
- return parse_date_format_string(next+1);
|
|
|
- }
|
|
|
- return [=](logpacket const & lp ){
|
|
|
- return fmt_time_with_milis(lp.time, predef_format);
|
|
|
- };
|
|
|
- }
|
|
|
+ format::generator date_token(char const * next);
|
|
|
|
|
|
- string_generator string_token(std::string str) {
|
|
|
- return [=](logpacket const &){ return str; };
|
|
|
- }
|
|
|
-
|
|
|
- string_generator handle( char const * & next ) {
|
|
|
+ format::generator handle( char const * & next ) {
|
|
|
if (is('c')) {
|
|
|
- return [](logpacket const & lp){ return lp.logger; };
|
|
|
+ return std::make_shared<log_handle_gen>();
|
|
|
} else if (is('p')) {
|
|
|
- return [](logpacket const & lp){ return to_string(lp.level, true); };
|
|
|
+ return std::make_shared<level_gen>();
|
|
|
} else if (is('m')) {
|
|
|
- return [](logpacket const & lp){ return lp.message.str(); };
|
|
|
+ return std::make_shared<message_gen>();
|
|
|
} else if (is('t')) {
|
|
|
- return [](logpacket const & lp){ return "???"; };
|
|
|
+ return std::make_shared<literal_gen>("???");
|
|
|
} else {
|
|
|
std::string error_msg{"unknown format character: '"};
|
|
|
throw unknown_format_specifier{error_msg + *next + "'"};
|
|
|
@@ -77,24 +110,12 @@ namespace logging {
|
|
|
|
|
|
format::generator parse_with_bounds(char const * & next) {
|
|
|
bool const is_left = *next == '-';
|
|
|
- auto align = is_left ? std::left : std::right;
|
|
|
if (is_left) ++next;
|
|
|
|
|
|
auto bounds = get_bounds(next);
|
|
|
- string_generator gen = handle(next);
|
|
|
|
|
|
- return [=](logpacket const & lp, std::ostream & out) {
|
|
|
- std::string str = gen(lp);
|
|
|
- if (str.length() > bounds.second)
|
|
|
- str.erase(str.begin()+bounds.second, str.end());
|
|
|
- out << align << std::setw(bounds.first) << str;
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
- format::generator convert( string_generator gen ) {
|
|
|
- return [=](logpacket const & lp, std::ostream & out) {
|
|
|
- out << gen( lp );
|
|
|
- };
|
|
|
+ bounds_gen gen{handle(next), is_left, bounds.first, bounds.second};
|
|
|
+ return std::make_shared<bounds_gen>(gen);
|
|
|
}
|
|
|
|
|
|
format format::parse_format_string( std::string const & fmt ) {
|
|
|
@@ -111,33 +132,35 @@ namespace logging {
|
|
|
}
|
|
|
|
|
|
if (curr < next-1) {
|
|
|
- out.gen.push_back(convert(string_token({curr, next - 1})));
|
|
|
+ std::string lit{curr, next - 1};
|
|
|
+ out.gen.push_back(std::make_shared<literal_gen>(lit));
|
|
|
}
|
|
|
|
|
|
if (is('d')) {
|
|
|
++next;
|
|
|
- out.gen.push_back(convert(date_token(next)));
|
|
|
+ out.gen.push_back(date_token(next));
|
|
|
if (is('{')) next = std::strchr(next, '}');
|
|
|
} else if (is('n')) {
|
|
|
- out.gen.push_back(convert(string_token(NEWLINE_TOKEN)));
|
|
|
+ out.gen.push_back(std::make_shared<literal_gen>(NEWLINE_TOKEN));
|
|
|
} else if (is('%')) {
|
|
|
- out.gen.push_back(convert(string_token("%")));
|
|
|
+ out.gen.push_back(std::make_shared<literal_gen>("%"));
|
|
|
} else if (is('.') || is('-') || isdigit( *next )) {
|
|
|
out.gen.push_back(parse_with_bounds(next));
|
|
|
} else {
|
|
|
- out.gen.push_back(convert(handle(next)));
|
|
|
+ out.gen.push_back(handle(next));
|
|
|
}
|
|
|
curr = ++next;
|
|
|
}
|
|
|
if (curr < end) {
|
|
|
- out.gen.push_back(convert(string_token({curr, end})));
|
|
|
+ std::string lit{curr, end};
|
|
|
+ out.gen.push_back(std::make_shared<literal_gen>(lit));
|
|
|
}
|
|
|
return out;
|
|
|
}
|
|
|
#undef is
|
|
|
|
|
|
void format::process(logpacket const & pkt, std::ostream & os) const {
|
|
|
- for (auto func : gen) { func(pkt, os); }
|
|
|
+ for (auto func : gen) { func->write(pkt, os); }
|
|
|
}
|
|
|
|
|
|
std::string format::process(logpacket const & pkt) const {
|