[log-format] add "truncate" overflow value

pull/356/head
Timothy Stack 8 years ago
parent c05dfafae8
commit 876b37ade0

@ -84,9 +84,15 @@ fields:
If "left", padding to meet the minimum-width will be added on the right.
If "right", padding will be added on the left. (v0.8.2+)
:overflow: The algorithm used to shorten a field that is longer than
"max-width". The only option at the moment is "abbrev", which removes
all but the first letter in dotted text. For example, "com.example.foo"
would be shortened to "c.e.foo". (v0.8.2+)
"max-width". The following algorithms are supported:
:abbrev: Removes all but the first letter in dotted text. For example,
"com.example.foo" would be shortened to "c.e.foo".
:truncate: Truncates any text past the maximum width.
:dot-dot: Cuts out the middle of the text and replaces it with two
dots (i.e. '..').
(v0.8.2+)
:timestamp-format: The timestamp format to use when displaying the time
for this log message. (v0.8.2+)
:default-value: The default value to use if the field could not be found

@ -224,7 +224,7 @@ Session
* - Keypress
- Command
* - |ks| Ctrl |ky| + |ks| R |ke|
* - |ks| Ctrl |ke| + |ks| R |ke|
- Reset current session.
Query

@ -726,15 +726,20 @@ size_t abbreviate_str(char *str, size_t len, size_t max_len)
}
for (size_t index = 0; index < len; index++) {
if (str[index] == '.' || str[index] == '-') {
memmove(&str[last_start], &str[index], len - index);
len -= (index - last_start);
index = last_start + 1;
last_start = index + 1;
if (len < max_len) {
return len;
}
switch (str[index]) {
case '.':
case '-':
case '/':
case ':':
memmove(&str[last_start], &str[index], len - index);
len -= (index - last_start);
index = last_start + 1;
last_start = index + 1;
if (len < max_len) {
return len;
}
break;
}
}

@ -66,14 +66,6 @@ string_attr_type logline::L_PARTITION;
string_attr_type logline::L_MODULE;
string_attr_type logline::L_OPID;
const intern_string_t external_log_format::json_format_element::ALIGN_LEFT =
intern_string::lookup("left");
const intern_string_t external_log_format::json_format_element::ALIGN_RIGHT =
intern_string::lookup("right");
const intern_string_t external_log_format::json_format_element::OVERFLOW_ABBREV =
intern_string::lookup("abbrev");
const char *logline::level_names[LEVEL__MAX + 1] = {
"unknown",
"trace",
@ -1152,33 +1144,41 @@ void external_log_format::get_subline(const logline &ll, shared_buffer_ref &sbr,
size_t nl_pos = str.find('\n');
lr.lr_start = this->jlf_cached_line.size();
if (jfe.jfe_align == json_format_element::ALIGN_RIGHT) {
if (str.size() < jfe.jfe_min_width) {
this->json_append_to_cache(jfe.jfe_min_width -
str.size());
}
}
this->json_append_to_cache(str.c_str(), str.size());
if (jfe.jfe_align == json_format_element::ALIGN_LEFT) {
if (str.size() < jfe.jfe_min_width) {
this->json_append_to_cache(jfe.jfe_min_width -
str.size());
}
}
size_t actual_size = this->jlf_cached_line.size() -
lr.lr_start;
if (actual_size > jfe.jfe_max_width) {
if (jfe.jfe_overflow == json_format_element::OVERFLOW_ABBREV) {
size_t new_size = abbreviate_str(
&this->jlf_cached_line[lr.lr_start],
actual_size,
jfe.jfe_max_width);
this->jlf_cached_line.resize(lr.lr_start + new_size);
if (str.size() > jfe.jfe_max_width) {
switch (jfe.jfe_overflow) {
case json_format_element::ABBREV: {
this->json_append_to_cache(
str.c_str(), str.size());
size_t new_size = abbreviate_str(
&this->jlf_cached_line[lr.lr_start],
str.size(),
jfe.jfe_max_width);
this->jlf_cached_line.resize(
lr.lr_start + new_size);
break;
}
case json_format_element::TRUNCATE: {
this->json_append_to_cache(
str.c_str(), jfe.jfe_max_width);
break;
}
case json_format_element::DOTDOT: {
size_t middle = (jfe.jfe_max_width / 2) - 1;
this->json_append_to_cache(
str.c_str(), middle);
this->json_append_to_cache("..", 2);
size_t rest = (jfe.jfe_max_width - middle - 2);
this->json_append_to_cache(
str.c_str() + str.size() - rest, rest);
break;
}
}
}
else {
this->json_append(jfe, str.c_str(), str.size());
}
if (nl_pos == string::npos) {
lr.lr_end = this->jlf_cached_line.size();
@ -1231,9 +1231,9 @@ void external_log_format::get_subline(const logline &ll, shared_buffer_ref &sbr,
string_attr(lr, &logline::L_TIMESTAMP));
}
else {
this->json_append_to_cache(
jfe.jfe_default_value.c_str(),
jfe.jfe_default_value.size());
this->json_append(jfe,
jfe.jfe_default_value.c_str(),
jfe.jfe_default_value.size());
}
break;
}

@ -1041,15 +1041,21 @@ public:
};
struct json_format_element {
static const intern_string_t ALIGN_LEFT;
static const intern_string_t ALIGN_RIGHT;
enum align_t {
LEFT,
RIGHT,
};
static const intern_string_t OVERFLOW_ABBREV;
enum overflow_t {
ABBREV,
TRUNCATE,
DOTDOT,
};
json_format_element()
: jfe_type(JLF_CONSTANT), jfe_default_value("-"), jfe_min_width(0),
jfe_max_width(LLONG_MAX), jfe_align(ALIGN_LEFT),
jfe_overflow(OVERFLOW_ABBREV)
jfe_max_width(LLONG_MAX), jfe_align(LEFT),
jfe_overflow(ABBREV)
{ };
json_log_field jfe_type;
@ -1057,8 +1063,8 @@ public:
std::string jfe_default_value;
long long jfe_min_width;
long long jfe_max_width;
intern_string_t jfe_align;
intern_string_t jfe_overflow;
align_t jfe_align;
overflow_t jfe_overflow;
std::string jfe_ts_format;
};
@ -1074,6 +1080,21 @@ public:
memset(&this->jlf_cached_line[old_size], ' ', len);
};
void json_append(const json_format_element &jfe, const char *value, size_t len) {
if (jfe.jfe_align == json_format_element::RIGHT) {
if (len < jfe.jfe_min_width) {
this->json_append_to_cache(jfe.jfe_min_width - len);
}
}
this->json_append_to_cache(value, len);
if (jfe.jfe_align == json_format_element::LEFT) {
if (len < jfe.jfe_min_width) {
this->json_append_to_cache(jfe.jfe_min_width - len);
}
}
};
bool jlf_json;
bool jlf_hide_extra;
std::vector<json_format_element> jlf_line_format;

@ -424,17 +424,19 @@ static struct json_path_handler pattern_handlers[] = {
json_path_handler()
};
static const intern_string_t ALIGN_ENUM[] = {
external_log_format::json_format_element::ALIGN_LEFT,
external_log_format::json_format_element::ALIGN_RIGHT,
static const json_path_handler_base::enum_value_t ALIGN_ENUM[] = {
make_pair("left", external_log_format::json_format_element::LEFT),
make_pair("right", external_log_format::json_format_element::RIGHT),
intern_string_t()
json_path_handler_base::ENUM_TERMINATOR
};
static const intern_string_t OVERFLOW_ENUM[] = {
external_log_format::json_format_element::OVERFLOW_ABBREV,
static const json_path_handler_base::enum_value_t OVERFLOW_ENUM[] = {
make_pair("abbrev", external_log_format::json_format_element::ABBREV),
make_pair("truncate", external_log_format::json_format_element::TRUNCATE),
make_pair("dot-dot", external_log_format::json_format_element::DOTDOT),
intern_string_t()
json_path_handler_base::ENUM_TERMINATOR
};
static struct json_path_handler line_format_handlers[] = {
@ -471,13 +473,13 @@ static struct json_path_handler line_format_handlers[] = {
.with_synopsis("left|right")
.with_description("Align the text in the column to the left or right side")
.with_enum_values(ALIGN_ENUM)
.for_field(&nullobj<external_log_format::json_format_element>()->jfe_align),
.for_enum(&nullobj<external_log_format::json_format_element>()->jfe_align),
json_path_handler("overflow")
.with_synopsis("abbrev")
.with_description("Overflow style")
.with_enum_values(OVERFLOW_ENUM)
.for_field(&nullobj<external_log_format::json_format_element>()->jfe_overflow),
.for_enum(&nullobj<external_log_format::json_format_element>()->jfe_overflow),
json_path_handler()
};

@ -36,6 +36,9 @@
using namespace std;
const json_path_handler_base::enum_value_t json_path_handler_base::ENUM_TERMINATOR =
make_pair((const char *) NULL, 0);
static char *resolve_root(yajlpp_parse_context *ypc)
{
const json_path_handler_base *jph = ypc->ypc_current_handler;
@ -74,6 +77,46 @@ int yajlpp_static_intern_string(yajlpp_parse_context *ypc, const unsigned char *
return 1;
}
int yajlpp_static_enum(yajlpp_parse_context *ypc, const unsigned char *str, size_t len)
{
char *root_ptr = resolve_root(ypc);
int *field_ptr = (int *) root_ptr;
const json_path_handler_base &jph = *ypc->ypc_current_handler;
bool found = false;
for (int lpc = 0; jph.jph_enum_values[lpc].first; lpc++) {
const json_path_handler::enum_value_t &ev = jph.jph_enum_values[lpc];
if (len == strlen(ev.first) && strncmp((const char *) str, ev.first, len) == 0) {
*field_ptr = ev.second;
found = true;
break;
}
}
if (!found) {
ypc->report_error("error:%s:line %d\n "
"Invalid value, '%.*s', for option:",
ypc->ypc_source.c_str(),
ypc->get_line_number(),
len,
str);
ypc->report_error(" %s %s -- %s\n",
&ypc->ypc_path[0],
jph.jph_synopsis,
jph.jph_description);
ypc->report_error(" Allowed values: ");
for (int lpc = 0; jph.jph_enum_values[lpc].first; lpc++) {
const json_path_handler::enum_value_t &ev = jph.jph_enum_values[lpc];
ypc->report_error(" %s\n", ev.first);
}
}
return 1;
}
yajl_gen_status yajlpp_static_gen_string(yajlpp_gen_context &ygc,
const json_path_handler_base &jph,
yajl_gen handle)
@ -123,33 +166,6 @@ void yajlpp_validator_for_intern_string(yajlpp_parse_context &ypc,
jph.jph_min_length);
ypc.report_error(buffer);
}
if (jph.jph_enum_values != NULL) {
bool matched = false;
for (int lpc = 0; !jph.jph_enum_values[lpc].empty(); lpc++) {
intern_string_t enum_value = jph.jph_enum_values[lpc];
if (enum_value == *field_ptr) {
matched = true;
break;
}
}
if (!matched) {
ypc.report_error("error:%s:line %d\n "
"Unexpected value for path %s -- %s",
ypc.ypc_source.c_str(),
ypc.get_line_number(),
ypc.get_path().get(),
(*field_ptr).get());
ypc.report_error(" Allowed values:\n");
for (int lpc = 0; !jph.jph_enum_values[lpc].empty(); lpc++) {
intern_string_t enum_value = jph.jph_enum_values[lpc];
ypc.report_error(" %s\n", enum_value.get());
}
}
}
}
void yajlpp_validator_for_int(yajlpp_parse_context &ypc,

@ -88,6 +88,10 @@ class json_schema_validator;
class yajlpp_parse_context;
struct json_path_handler_base {
typedef std::pair<const char *, int> enum_value_t;
static const enum_value_t ENUM_TERMINATOR;
json_path_handler_base(const char *path)
: jph_path(path),
jph_regex(path, PCRE_ANCHORED),
@ -120,12 +124,13 @@ struct json_path_handler_base {
json_path_handler_base *jph_children;
size_t jph_min_length;
size_t jph_max_length;
const intern_string_t *jph_enum_values;
const enum_value_t *jph_enum_values;
long long jph_min_value;
};
int yajlpp_static_string(yajlpp_parse_context *, const unsigned char *, size_t);
int yajlpp_static_intern_string(yajlpp_parse_context *, const unsigned char *, size_t);
int yajlpp_static_enum(yajlpp_parse_context *, const unsigned char *, size_t);
yajl_gen_status yajlpp_static_gen_string(yajlpp_gen_context &ygc,
const json_path_handler_base &,
yajl_gen);
@ -228,7 +233,7 @@ struct json_path_handler : public json_path_handler_base {
return *this;
}
json_path_handler &with_enum_values(const intern_string_t values[]) {
json_path_handler &with_enum_values(const enum_value_t values[]) {
this->jph_enum_values = values;
return *this;
}
@ -260,6 +265,14 @@ struct json_path_handler : public json_path_handler_base {
return *this;
};
template<typename T>
json_path_handler &for_enum(T *field) {
this->add_cb(yajlpp_static_enum);
this->jph_simple_offset = field;
this->jph_gen_callback = yajlpp_static_gen_string;
return *this;
};
json_path_handler &for_field(long long *field) {
this->add_cb(yajlpp_static_number);
this->jph_simple_offset = field;

Loading…
Cancel
Save