Skip to content

Commit 2052a26

Browse files
committed
[filters] add level filter
1 parent 2428420 commit 2052a26

20 files changed

+308
-95
lines changed

NEWS.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33

44
Features:
55
* The Filter configuration panel in the TUI now supports
6-
editing the minimum/maximum times for the current
7-
view. Previously, only the `:hide-lines-before` and
6+
editing the minimum log level and minimum/maximum
7+
times for the current view. Previously, only the
8+
`:set-min-log-level`, `:hide-lines-before`, and
89
`:hide-lines-after` commands could be used to set the
9-
values. Pressing `m` will create/set the minimum
10+
values. Pressing `l` will create/set the log level.
11+
Pressing `m` will create/set the minimum
1012
time and pressing `Shift` + `M` will create/set the
1113
maximum time. Live preview has also been added to
1214
show which lines will be filtered out when the min/max

src/base/ansi_scrubber.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848

4949
#define ANSI_BOLD(msg) ANSI_BOLD_START msg ANSI_NORM
5050
#define ANSI_UNDERLINE(msg) ANSI_UNDERLINE_START msg ANSI_NORM
51+
#define ANSI_HOTKEY(key) ANSI_CSI "1;4m" key ANSI_NORM
5152

5253
#define ANSI_ROLE(msg) ANSI_CSI "%dO" msg ANSI_NORM
5354
#define ANSI_ROLE_FMT(msg) ANSI_CSI "{}O" msg ANSI_NORM

src/db_sub_source.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "base/types.hh"
4444
#include "config.h"
4545
#include "hist_source_T.hh"
46+
#include "log_level.hh"
4647
#include "scn/scan.h"
4748
#include "yajlpp/json_ptr.hh"
4849
#include "yajlpp/yajlpp_def.hh"

src/filter_status_source.cc

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,22 @@
3636
#include "filter_sub_source.hh"
3737
#include "lnav.hh"
3838

39-
static constexpr auto TOGGLE_MSG = "Press " ANSI_BOLD("TAB") " to edit "_frag;
40-
static constexpr auto EXIT_MSG = "Press " ANSI_BOLD("ESC") " to exit "_frag;
39+
static constexpr auto TOGGLE_MSG = "Press " ANSI_HOTKEY("TAB") " to edit "_frag;
40+
static constexpr auto EXIT_MSG = "Press " ANSI_HOTKEY("ESC") " to exit "_frag;
4141

4242
static constexpr auto CREATE_HELP
43-
= ANSI_BOLD("i") "/" ANSI_BOLD("o") ": Create in/out";
44-
static constexpr auto CREATE_EXPR_HELP = " " ANSI_BOLD("e") ": Edit SQL expr";
43+
= "Create: " ANSI_HOTKEY("i") "n/" ANSI_HOTKEY("o") "ut";
44+
static constexpr auto CREATE_EXPR_HELP = " SQL " ANSI_HOTKEY("e") "xpr";
45+
static constexpr auto CREATE_LEVEL_HELP = " " ANSI_HOTKEY("l") "evel";
4546
static constexpr auto MIN_MAX_TIME_HELP
46-
= ANSI_BOLD("m") "/" ANSI_BOLD("M") ": Set min/max time";
47-
static constexpr auto ENABLE_HELP = ANSI_BOLD("SPC") ": ";
48-
static constexpr auto EDIT_HELP = ANSI_BOLD("ENTER") ": Edit";
49-
static constexpr auto TOGGLE_HELP = ANSI_BOLD("t") ": To ";
50-
static constexpr auto DELETE_HELP = ANSI_BOLD("D") ": Delete";
51-
static constexpr auto FILTERING_HELP = ANSI_BOLD("f") ": ";
52-
static constexpr auto JUMP_HELP = ANSI_BOLD("ENTER") ": Jump To";
53-
static constexpr auto CLOSE_HELP = ANSI_BOLD("X") ": Close";
47+
= " " ANSI_HOTKEY("m") "in/" ANSI_HOTKEY("M") "ax time";
48+
static constexpr auto ENABLE_HELP = ANSI_HOTKEY("SPC") ": ";
49+
static constexpr auto EDIT_HELP = ANSI_HOTKEY("ENTER") ": Edit";
50+
static constexpr auto TOGGLE_HELP = ANSI_HOTKEY("t") ": To ";
51+
static constexpr auto DELETE_HELP = ANSI_HOTKEY("D") ": Delete";
52+
static constexpr auto FILTERING_HELP = ANSI_HOTKEY("f") ": ";
53+
static constexpr auto JUMP_HELP = ANSI_HOTKEY("ENTER") ": Jump To";
54+
static constexpr auto CLOSE_HELP = ANSI_HOTKEY("X") ": Close";
5455
static constexpr auto FOCUS_DETAILS_HELP
5556
= ANSI_BOLD("CTRL-]") ": Focus on details view";
5657

