[docs] add a note that level regexes are not anchored

Related to #1153
pull/1159/head
Tim Stack 1 year ago
parent c3abaee445
commit a324bc8c1c

@ -258,6 +258,11 @@ object with the following fields:
of exact numbers, you can supply a pattern and the number found in the log
will be converted to a string for pattern-matching.
.. note:: The regular expression is not anchored to the start of the
string by default, so an expression like :code:`1` will match
:code:`-1`. If you want to exactly match :code:`1`, you would
use :code:`^1$` as the expression.
:multiline: If false, **lnav** will consider any log lines that do not
match one of the message patterns to be in error when checking files with
the '-C' option. This flag will not affect normal viewing operation.

@ -390,6 +390,14 @@ code_border(S str)
VC_ROLE.template value(role_t::VCR_CODE_BORDER));
}
template<typename S>
inline std::pair<S, string_attr_pair>
snippet_border(S str)
{
return std::make_pair(std::move(str),
VC_ROLE.template value(role_t::VCR_SNIPPET_BORDER));
}
template<typename S>
inline std::pair<S, string_attr_pair>
table_border(S str)

@ -2281,19 +2281,75 @@ external_log_format::build(std::vector<lnav::console::user_message>& errors)
.append("\n")
.append("captured level = ")
.append_quoted(level_cap->to_string());
errors.emplace_back(
lnav::console::user_message::error(
attr_line_t("invalid sample log message: ")
.append(lnav::to_json(elf_sample.s_line.pp_value)))
.with_reason(attr_line_t()
.append_quoted(lnav::roles::symbol(
level_names[level]))
.append(" does not match the expected "
"level of ")
.append_quoted(lnav::roles::symbol(
level_names[elf_sample.s_level])))
.with_snippet(elf_sample.s_line.to_snippet())
.with_note(note_al));
if (level_cap && !this->elf_level_patterns.empty()) {
static thread_local auto md
= lnav::pcre2pp::match_data::unitialized();
note_al.append("\nlevel regular expression match results:");
for (const auto& level_pattern : this->elf_level_patterns) {
attr_line_t regex_al = level_pattern.second.lp_pcre
.pp_value->get_pattern();
lnav::snippets::regex_highlighter(
regex_al,
-1,
line_range{0, (int) regex_al.length()});
note_al.append("\n ")
.append(
lnav::roles::symbol(level_pattern.second.lp_pcre
.pp_path.to_string()))
.append(" = ")
.append(regex_al)
.append("\n ");
auto match_res = level_pattern.second.lp_pcre.pp_value
->capture_from(level_cap.value())
.into(md)
.matches(PCRE2_NO_UTF_CHECK)
.ignore_error();
if (!match_res) {
note_al.append(lnav::roles::warning("no match"));
continue;
}
note_al.append(level_cap.value())
.append("\n ")
.append(md.leading().length(), ' ')
.append("^"_snippet_border);
if (match_res->f_all.length() > 2) {
note_al.append(
lnav::roles::snippet_border(std::string(
match_res->f_all.length() - 2, '-')));
}
if (match_res->f_all.length() > 1) {
note_al.append("^"_snippet_border);
}
}
}
auto um
= lnav::console::user_message::error(
attr_line_t("invalid sample log message: ")
.append(
lnav::to_json(elf_sample.s_line.pp_value)))
.with_reason(
attr_line_t()
.append_quoted(
lnav::roles::symbol(level_names[level]))
.append(" does not match the expected "
"level of ")
.append_quoted(lnav::roles::symbol(
level_names[elf_sample.s_level])))
.with_snippet(elf_sample.s_line.to_snippet())
.with_note(note_al);
if (!this->elf_level_patterns.empty()) {
um.with_help(
attr_line_t("Level regexes are not anchored to the "
"start/end of the string. Prepend ")
.append_quoted("^"_symbol)
.append(" to the expression to match from the "
"start of the string and append ")
.append_quoted("$"_symbol)
.append(" to match up to the end of the string."));
}
errors.emplace_back(um);
}
{

@ -300,6 +300,7 @@ read_levels(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
log_level_t level = string2level(level_name_or_number.c_str());
auto value_frag = string_fragment::from_bytes(str, len);
elf->elf_level_patterns[level].lp_pcre.pp_path = ypc->get_full_path();
auto compile_res = lnav::pcre2pp::code::from(value_frag);
if (compile_res.isErr()) {
static const intern_string_t PATTERN_SRC

@ -25,6 +25,10 @@
}
},
"level-field": "level",
"level": {
"info": "info",
"debug": "debug"
},
"sample": [
{
"line": "abc: foo"

@ -116,24 +116,31 @@
 = help: update the regular expression to fully capture the sample message
✘ error: invalid sample log message: "abc: foo"
reason: unrecognized timestamp -- abc
 --> {test_dir}/bad-config/formats/invalid-sample/format.json:30
 --> {test_dir}/bad-config/formats/invalid-sample/format.json:34
 = note: the following custom formats were tried:
abc
^ “%i” matched up to here
 = help: If the timestamp format is not supported by default, you can add a custom format with the “timestamp-format” property
✘ error: invalid sample log message: "1428634687123| debug hello"
reason: “debug” does not match the expected level of “info”
 --> {test_dir}/bad-config/formats/invalid-sample/format.json:33
 --> {test_dir}/bad-config/formats/invalid-sample/format.json:37
 = note: matched regex = with-level
captured level = “debug”
level regular expression match results:
/bad_sample_log/level/debug = debug
debug
^---^
/bad_sample_log/level/info = info
no match
 = help: Level regexes are not anchored to the start/end of the string. Prepend “^” to the expression to match from the start of the string and append “$” to match up to the end of the string.
✘ error: invalid pattern: “with-level”
reason: pattern does not match entire multiline sample message
 --> {test_dir}/bad-config/formats/invalid-sample/format.json:37
 --> {test_dir}/bad-config/formats/invalid-sample/format.json:41
 = note: with-level = ^(?<timestamp>\d+)\| (?<level>\w+) (?<body>\w+)$
 = help: use “.*” to match new-lines
✘ error: invalid sample log message: "1428634687123; foo bar"
reason: sample does not match any patterns
 --> {test_dir}/bad-config/formats/invalid-sample/format.json:41
 --> {test_dir}/bad-config/formats/invalid-sample/format.json:45
 = note: the following shows how each pattern matched this sample:
1428634687123; foo bar
^ bad-time matched up to here

Loading…
Cancel
Save