dev: lay ground for sending filters via get params

This commit is contained in:
Jeremy Wall 2024-03-12 20:33:05 -04:00
parent 02314a3309
commit cef7b42fac
4 changed files with 38 additions and 6 deletions

View File

@ -1,3 +1,4 @@
use std::collections::HashMap;
// Copyright 2023 Jeremy Wall
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -120,12 +121,13 @@ pub struct LogStream {
pub query_type: QueryType,
}
pub async fn prom_query_data(
pub async fn prom_query_data<'a>(
graph: &Graph,
dash: &Dashboard,
query_span: Option<GraphSpan>,
filters: &Option<HashMap<&'a str, &'a str>>,
) -> Result<Vec<QueryResult>> {
let connections = graph.get_query_connections(&dash.span, &query_span);
let connections = graph.get_query_connections(&dash.span, &query_span, filters);
let mut data = Vec::new();
for conn in connections {
data.push(prom_to_samples(
@ -205,12 +207,14 @@ impl Graph {
&'graph self,
graph_span: &'graph Option<GraphSpan>,
query_span: &'graph Option<GraphSpan>,
filters: &'graph Option<HashMap<&'graph str, &'graph str>>,
) -> Vec<PromQueryConn<'conn>> {
let mut conns = Vec::new();
for plot in self.plots.iter() {
debug!(
query = plot.query,
source = plot.source,
filters = ?filters,
"Getting query connection for graph",
);
let mut conn = PromQueryConn::new(
@ -219,6 +223,9 @@ impl Graph {
self.query_type.clone(),
plot.meta.clone(),
);
if let Some(filters) = filters {
conn = conn.with_filters(filters);
}
// Query params take precendence over all other settings. Then graph settings take
// precedences and finally the dashboard settings take precendence
if let Some((end, duration, step_duration)) = graph_span_to_tuple(query_span) {

View File

@ -53,7 +53,7 @@ struct Cli {
async fn validate(dash: &Dashboard) -> anyhow::Result<()> {
if let Some(ref graphs) = dash.graphs {
for graph in graphs.iter() {
let data = prom_query_data(graph, &dash, None).await;
let data = prom_query_data(graph, &dash, None, &None).await;
if data.is_err() {
error!(err=?data, "Invalid dashboard graph query or queries");
}

View File

@ -30,6 +30,7 @@ pub struct PromQueryConn<'conn> {
query: &'conn str,
span: Option<TimeSpan>,
query_type: QueryType,
filters: Option<&'conn HashMap<&'conn str, &'conn str>>,
pub meta: PlotMeta,
}
@ -46,9 +47,16 @@ impl<'conn> PromQueryConn<'conn> {
query_type,
meta,
span: None,
filters: None,
}
}
pub fn with_filters(mut self, filters: &'conn HashMap<&'conn str, &'conn str>) -> Self {
self.filters = Some(filters);
self
}
pub fn with_span(
mut self,
end: DateTime<Utc>,

View File

@ -54,7 +54,7 @@ pub async fn loki_query(
.expect("No logs in this dashboard")
.get(loki_idx)
.expect(&format!("No such log query {}", loki_idx));
let plots = vec![loki_query_data(log, dash, query_to_graph_span(query))
let plots = vec![loki_query_data(log, dash, query_to_graph_span(&query))
.await
.expect("Unable to get log query results")];
Json(GraphPayload {
@ -79,7 +79,8 @@ pub async fn graph_query(
.expect("No graphs in this dashboard")
.get(graph_idx)
.expect(&format!("No such graph in dasboard {}", dash_idx));
let plots = prom_query_data(graph, dash, query_to_graph_span(query))
let filters = query_to_filterset(&query);
let plots = prom_query_data(graph, dash, query_to_graph_span(&query), &filters)
.await
.expect("Unable to get query results");
Json(GraphPayload {
@ -89,7 +90,23 @@ pub async fn graph_query(
})
}
fn query_to_graph_span(query: HashMap<String, String>) -> Option<GraphSpan> {
fn query_to_filterset<'v, 'a: 'v>(query: &'a HashMap<String, String>) -> Option<HashMap<&'v str, &'v str>> {
let mut label_set = HashMap::new();
for (k, v) in query.iter() {
if k.starts_with("filter-") {
if let Some(label) = k.strip_prefix("filter-") {
label_set.insert(label, v.as_str());
}
}
}
if label_set.is_empty() {
None
} else {
Some(label_set)
}
}
fn query_to_graph_span<'a>(query: &'a HashMap<String, String>) -> Option<GraphSpan> {
let query_span = {
if query.contains_key("end")
&& query.contains_key("duration")