@@ -305,14 +306,17 @@ filter_help_status_source::statusview_fields()
305306
auto rows = fss->rows_for(tc);
306307
if (rows.empty()) {
307308
this->fss_help.set_value(
308-
" %s%s %s",
309+
" %s%s%s%s",
309310
CREATE_HELP,
310311
lss != nullptr ? CREATE_EXPR_HELP : "",
312+
lss != nullptr ? CREATE_LEVEL_HELP : "",
311313
ttt != nullptr ? MIN_MAX_TIME_HELP : "");
312314
} else {
313315
auto& row = rows[sel.value()];
314316
auto* tfr = dynamic_cast<filter_sub_source::text_filter_row*>(
315317
row.get());
318+
auto* tir = dynamic_cast<filter_sub_source::time_filter_row*>(
319+
row.get());
316320
if (editor->fss_editing) {
317321
if (tfr != nullptr) {
318322
auto& tf = tfr->tfr_filter;
@@ -333,17 +337,23 @@ filter_help_status_source::statusview_fields()
333337
"out:",
334338
lang);
335339
}
336-
} else {
340+
} else if (tir != nullptr) {
337341
this->fss_help.set_value(
338342
" "
339343
"Enter timestamp:");
344+
} else {
345+
this->fss_help.set_value(
346+
" "
347+
"Enter level:");
340348
}
341349
} else if (tfr != nullptr) {
342350
auto& tf = tfr->tfr_filter;
343351
this->fss_help.set_value(
344-
" %s%s %s%s %s %s%s %s %s%s",
352+
" %s%s%s%s %s%s %s %s%s %s %s%s",
345353
CREATE_HELP,
346354
lss != nullptr ? CREATE_EXPR_HELP : "",
355+
lss != nullptr ? CREATE_LEVEL_HELP : "",
356+
ttt != nullptr ? MIN_MAX_TIME_HELP : "",
347357
ENABLE_HELP,
348358
tf->is_enabled() ? "Disable" : "Enable ",
349359
EDIT_HELP,
@@ -356,9 +366,11 @@ filter_help_status_source::statusview_fields()
356366
: "Enable Filtering");
357367
} else {
358368
this->fss_help.set_value(
359-
" %s%s %s %s %s%s",
369+
" %s%s%s%s %s %s %s%s",
360370
CREATE_HELP,
361371
lss != nullptr ? CREATE_EXPR_HELP : "",
372+
lss != nullptr ? CREATE_LEVEL_HELP : "",
373+
ttt != nullptr ? MIN_MAX_TIME_HELP : "",
362374
EDIT_HELP,
363375
DELETE_HELP,
364376
FILTERING_HELP,

src/filter_sub_source.cc

Lines changed: 128 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@
3636
#include "base/attr_line.builder.hh"
3737
#include "base/auto_mem.hh"
3838
#include "base/func_util.hh"
39+
#include "base/itertools.hh"
3940
#include "base/opt_util.hh"
4041
#include "base/relative_time.hh"
4142
#include "base/text_format_enum.hh"
4243
#include "cmd.parser.hh"
4344
#include "config.h"
45+
#include "itertools.similar.hh"
4446
#include "lnav.hh"
4547
#include "lnav.prompt.hh"
4648
#include "readline_highlighters.hh"
@@ -158,6 +160,25 @@ filter_sub_source::list_input_handle_key(listview_curses& lv, const ncinput& ch)
158160
}
159161
return true;
160162
}
163+
case 'l': {
164+
auto* top_view = *lnav_data.ld_view_stack.top();
165+
auto* tss = top_view->get_sub_source();
166+
if (tss->get_min_log_level() == LEVEL_UNKNOWN) {
167+
tss->set_min_log_level(LEVEL_TRACE);
168+
}
169+
const auto& [index, row]
170+
= this->find_row<level_filter_row>(top_view);
171+
lv.set_selection(index);
172+
lv.reload_data();
173+
this->fss_editing = true;
174+
this->tss_view->set_enabled(false);
175+
row->prime_text_input(top_view, *this->fss_editor, *this);
176+
this->fss_editor->set_y(lv.get_y_for_selection());
177+
this->fss_editor->set_visible(true);
178+
this->fss_editor->focus();
179+
this->tss_view->reload_data();
180+
return true;
181+
}
161182
case 'm': {
162183
auto* top_view = *lnav_data.ld_view_stack.top();
163184
auto* ttt = dynamic_cast<text_time_translator*>(
@@ -186,11 +207,10 @@ filter_sub_source::list_input_handle_key(listview_curses& lv, const ncinput& ch)
186207
ttt->ttt_preview_min_time = this->fss_min_time;
187208
}
188209

189-
lv.set_selection(0_vl);
210+
const auto& [index, row]
211+
= this->find_row<min_time_filter_row>(top_view);
212+
lv.set_selection(index);
190213
lv.reload_data();
191-
192-
auto rows = this->rows_for(top_view);
193-
auto& row = rows[0];
194214
this->fss_editing = true;
195215
this->tss_view->set_enabled(false);
196216
row->prime_text_input(top_view, *this->fss_editor, *this);
@@ -230,12 +250,10 @@ filter_sub_source::list_input_handle_key(listview_curses& lv, const ncinput& ch)
230250
ttt->ttt_preview_max_time = this->fss_max_time;
231251
}
232252

