|
|
@@ -19,6 +19,7 @@
|
|
|
#include "common.h"
|
|
|
#include "logger/exception.h"
|
|
|
#include "logger/logger.h"
|
|
|
+#include "logger/logpacket.h"
|
|
|
|
|
|
#if defined( _WIN32 )
|
|
|
# define NEWLINE "\r\n"
|
|
|
@@ -27,64 +28,14 @@
|
|
|
#endif
|
|
|
|
|
|
namespace logging {
|
|
|
- namespace {
|
|
|
- std::string fmt_time(struct timeval round, char const * const fmt) {
|
|
|
- struct tm time;
|
|
|
- // Supports localtime when requested, but you can't really test that
|
|
|
- if (strstr(fmt, "%z") || strstr(fmt, "%Z")) {
|
|
|
- localtime_r(&round.tv_sec, &time);
|
|
|
- } else {
|
|
|
- gmtime_r(&round.tv_sec, &time);
|
|
|
- }
|
|
|
- char buf[64] = {'\0'};
|
|
|
- std::strftime(buf, sizeof(buf), fmt, &time);
|
|
|
- return buf;
|
|
|
- }
|
|
|
-
|
|
|
- std::string fmt_time(struct timeval round, std::string const & fmt) {
|
|
|
- return fmt_time(round, fmt.c_str());
|
|
|
- }
|
|
|
-
|
|
|
- std::string fmt_time_with_milis(struct timeval round,
|
|
|
- std::string const & fmt) {
|
|
|
- char buf[64] = {'\0'};
|
|
|
- snprintf(buf, sizeof(buf), fmt.c_str(), round.tv_usec/1000);
|
|
|
- return fmt_time(round, buf);
|
|
|
- }
|
|
|
- }
|
|
|
- using string_generator = std::function<std::string(logpacket const &)>;
|
|
|
-
|
|
|
- string_generator parse_date_format_string( char const * str ) {
|
|
|
- char const * const end = strchr(str, '}');
|
|
|
- if (end == nullptr) {
|
|
|
- std::string error_msg{"expected date-format specifier to terminate"};
|
|
|
- throw format_parsing_exception{error_msg};
|
|
|
- }
|
|
|
-
|
|
|
- char const * const has_millis = strstr( str, "%_ms");
|
|
|
- std::string fmtstring{str, end};
|
|
|
- if ( has_millis && has_millis < end ) {
|
|
|
- size_t pos = 0;
|
|
|
- while ( (pos = fmtstring.find("%", pos)) != std::string::npos ) {
|
|
|
- fmtstring.replace(pos, 1, "%%");
|
|
|
- pos += 2;
|
|
|
- }
|
|
|
- fmtstring.replace(fmtstring.find("%%_ms"), 5, "%.03d");
|
|
|
- return [=](logpacket const & lp) {
|
|
|
- return fmt_time_with_milis(lp.time, fmtstring);
|
|
|
- };
|
|
|
- } else {
|
|
|
- return [=](logpacket const & lp) {
|
|
|
- return fmt_time(lp.time, fmtstring);
|
|
|
- };
|
|
|
- }
|
|
|
- }
|
|
|
+ std::string fmt_time_with_milis(struct timeval, std::string const &);
|
|
|
+ string_generator parse_date_format_string(char const *);
|
|
|
|
|
|
#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}")) {
|
|
|
+ if (is_string("{ISO8601}")) {
|
|
|
predef_format = "%%Y-%%m-%%dT%%H:%%M:%%S.%.03dZ";
|
|
|
} else if (is_string("{ABSOLUTE}")) {
|
|
|
predef_format = "%%H:%%M:%%S,%.03d";
|
|
|
@@ -97,9 +48,9 @@ namespace logging {
|
|
|
return fmt_time_with_milis(lp.time, predef_format);
|
|
|
};
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
string_generator string_token(std::string str) {
|
|
|
- return [=]( logpacket const & ){
|
|
|
+ return [=](logpacket const &){
|
|
|
return str;
|
|
|
};
|
|
|
}
|
|
|
@@ -111,11 +62,11 @@ namespace logging {
|
|
|
};
|
|
|
} else if (is('p')) {
|
|
|
return [](logpacket const & lp){
|
|
|
- return level_header(lp.level);
|
|
|
+ return to_string(lp.level, true);
|
|
|
};
|
|
|
} else if (is('m')) {
|
|
|
return [](logpacket const & lp){
|
|
|
- return lp.message;
|
|
|
+ return lp.message.str();
|
|
|
};
|
|
|
} else {
|
|
|
std::string error_msg{"unknown format character: '"};
|
|
|
@@ -205,12 +156,23 @@ namespace logging {
|
|
|
process(pkt, ss);
|
|
|
return ss.str();
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-namespace logging {
|
|
|
- format_point_t get_next_format_specifier(std::string const & interp,
|
|
|
- size_t pos) {
|
|
|
+ void format_msg(std::ostream & os, std::string const & interp, size_t pos,
|
|
|
+ std::vector<detail::object> const & objs, size_t idx) {
|
|
|
size_t next = interp.find("{}", pos);
|
|
|
- return { next, next + 2 };
|
|
|
+ os << interp.substr(pos, next);
|
|
|
+ if (next == std::string::npos) {
|
|
|
+ return; // throw?
|
|
|
+ } else if (!strncmp(interp.c_str() + next - 1, "{{}}", 4)) {
|
|
|
+ format_msg(os, interp, next+2, objs, idx);
|
|
|
+ } else {
|
|
|
+ format_msg(os << objs[idx], interp, next+2, objs, idx+1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string message::str() const {
|
|
|
+ std::stringstream ss;
|
|
|
+ format_msg(ss, format_code, 0, objects, 0);
|
|
|
+ return ss.str();
|
|
|
}
|
|
|
}
|