Skip to content

Commit d31334c

Browse files
committed
[metrics] handle non-metrics file better
1 parent a1f91b3 commit d31334c

23 files changed

Lines changed: 175 additions & 42 deletions

src/log_format_impls.cc

Lines changed: 66 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ class metrics_log_format : public log_format {
441441
{
442442
this->lf_multiline = false;
443443
this->lf_is_metric = true;
444+
this->lf_time_ordered = false;
444445
}
445446

446447
const intern_string_t get_name() const override
@@ -500,13 +501,15 @@ class metrics_log_format : public log_format {
500501
if (cell_len > stats.lvs_width) {
501502
stats.lvs_width = cell_len;
502503
}
503-
parse_cell(iter).match(
504-
[](empty_cell) {},
505-
[&stats](int64_t i) {
506-
stats.add_value(static_cast<double>(i));
507-
},
508-
[&stats](double d) { stats.add_value(d); },
509-
[&stats](humanized_cell hc) { stats.add_value(hc.value); });
504+
parse_cell(iter, parse_context::scan)
505+
.match(
506+
[](empty_cell) {},
507+
[&stats](int64_t i) {
508+
stats.add_value(static_cast<double>(i));
509+
},
510+
[&stats](double d) { stats.add_value(d); },
511+
[&stats](humanized_cell hc) { stats.add_value(hc.value); },
512+
[](const text_cell& tc) {});
510513
}
511514
if (field_index < this->mlf_field_defs.size()) {
512515
return scan_error{fmt::format(
@@ -515,6 +518,15 @@ class metrics_log_format : public log_format {
515518
field_index,
516519
this->mlf_field_defs.size())};
517520
}
521+
if (!this->lf_specialized) {
522+
auto number_cells = 0;
523+
for (const auto& stats : sbc.sbc_value_stats) {
524+
number_cells += stats.lvs_count;
525+
}
526+
if (number_cells == 0) {
527+
return scan_error{"metric row has no numeric fields"};
528+
}
529+
}
518530

519531
return scan_match{500};
520532
}
@@ -531,11 +543,9 @@ class metrics_log_format : public log_format {
531543
// post-clear scan arrives here with an empty `dst`. Seed
532544
// from epoch rather than reading `dst.back()` on an empty
533545
// vector.
534-
const auto prev_time = dst.empty()
535-
? std::chrono::microseconds::zero()
536-
: dst.back().get_time<>();
537-
dst.emplace_back(
538-
li.li_file_range.fr_offset, prev_time, LEVEL_STATS);
546+
const auto prev_time = dst.empty() ? std::chrono::microseconds::zero()
547+
: dst.back().get_time<>();
548+
dst.emplace_back(li.li_file_range.fr_offset, prev_time, LEVEL_STATS);
539549
auto retval = this->parse_line(line_sf, dst, sbc);
540550
if (!retval.is<scan_match>()) {
541551
dst.pop_back();
@@ -560,8 +570,7 @@ class metrics_log_format : public log_format {
560570
// subsequent timestamp parses against the wrong zone.
561571
{
562572
auto file_options = lf.get_file_options();
563-
this->lf_date_time.dts_default_zone
564-
= file_options
573+
this->lf_date_time.dts_default_zone = file_options
565574
? file_options->second.fo_default_zone.pp_value
566575
: nullptr;
567576
}
@@ -734,18 +743,24 @@ class metrics_log_format : public log_format {
734743
if (mlf_hidden_columns.count(meta.lvm_name) != 0) {
735744
meta.lvm_user_hidden = true;
736745
}
737-
parse_cell(iter).match(
738-
[&](empty_cell) { values.lvv_values.emplace_back(meta); },
739-
[&](int64_t i) { values.lvv_values.emplace_back(meta, i); },
740-
[&](double d) { values.lvv_values.emplace_back(meta, d); },
741-
[&](humanized_cell hc) {
742-
// Carry the detected unit on the per-value meta so
743-
// downstream renderers can call humanize::format
744-
// against the base-unit value.
745-
auto cell_meta = meta;
746-
cell_meta.lvm_unit_suffix = hc.unit_suffix;
747-
values.lvv_values.emplace_back(cell_meta, hc.value);
748-
});
746+
parse_cell(iter, parse_context::annotate)
747+
.match(
748+
[&](empty_cell) { values.lvv_values.emplace_back(meta); },
749+
[&](int64_t i) { values.lvv_values.emplace_back(meta, i); },
750+
[&](double d) { values.lvv_values.emplace_back(meta, d); },
751+
[&](humanized_cell hc) {
752+
// Carry the detected unit on the per-value meta so
753+
// downstream renderers can call humanize::format
754+
// against the base-unit value.
755+
auto cell_meta = meta;
756+
cell_meta.lvm_unit_suffix = hc.unit_suffix;
757+
values.lvv_values.emplace_back(cell_meta, hc.value);
758+
},
759+
[&](const text_cell& tc) {
760+
values.lvv_values.emplace_back(meta, tc.value);
761+
values.lvv_values.back().lv_meta.lvm_kind
762+
= value_kind_t::VALUE_TEXT;
763+
});
749764
values.lvv_values.back().lv_origin = lr;
750765
}
751766

@@ -776,10 +791,19 @@ class metrics_log_format : public log_format {
776791
double value;
777792
intern_string_t unit_suffix;
778793
};
779-
using parsed_cell_t
780-
= mapbox::util::variant<empty_cell, int64_t, double, humanized_cell>;
794+
struct text_cell {
795+
std::string value;
796+
};
797+
using parsed_cell_t = mapbox::util::
798+
variant<empty_cell, int64_t, double, humanized_cell, text_cell>;
799+
800+
enum class parse_context {
801+
scan,
802+
annotate,
803+
};
781804

782-
static parsed_cell_t parse_cell(const separated_string::iterator& iter)
805+
static parsed_cell_t parse_cell(const separated_string::iterator& iter,
806+
parse_context pc)
783807
{
784808
const auto field = *iter;
785809
switch (iter.kind()) {
@@ -812,7 +836,19 @@ class metrics_log_format : public log_format {
812836
}
813837
case separated_string::cell_kind::other: {
814838
// Plain text; humanize wouldn't have parsed it.
815-
return parsed_cell_t{empty_cell{}};
839+
switch (pc) {
840+
case parse_context::scan:
841+
// During scanning, treat unparseable text as
842+
// empty so it doesn't mess with stats or
843+
// trigger a type change on the column.
844+
return parsed_cell_t{empty_cell{}};
845+
case parse_context::annotate:
846+
// During annotation, preserve the text so the
847+
// renderer can show it and the user can query
848+
// against it.
849+
return parsed_cell_t{text_cell{
850+
separated_string::unescape_quoted(field)}};
851+
}
816852
}
817853
}
818854
return parsed_cell_t{empty_cell{}};

src/logfile.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,9 @@ logfile::process_prefix(shared_buffer_ref& sbr,
10531053
curr->get_name().c_str());
10541054
},
10551055
[this, curr](const log_format::scan_error& se) {
1056+
if (this->lf_format == nullptr) {
1057+
return;
1058+
}
10561059
this->lf_invalid_lines.ili_total += 1;
10571060
if (this->lf_invalid_lines.ili_lines.size()
10581061
>= invalid_line_info::MAX_INVALID_LINES)

src/logfile_sub_source.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -359,9 +359,6 @@ logfile_sub_source::text_value_for_line(textview_curses& tc,
359359
auto emit_value = [&](logfile* src_lf,
360360
const logline_value& lv,
361361
const char* src_data) {
362-
if (lv.lv_meta.lvm_kind == value_kind_t::VALUE_NULL) {
363-
return;
364-
}
365362
// Respect `:hide-fields metrics_log.<col>` — a user-hidden
366363
// column drops out of the composed line entirely.
367364
if (lv.lv_meta.is_hidden()) {
@@ -413,10 +410,13 @@ logfile_sub_source::text_value_for_line(textview_curses& tc,
413410
stats != nullptr ? static_cast<size_t>(stats->lvs_width)
414411
: rendered.size());
415412
const auto value_start = static_cast<int>(composed.size());
416-
if (col_width > rendered.size()) {
413+
if (have_numeric && col_width > rendered.size()) {
417414
composed.append(col_width - rendered.size(), ' ');
418415
}
419416
composed.append(rendered);
417+
if (!have_numeric && col_width > rendered.size()) {
418+
composed.append(col_width - rendered.size(), ' ');
419+
}
420420

421421
if (have_numeric && stats != nullptr && stats->lvs_count > 0
422422
&& col_width > 0)

src/metrics_vtab.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,12 @@ CREATE TABLE lnav_db.all_metrics (
253253
} else if (col == 5) {
254254
if (lv.lv_meta.lvm_kind == value_kind_t::VALUE_INTEGER) {
255255
sqlite3_result_int64(ctx, lv.lv_value.i);
256-
} else if (lv.lv_meta.lvm_kind
257-
== value_kind_t::VALUE_FLOAT)
256+
} else if (lv.lv_meta.lvm_kind == value_kind_t::VALUE_FLOAT)
258257
{
259258
sqlite3_result_double(ctx, lv.lv_value.d);
259+
} else if (lv.lv_meta.lvm_kind == value_kind_t::VALUE_TEXT)
260+
{
261+
to_sqlite(ctx, lv.text_value_fragment());
260262
} else {
261263
sqlite3_result_null(ctx);
262264
}

test/expected/Makefile.am

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,8 @@ dist_noinst_DATA = \
676676
test_metric_log.sh_4db8507cd55d807eca20cba3ba401863ae301e7c.out \
677677
test_metric_log.sh_50f252ff4452cc765fc67436d5692ede72a9e157.err \
678678
test_metric_log.sh_50f252ff4452cc765fc67436d5692ede72a9e157.out \
679+
test_metric_log.sh_5987812b0d6c70a719e43b294aabb6640f29d7d6.err \
680+
test_metric_log.sh_5987812b0d6c70a719e43b294aabb6640f29d7d6.out \
679681
test_metric_log.sh_5d58f57d6c95ff38e484fe5a470bb7bb9b95c31e.err \
680682
test_metric_log.sh_5d58f57d6c95ff38e484fe5a470bb7bb9b95c31e.out \
681683
test_metric_log.sh_5e5bf755596469de3f3d01c71379e6bb3a575ffc.err \
@@ -716,10 +718,14 @@ dist_noinst_DATA = \
716718
test_metric_log.sh_a9380b497697901ab77c8e207c0cc08bcdd031c0.out \
717719
test_metric_log.sh_ad2750b3c03c59b211b54a76f70d04bcd4c9588d.err \
718720
test_metric_log.sh_ad2750b3c03c59b211b54a76f70d04bcd4c9588d.out \
721+
test_metric_log.sh_b602843dec24ff5f8585162c87fc6921d7ca8635.err \
722+
test_metric_log.sh_b602843dec24ff5f8585162c87fc6921d7ca8635.out \
719723
test_metric_log.sh_b8313adbb4cceee46c1672d8cecac09910eb2a59.err \
720724
test_metric_log.sh_b8313adbb4cceee46c1672d8cecac09910eb2a59.out \
721725
test_metric_log.sh_bba1f5ef936f30f029aabc26afbbf2cef3714a03.err \
722726
test_metric_log.sh_bba1f5ef936f30f029aabc26afbbf2cef3714a03.out \
727+
test_metric_log.sh_bce1444a2940943fd594d52e3f1d877b17c62e80.err \
728+
test_metric_log.sh_bce1444a2940943fd594d52e3f1d877b17c62e80.out \
723729
test_metric_log.sh_ccfa12f1625f04c74ff9ab18b2c3432da3f38eb0.err \
724730
test_metric_log.sh_ccfa12f1625f04c74ff9ab18b2c3432da3f38eb0.out \
725731
test_metric_log.sh_d7d470a79a1107a0a911ddff6ac8c18e1c939590.err \
@@ -732,10 +738,14 @@ dist_noinst_DATA = \
732738
test_metric_log.sh_e8e41753e6506f11710937119c931d50deebd0a1.out \
733739
test_metric_log.sh_f580091f21b2aad05cce6de17088d3ddefd21919.err \
734740
test_metric_log.sh_f580091f21b2aad05cce6de17088d3ddefd21919.out \
741+
test_metric_log.sh_f7220aac78792df8347a4f3f98899dff4e449f7d.err \
742+
test_metric_log.sh_f7220aac78792df8347a4f3f98899dff4e449f7d.out \
735743
test_metric_log.sh_f98800e078b61e68cd4a38e0aa0255e8b7fdd149.err \
736744
test_metric_log.sh_f98800e078b61e68cd4a38e0aa0255e8b7fdd149.out \
737745
test_metric_log.sh_fbc1c62d020654cde7bcdca14591e6f7c679c6e0.err \
738746
test_metric_log.sh_fbc1c62d020654cde7bcdca14591e6f7c679c6e0.out \
747+
test_metric_log.sh_fd547d2682d1ac79fd4f78a22d81da698660a3da.err \
748+
test_metric_log.sh_fd547d2682d1ac79fd4f78a22d81da698660a3da.out \
739749
test_metric_log.sh_ff5e772ec1dd920dad2c4d775403573be0d088dd.err \
740750
test_metric_log.sh_ff5e772ec1dd920dad2c4d775403573be0d088dd.out \
741751
test_pretty_print.sh_3c255c3c8b28df9d694b329a265e8b8140dae4a2.err \
@@ -826,8 +836,6 @@ dist_noinst_DATA = \
826836
test_sessions.sh_11283dc874ab809af1d61848ac659b79930c58b5.out \
827837
test_sessions.sh_13cbceaaa93ddd2756eef4c6a99500c466c60f10.err \
828838
test_sessions.sh_13cbceaaa93ddd2756eef4c6a99500c466c60f10.out \
829-
test_sessions.sh_14aae534ade7470dee4e812297dd719f0725fee4.err \
830-
test_sessions.sh_14aae534ade7470dee4e812297dd719f0725fee4.out \
831839
test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.err \
832840
test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.out \
833841
test_sessions.sh_2c01cde634f96b5425df76c8b0adbd5974897d20.err \
@@ -874,6 +882,8 @@ dist_noinst_DATA = \
874882
test_sessions.sh_7f4805745c6551e9f3ecbb809ffb4cfe8bce9c6f.out \
875883
test_sessions.sh_858fd0081ed9c46dd81e2f81f1090756f2463558.err \
876884
test_sessions.sh_858fd0081ed9c46dd81e2f81f1090756f2463558.out \
885+
test_sessions.sh_882d7edbe0b797245bbbbd5c7bb7e76a9b5f864d.err \
886+
test_sessions.sh_882d7edbe0b797245bbbbd5c7bb7e76a9b5f864d.out \
877887
test_sessions.sh_903b41c950f5f90d7786d7a09bb6e2f217654b15.err \
878888
test_sessions.sh_903b41c950f5f90d7786d7a09bb6e2f217654b15.out \
879889
test_sessions.sh_92a98a3e4e3a10bf1f2371d21a8282c5d3d4baa5.err \
@@ -892,12 +902,8 @@ dist_noinst_DATA = \
892902
test_sessions.sh_a92822d121a836140a401fd71535dc4a7a8d5b48.out \
893903
test_sessions.sh_aa301115c684a1ab028aa8a07c684d40e455134c.err \
894904
test_sessions.sh_aa301115c684a1ab028aa8a07c684d40e455134c.out \
895-
test_sessions.sh_b3d71a87fcb4e3487f71ccad8c6ce681db220572.err \
896-
test_sessions.sh_b3d71a87fcb4e3487f71ccad8c6ce681db220572.out \
897905
test_sessions.sh_b932b33dd087b94d4306dd179c5d4f9ddd394960.err \
898906
test_sessions.sh_b932b33dd087b94d4306dd179c5d4f9ddd394960.out \
899-
test_sessions.sh_ba02a743ac8f9af518f28efe2cc832c3fff853dd.err \
900-
test_sessions.sh_ba02a743ac8f9af518f28efe2cc832c3fff853dd.out \
901907
test_sessions.sh_ba1ded92531350668301431db64df2d2f4a2e9ee.err \
902908
test_sessions.sh_ba1ded92531350668301431db64df2d2f4a2e9ee.out \
903909
test_sessions.sh_bd713216a3fdfe394d0c00346645b7fdd8ac65da.err \
@@ -914,6 +920,8 @@ dist_noinst_DATA = \
914920
test_sessions.sh_ddf45811e9906de9f3930fe802ac7b2cc6e48106.out \
915921
test_sessions.sh_de50586d15f64bc767b1d9f64dce5d4ff649f0bd.err \
916922
test_sessions.sh_de50586d15f64bc767b1d9f64dce5d4ff649f0bd.out \
923+
test_sessions.sh_de8750378504977ee44faa266996a26efd7f3a88.err \
924+
test_sessions.sh_de8750378504977ee44faa266996a26efd7f3a88.out \
917925
test_sessions.sh_e47760d896ef5e5eab2a4a15f8e6b8a69cdd5280.err \
918926
test_sessions.sh_e47760d896ef5e5eab2a4a15f8e6b8a69cdd5280.out \
919927
test_sessions.sh_e492b83e19ae525a97ef0140f055e2954b69225a.err \

test/expected/test_metric_log.sh_5987812b0d6c70a719e43b294aabb6640f29d7d6.err

Whitespace-only changes.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
log_line,log_time,metric,value
2+
0,2026-04-14T10:00:00.000000,cpu_pct,0
3+
0,2026-04-14T10:00:00.000000,mem_mb,500
4+
1,2026-04-14T10:00:10.000000,cpu_pct,10
5+
1,2026-04-14T10:00:10.000000,mem_mb,1000
6+
2,2026-04-14T10:00:20.000000,cpu_pct,20
7+
2,2026-04-14T10:00:20.000000,mem_mb,2000
8+
3,2026-04-14T10:00:30.000000,cpu_pct,30
9+
3,2026-04-14T10:00:30.000000,mem_mb,3000

test/expected/test_metric_log.sh_b602843dec24ff5f8585162c87fc6921d7ca8635.err

Whitespace-only changes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
n
2+
0

test/expected/test_metric_log.sh_bce1444a2940943fd594d52e3f1d877b17c62e80.err

Whitespace-only changes.

0 commit comments

Comments
 (0)