233-
auto new_sel = ttt->get_min_row_time() ? 1_vl : 0_vl;
234-
lv.set_selection(new_sel);
253+
const auto& [index, row]
254+
= this->find_row<level_filter_row>(top_view);
255+
lv.set_selection(index);
235256
lv.reload_data();
236-
237-
auto rows = this->rows_for(top_view);
238-
auto& row = rows[new_sel];
239257
this->fss_editing = true;
240258
this->tss_view->set_enabled(false);
241259
row->prime_text_input(top_view, *this->fss_editor, *this);
@@ -670,6 +688,103 @@ filter_sub_source::min_time_filter_row::ti_abort(textview_curses* top_view,
670688
tss->text_filters_changed();
671689
}
672690

691+
void
692+
filter_sub_source::level_filter_row::value_for(const render_state& rs,
693+
attr_line_t& al)
694+
{
695+
auto lev = rs.rs_top_view->get_sub_source()->get_min_log_level();
696+
697+
al.append(" ").append("Level"_table_header).append(" ");
698+
if (rs.rs_editing) {
699+
al.append(fmt::format(FMT_STRING("{:>9}"), "-"),
700+
VC_ROLE.value(role_t::VCR_NUMBER));
701+
} else {
702+
al.append(
703+
fmt::format(
704+
FMT_STRING("{:>9}"),
705+
rs.rs_top_view->get_sub_source()->tss_level_filtered_count),
706+
VC_ROLE.value(role_t::VCR_NUMBER));
707+
}
708+
al.append(" hits ")
709+
.append("|", VC_GRAPHIC.value(NCACS_VLINE))
710+
.append(" ")
711+
.append(level_names[lev]);
712+
}
713+
714+
bool
715+
filter_sub_source::level_filter_row::handle_key(textview_curses* top_view,
716+
const ncinput& ch)
717+
{
718+
switch (ch.eff_text[0]) {
719+
case 'D':
720+
top_view->get_sub_source()->set_min_log_level(LEVEL_UNKNOWN);
721+
return true;
722+
}
723+
return false;
724+
}
725+
726+
bool
727+
filter_sub_source::level_filter_row::prime_text_input(textview_curses* top_view,
728+
textinput_curses& ti,
729+
filter_sub_source& parent)
730+
{
731+
auto* tss = top_view->get_sub_source();
732+
auto lev = tss->get_min_log_level();
733+
parent.fss_curr_level = lev;
734+
tss->set_min_log_level(LEVEL_TRACE);
735+
tss->text_filters_changed();
736+
ti.set_content(level_names[lev].to_string());
737+
ti.tc_selection
738+
= ti.clamp_selection(textinput_curses::selected_range::from_mouse(
739+
textinput_curses::input_point::home(),
740+
textinput_curses::input_point::end()));
741+
return true;
742+
}
743+
744+
void
745+
filter_sub_source::level_filter_row::ti_change(textview_curses* top_view,
746+
textinput_curses& rc)
747+
{
748+
auto lev = rc.get_content();
749+
top_view->get_sub_source()->tss_preview_min_log_level
750+
= string2level(lev.c_str(), lev.size(), false);
751+
this->ti_completion_request(
752+
top_view, rc, completion_request_type_t::partial);
753+
}
754+
755+
void
756+
filter_sub_source::level_filter_row::ti_completion_request(
757+
textview_curses* top_view,
758+
textinput_curses& tc,
759+
completion_request_type_t crt)
760+
{
761+
auto lev = tc.get_content();
762+
auto poss = level_names | lnav::itertools::similar_to(lev)
763+
| lnav::itertools::map([](const auto& elem) {
764+
return attr_line_t().append(elem).with_attr_for_all(
765+
lnav::prompt::SUBST_TEXT.value(elem.to_string()));
766+
});
767+
tc.open_popup_for_completion(0, poss);
768+
}
769+
770+
void
771+
filter_sub_source::level_filter_row::ti_perform(textview_curses* top_view,
772+
textinput_curses& tc,
773+
filter_sub_source& parent)
774+
{
775+
auto lev = tc.get_content();
776+
auto new_level = string2level(lev.c_str(), lev.size(), false);
777+
top_view->get_sub_source()->set_min_log_level(new_level);
778+
}
779+
780+
void
781+
filter_sub_source::level_filter_row::ti_abort(textview_curses* top_view,
782+
textinput_curses& tc,
783+
filter_sub_source& parent)
784+
{
785+
top_view->get_sub_source()->set_min_log_level(parent.fss_curr_level);
786+
}
787+
673788
bool
674789
filter_sub_source::time_filter_row::prime_text_input(textview_curses* top_view,
675790
textinput_curses& ti,
@@ -1227,6 +1342,10 @@ filter_sub_source::rows_for(textview_curses* tc) const
12271342
}
12281343
}
12291344

1345+
if (tss->get_min_log_level() != LEVEL_UNKNOWN) {
1346+
retval.emplace_back(std::make_unique<level_filter_row>());
1347+
}
1348+
12301349
auto& fs = tss->get_filters();
12311350
for (auto& tf : fs) {
12321351
retval.emplace_back(std::make_unique<text_filter_row>(tf));

0 commit comments

Comments
 (0)