use model::Field;
use model::FieldId;
use model::Nameable;
use model::Queriable;
use model::Recursive;
use render::RenderConfig;
use render::RenderOpenMetricsConfigBuilder;
use super::*;
impl CommonField {
pub fn get_render_config(&self) -> RenderConfig {
let rc = render::RenderConfigBuilder::new();
match self {
Self::Timestamp => rc.title("Timestamp").width(10),
Self::Datetime => rc.title("Datetime").width(19),
}
.get()
}
}
impl<F> DumpField<F>
where
F: FieldId,
<<F as FieldId>::Queriable as Queriable>::FieldId: ToString,
{
fn get_field_id_str(&self) -> String {
match self {
Self::Common(common) => common.to_string(),
Self::FieldId(field_id) => field_id.to_string(),
}
}
}
impl<F> DumpField<F>
where
F: FieldId,
F::Queriable: HasRenderConfigForDump,
{
pub fn get_render_config(&self) -> RenderConfig {
match self {
Self::Common(common) => common.get_render_config(),
Self::FieldId(field_id) => F::Queriable::get_render_config_for_dump(field_id),
}
}
pub fn get_openmetrics_render_config(
&self,
model: &F::Queriable,
) -> Option<RenderOpenMetricsConfigBuilder> {
match self {
Self::Common(_) => None,
Self::FieldId(field_id) => model.get_openmetrics_config_for_dump(field_id),
}
}
pub fn get_field(&self, ctx: &CommonFieldContext, model: &F::Queriable) -> Option<Field> {
match self {
Self::Common(common) => common.get_field(ctx),
Self::FieldId(field_id) => model.query(field_id),
}
}
pub fn dump_field(
&self,
ctx: &CommonFieldContext,
model: &F::Queriable,
raw: bool,
fixed_width: bool,
) -> String {
let mut config = self.get_render_config();
if raw {
config.format = None;
config.suffix = None;
}
config.render(self.get_field(ctx, model), fixed_width)
}
pub fn dump_field_openmetrics(
&self,
key: &str,
ctx: &CommonFieldContext,
model: &F::Queriable,
) -> Option<String> {
match self.get_field(ctx, model) {
Some(f) => self.get_openmetrics_render_config(model).map(|b| {
b.label("hostname", &ctx.hostname)
.build()
.render(key, f, ctx.timestamp)
}),
None => None,
}
}
}
impl<F> DumpField<F>
where
F: FieldId,
F::Queriable: HasRenderConfigForDump + Recursive,
{
pub fn dump_field_indented(
&self,
ctx: &CommonFieldContext,
model: &F::Queriable,
raw: bool,
fixed_width: bool,
) -> String {
let mut config = self.get_render_config();
if raw {
config.format = None;
config.suffix = None;
}
config.render_indented(self.get_field(ctx, model), fixed_width, model.get_depth())
}
}
pub fn dump_kv<T: HasRenderConfigForDump>(
fields: &[DumpField<T::FieldId>],
ctx: &CommonFieldContext,
model: &T,
raw: bool,
) -> String {
let mut res = String::new();
for field in fields {
let config = field.get_render_config();
res.push_str(&format!(
"{}: {}\n",
config.render_title(false),
field.dump_field(ctx, model, raw, false),
));
}
res.push('\n');
res
}
pub fn dump_json<T: HasRenderConfigForDump>(
fields: &[DumpField<T::FieldId>],
ctx: &CommonFieldContext,
model: &T,
raw: bool,
) -> Value {
let mut res = json!({});
for field in fields {
let config = field.get_render_config();
res[config.render_title(false)] = json!(field.dump_field(ctx, model, raw, false));
}
res
}
fn dump_title_line<F>(fields: &[DumpField<F>], sep: &'static str, fixed_width: bool) -> String
where
F: FieldId,
F::Queriable: HasRenderConfigForDump,
{
let mut line = String::new();
for field in fields {
line.push_str(&field.get_render_config().render_title(fixed_width));
line.push_str(sep);
}
line.push('\n');
line
}
pub fn dump_raw<T: HasRenderConfigForDump>(
fields: &[DumpField<T::FieldId>],
ctx: &CommonFieldContext,
model: &T,
round: usize,
repeat_title: Option<usize>,
disable_title: bool,
raw: bool,
) -> String {
let mut res = String::new();
let repeat = repeat_title.unwrap_or(0);
if !disable_title && (round == 0 || (repeat != 0 && round % repeat == 0)) {
res.push_str(&dump_title_line(fields, " ", true));
}
for field in fields {
res.push_str(&field.dump_field(ctx, model, raw, true));
res.push(' ');
}
res.push('\n');
res
}
pub fn dump_raw_indented<T: HasRenderConfigForDump + Recursive>(
fields: &[DumpField<T::FieldId>],
ctx: &CommonFieldContext,
model: &T,
round: usize,
repeat_title: Option<usize>,
disable_title: bool,
raw: bool,
) -> String {
let mut res = String::new();
let repeat = repeat_title.unwrap_or(0);
if !disable_title && (round == 0 || (repeat != 0 && round % repeat == 0)) {
res.push_str(&dump_title_line(fields, " ", true));
}
for field in fields {
res.push_str(&field.dump_field_indented(ctx, model, raw, true));
res.push(' ');
}
res.push('\n');
res
}
pub fn dump_csv<T: HasRenderConfigForDump>(
fields: &[DumpField<T::FieldId>],
ctx: &CommonFieldContext,
model: &T,
round: usize,
disable_title: bool,
raw: bool,
) -> String {
let mut res = String::new();
if !disable_title && round == 0 {
res.push_str(&dump_title_line(fields, ",", false));
}
for field in fields {
res.push_str(&field.dump_field(ctx, model, raw, false));
res.push(',');
}
res.push('\n');
res
}
pub fn dump_tsv<T: HasRenderConfigForDump>(
fields: &[DumpField<T::FieldId>],
ctx: &CommonFieldContext,
model: &T,
round: usize,
disable_title: bool,
raw: bool,
) -> String {
let mut res = String::new();
if !disable_title && round == 0 {
res.push_str(&dump_title_line(fields, "\t", false));
}
for field in fields {
res.push_str(&field.dump_field(ctx, model, raw, false));
res.push('\t');
}
res.push('\n');
res
}
pub fn dump_openmetrics<T>(
fields: &[DumpField<T::FieldId>],
ctx: &CommonFieldContext,
model: &T,
) -> String
where
T: HasRenderConfigForDump,
T: Nameable,
T::FieldId: ToString,
{
fields
.iter()
.filter_map(|field| {
let key = format!(
"{}_{}",
T::name(),
field.get_field_id_str().replace('.', "_")
);
field.dump_field_openmetrics(&key, ctx, model)
})
.flat_map(|s| s.chars().collect::<Vec<_>>().into_iter())
.collect::<String>()
}