Skip to content

Commit

Permalink
new: options to always show time and level fields (auto by default) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
pamburus authored May 4, 2024
1 parent 1399d74 commit 834b33a
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 53 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ members = [".", "crate/encstr"]
[workspace.package]
repository = "https://github.com/pamburus/hl"
authors = ["Pavel Ivanov <[email protected]>"]
version = "0.29.0-alpha.12"
version = "0.29.0-alpha.13"
edition = "2021"
license = "MIT"

Expand Down
2 changes: 2 additions & 0 deletions etc/defaults/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ fields:
# Configuration of the predefined set of fields.
predefined:
time:
show: auto
names:
[
ts,
Expand All @@ -24,6 +25,7 @@ fields:
logger:
names: [logger, LOGGER, Logger]
level:
show: auto
variants:
- names: [level, LEVEL, Level]
values:
Expand Down
6 changes: 4 additions & 2 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use crate::{
model::{Filter, Parser, ParserSettings, RawRecord, Record, RecordFilter, RecordWithSourceConstructor},
query::Query,
scanning::{BufFactory, Delimit, Delimiter, Scanner, SearchExt, Segment, SegmentBuf, SegmentBufFactory},
settings::{Fields, Formatting},
settings::{FieldShowOption, Fields, Formatting},
theme::{Element, StylingPush, Theme},
timezone::Tz,
IncludeExcludeKeyFilter,
Expand Down Expand Up @@ -670,7 +670,9 @@ impl App {
self.options.formatting.clone(),
)
.with_field_unescaping(!self.options.raw_fields)
.with_flatten(self.options.flatten),
.with_flatten(self.options.flatten)
.with_always_show_time(self.options.fields.settings.predefined.time.show == FieldShowOption::Always)
.with_always_show_level(self.options.fields.settings.predefined.level.show == FieldShowOption::Always),
)
}
}
Expand Down
139 changes: 110 additions & 29 deletions src/formatting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ pub struct RecordFormatter {
ts_width: usize,
hide_empty_fields: bool,
flatten: bool,
always_show_time: bool,
always_show_level: bool,
fields: Arc<IncludeExcludeKeyFilter>,
cfg: Formatting,
}
Expand All @@ -78,6 +80,8 @@ impl RecordFormatter {
ts_width,
hide_empty_fields,
flatten: false,
always_show_time: false,
always_show_level: false,
fields,
cfg,
}
Expand All @@ -93,16 +97,27 @@ impl RecordFormatter {
self
}

pub fn with_always_show_time(mut self, value: bool) -> Self {
self.always_show_time = value;
self
}

pub fn with_always_show_level(mut self, value: bool) -> Self {
self.always_show_level = value;
self
}

