diff --git a/docs/source/formats.rst b/docs/source/formats.rst index 447ec955d03..9010dd947a2 100644 --- a/docs/source/formats.rst +++ b/docs/source/formats.rst @@ -227,6 +227,8 @@ object with the following fields: :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. '..'). + :last-word: Removes all but the last word in dotted text. For example, + "com.example.foo" would be shortened to "foo". (v0.8.2+) :timestamp-format: The timestamp format to use when displaying the time diff --git a/src/base/string_util.cc b/src/base/string_util.cc index 4915307025d..90c8f86b0d5 100644 --- a/src/base/string_util.cc +++ b/src/base/string_util.cc @@ -198,6 +198,34 @@ is_url(const std::string& fn) return std::regex_match(fn, url_re); } +size_t +last_word_str(char* str, size_t len, size_t max_len) +{ + if (len < max_len) { + return len; + } + + size_t last_start = 0; + + for (size_t index = 0; index < len; index++) { + switch (str[index]) { + case '.': + case '-': + case '/': + case ':': + last_start = index + 1; + break; + } + } + + if (last_start == 0) { + return len; + } + + memmove(&str[0], &str[last_start], len - last_start); + return len - last_start; +} + size_t abbreviate_str(char* str, size_t len, size_t max_len) { diff --git a/src/base/string_util.hh b/src/base/string_util.hh index ae87ab604b5..95cf53108ba 100644 --- a/src/base/string_util.hh +++ b/src/base/string_util.hh @@ -228,6 +228,8 @@ bool is_blank(const std::string& str); size_t abbreviate_str(char* str, size_t len, size_t max_len); +size_t last_word_str(char* str, size_t len, size_t max_len); + void split_ws(const std::string& str, std::vector& toks_out); std::string repeat(const std::string& input, size_t num); diff --git a/src/log_format.cc b/src/log_format.cc index 7ce3902988c..2981073c16a 100644 --- a/src/log_format.cc +++ b/src/log_format.cc @@ -2280,6 +2280,13 @@ external_log_format::get_subline(const logline& ll, rest); break; } + case json_format_element::overflow_t:: + LASTWORD: { + size_t new_size = last_word_str(&str[0], str.size(), jfe.jfe_max_width); + str.resize(new_size); + this->json_append(jfe, vd, str.data(), str.size()); + break; + } } } else { sub_offset diff --git a/src/log_format_ext.hh b/src/log_format_ext.hh index 94568f5c2ed..d59a15a824e 100644 --- a/src/log_format_ext.hh +++ b/src/log_format_ext.hh @@ -231,6 +231,7 @@ public: ABBREV, TRUNCATE, DOTDOT, + LASTWORD, }; enum class transform_t { diff --git a/src/log_format_loader.cc b/src/log_format_loader.cc index 5694e02aaff..0fe628b8c40 100644 --- a/src/log_format_loader.cc +++ b/src/log_format_loader.cc @@ -456,6 +456,7 @@ static const json_path_handler_base::enum_value_t OVERFLOW_ENUM[] = { {"truncate", external_log_format::json_format_element::overflow_t::TRUNCATE}, {"dot-dot", external_log_format::json_format_element::overflow_t::DOTDOT}, + {"last-word", external_log_format::json_format_element::overflow_t::LASTWORD}, json_path_handler_base::ENUM_TERMINATOR, };