pub fn format_record(&self, buf: &mut Buf, rec: &model::Record) {
let mut fs = FormattingState::new(self.flatten && self.unescape_fields);

self.theme.apply(buf, &rec.level, |s| {
//
// time
//
s.element(Element::Time, |s| {
s.batch(|buf| {
if let Some(ts) = &rec.ts {
if let Some(ts) = &rec.ts {
fs.add_element(|| {});
s.element(Element::Time, |s| {
s.batch(|buf| {
aligned_left(buf, self.ts_width, b' ', |mut buf| {
if ts
.as_rfc3339()
Expand All @@ -116,39 +131,46 @@ impl RecordFormatter {
}
}
});
} else {
centered(buf, self.ts_width, b' ', |mut buf| {
buf.extend_from_slice(b"---");
})
});
} else if self.always_show_time {
fs.add_element(|| {});
s.element(Element::Time, |s| {
s.batch(|buf| {
centered(buf, self.ts_width, b'-', |mut buf| {
buf.extend_from_slice(b"-");
});
}
})
});
})
});
}

//
// level
//
s.space();
s.element(Element::Level, |s| {
s.batch(|buf| {
buf.extend_from_slice(self.cfg.punctuation.level_left_separator.as_bytes());
});
s.element(Element::LevelInner, |s| {
let level = match rec.level {
Some(Level::Debug) => Some(b"DBG"),
Some(Level::Info) => Some(b"INF"),
Some(Level::Warning) => Some(b"WRN"),
Some(Level::Error) => Some(b"ERR"),
_ => None,
};
let level = level.or_else(|| self.always_show_level.then(|| b"(?)"));
if let Some(level) = level {
fs.add_element(|| s.space());
s.element(Element::Level, |s| {
s.batch(|buf| {
buf.extend_from_slice(match rec.level {
Some(Level::Debug) => b"DBG",
Some(Level::Info) => b"INF",
Some(Level::Warning) => b"WRN",
Some(Level::Error) => b"ERR",
_ => b"(?)",
})
})
buf.extend_from_slice(self.cfg.punctuation.level_left_separator.as_bytes());
});
s.element(Element::LevelInner, |s| s.batch(|buf| buf.extend_from_slice(level)));
s.batch(|buf| buf.extend_from_slice(self.cfg.punctuation.level_right_separator.as_bytes()));
});
s.batch(|buf| buf.extend_from_slice(self.cfg.punctuation.level_right_separator.as_bytes()));
});
}

//
// logger
//
if let Some(logger) = rec.logger {
s.batch(|buf| buf.push(b' '));
fs.add_element(|| s.batch(|buf| buf.push(b' ')));
s.element(Element::Logger, |s| {
s.element(Element::LoggerInner, |s| {
s.batch(|buf| buf.extend_from_slice(logger.as_bytes()))
Expand Down Expand Up @@ -226,8 +248,10 @@ impl RecordFormatter {
match value {
RawValue::String(value) => {
if !value.is_empty() {
s.reset();
s.space();
fs.add_element(|| {
s.reset();
s.space();
});
s.element(Element::Message, |s| {
s.batch(|buf| buf.with_auto_trim(|buf| MessageFormatAuto::new(value).format(buf).unwrap()))
});
Expand All @@ -251,6 +275,7 @@ impl RecordWithSourceFormatter for RecordFormatter {
struct FormattingState {
key_prefix: KeyPrefix,
flatten: bool,
empty: bool,
}

impl FormattingState {
Expand All @@ -259,6 +284,15 @@ impl FormattingState {
Self {
key_prefix: KeyPrefix::default(),
flatten,
empty: true,
}
}

fn add_element(&mut self, add_space: impl FnOnce()) {
if self.empty {
self.empty = false;
} else {
add_space();
}
}
}
Expand Down Expand Up @@ -438,7 +472,7 @@ impl<'a> FieldFormatter<'a> {

let variant = FormattedFieldVariant::Normal { flatten: fs.flatten };

s.space();
fs.add_element(|| s.space());
s.element(Element::Key, |s| {
s.batch(|buf| {
if fs.flatten {
Expand Down Expand Up @@ -922,4 +956,51 @@ mod tests {
"\u{1b}[0;2;3m00-01-02 03:04:05.123 \u{1b}[0;36m|\u{1b}[0;95mDBG\u{1b}[0;36m|\u{1b}[0;2;3m \u{1b}[0;2;4mtl:\u{1b}[0m \u{1b}[0;1;39mtm \u{1b}[0;32mk-a.va.kb\u{1b}[0;2m=\u{1b}[0;94m42 \u{1b}[0;32mk-a.va.kc\u{1b}[0;2m=\u{1b}[0;94m43\u{1b}[0;2;3m @ tc\u{1b}[0m",
);
}

#[test]
fn test_timestamp_none() {
let rec = Record {
message: Some(RawValue::String(EncodedString::json(r#""tm""#))),
level: Some(Level::Error),
..Default::default()
};

assert_eq!(&format(&rec), "\u{1b}[0;7;91m|ERR|\u{1b}[0m \u{1b}[0;1;39mtm\u{1b}[0m");
}

#[test]
fn test_timestamp_none_always_show() {
let rec = Record {
message: Some(RawValue::String(EncodedString::json(r#""tm""#))),
..Default::default()
};

assert_eq!(
&formatter().with_always_show_time(true).format_to_string(&rec),
"\u{1b}[0;2;3m---------------------\u{1b}[0m \u{1b}[0;1;39mtm\u{1b}[0m",
);
}

#[test]
fn test_level_none() {
let rec = Record {
message: Some(RawValue::String(EncodedString::json(r#""tm""#))),
..Default::default()
};

assert_eq!(&format(&rec), "\u{1b}[0;1;39mtm\u{1b}[0m",);
}

#[test]
fn test_level_none_always_show() {
let rec = Record {
message: Some(RawValue::String(EncodedString::json(r#""tm""#))),
..Default::default()
};

assert_eq!(
&formatter().with_always_show_level(true).format_to_string(&rec),
"\u{1b}[0;36m|(?)|\u{1b}[0m \u{1b}[0;1;39mtm\u{1b}[0m",
);
}
}
2 changes: 2 additions & 0 deletions src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ impl Eq for RawArray<'_> {}

// ---

#[derive(Default)]
pub struct Record<'a> {
pub ts: Option<Timestamp<'a>>,
pub message: Option<RawValue<'a>>,
Expand Down Expand Up @@ -335,6 +336,7 @@ impl<'a> Record<'a> {
}
}

#[derive(Default)]
pub struct RecordFields<'a> {
pub(crate) head: heapless::Vec<(&'a str, RawValue<'a>), RECORD_EXTRA_CAPACITY>,
pub(crate) tail: Vec<(&'a str, RawValue<'a>)>,
Expand Down
Loading

0 comments on commit 834b33a

Please sign in to comment.