maint: formatting fixes

This commit is contained in:
Jeremy Wall 2024-03-02 10:14:36 -05:00
parent 1de77b189d
commit 464f5db99c
6 changed files with 79 additions and 41 deletions

View File

@ -13,14 +13,16 @@
// limitations under the License. // limitations under the License.
use std::path::Path; use std::path::Path;
use anyhow::Result;
use chrono::prelude::*; use chrono::prelude::*;
use chrono::Duration; use chrono::Duration;
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
use serde_yaml; use serde_yaml;
use tracing::{debug, error}; use tracing::{debug, error};
use anyhow::Result;
use crate::query::{PromQueryConn, QueryType, QueryResult, LokiConn, prom_to_samples, loki_to_sample}; use crate::query::{
loki_to_sample, prom_to_samples, LokiConn, PromQueryConn, QueryResult, QueryType,
};
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PlotMeta { pub struct PlotMeta {
@ -118,22 +120,27 @@ pub struct LogStream {
pub query_type: QueryType, pub query_type: QueryType,
} }
pub async fn prom_query_data(graph: &Graph, dash: &Dashboard, query_span: Option<GraphSpan>) -> Result<Vec<QueryResult>> { pub async fn prom_query_data(
graph: &Graph,
dash: &Dashboard,
query_span: Option<GraphSpan>,
) -> Result<Vec<QueryResult>> {
let connections = graph.get_query_connections(&dash.span, &query_span); let connections = graph.get_query_connections(&dash.span, &query_span);
let mut data = Vec::new(); let mut data = Vec::new();
for conn in connections { for conn in connections {
data.push(prom_to_samples( data.push(prom_to_samples(
conn.get_results() conn.get_results().await?.data().clone(),
.await?
.data()
.clone(),
conn.meta, conn.meta,
)); ));
} }
Ok(data) Ok(data)
} }
pub async fn loki_query_data(stream: &LogStream, dash: &Dashboard, query_span: Option<GraphSpan>) -> Result<QueryResult> { pub async fn loki_query_data(
stream: &LogStream,
dash: &Dashboard,
query_span: Option<GraphSpan>,
) -> Result<QueryResult> {
let conn = stream.get_query_connection(&dash.span, &query_span); let conn = stream.get_query_connection(&dash.span, &query_span);
let response = conn.get_results().await?; let response = conn.get_results().await?;
if response.status == "success" { if response.status == "success" {
@ -206,7 +213,12 @@ impl Graph {
source = plot.source, source = plot.source,
"Getting query connection for graph", "Getting query connection for graph",
); );
let mut conn = PromQueryConn::new(&plot.source, &plot.query, self.query_type.clone(), plot.meta.clone()); let mut conn = PromQueryConn::new(
&plot.source,
&plot.query,
self.query_type.clone(),
plot.meta.clone(),
);
// Query params take precendence over all other settings. Then graph settings take // Query params take precendence over all other settings. Then graph settings take
// precedences and finally the dashboard settings take precendence // precedences and finally the dashboard settings take precendence
if let Some((end, duration, step_duration)) = graph_span_to_tuple(query_span) { if let Some((end, duration, step_duration)) = graph_span_to_tuple(query_span) {

View File

@ -11,15 +11,15 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::path::PathBuf;
use anyhow; use anyhow;
use axum::{self, extract::State, routing::*, Router}; use axum::{self, extract::State, routing::*, Router};
use clap::{self, Parser, ValueEnum}; use clap::{self, Parser, ValueEnum};
use dashboard::{Dashboard, prom_query_data}; use dashboard::{prom_query_data, Dashboard};
use std::path::PathBuf;
use tokio::net::TcpListener; use tokio::net::TcpListener;
use tower_http::trace::TraceLayer; use tower_http::trace::TraceLayer;
use tracing::{error, info};
use tracing::Level; use tracing::Level;
use tracing::{error, info};
use tracing_subscriber::FmtSubscriber; use tracing_subscriber::FmtSubscriber;
mod dashboard; mod dashboard;
@ -101,7 +101,9 @@ async fn main() -> anyhow::Result<()> {
.layer(TraceLayer::new_for_http()) .layer(TraceLayer::new_for_http())
.with_state(State(config.clone())); .with_state(State(config.clone()));
let socket_addr = args.listen.unwrap_or("127.0.0.1:3000".to_string()); let socket_addr = args.listen.unwrap_or("127.0.0.1:3000".to_string());
let listener = TcpListener::bind(socket_addr).await.expect("Unable to bind listener to address"); let listener = TcpListener::bind(socket_addr)
.await
.expect("Unable to bind listener to address");
axum::serve(listener, router).await?; axum::serve(listener, router).await?;
Ok(()) Ok(())
} }

View File

@ -13,8 +13,8 @@
// limitations under the License. // limitations under the License.
use std::collections::HashMap; use std::collections::HashMap;
use serde::{Serialize, Deserialize};
use chrono::prelude::*; use chrono::prelude::*;
use serde::{Deserialize, Serialize};
use crate::dashboard::PlotMeta; use crate::dashboard::PlotMeta;
@ -34,7 +34,6 @@ pub struct TimeSpan {
pub step_seconds: i64, pub step_seconds: i64,
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct DataPoint { pub struct DataPoint {
timestamp: f64, timestamp: f64,
@ -92,5 +91,5 @@ impl std::fmt::Debug for QueryResult {
} }
} }
pub use prom::*;
pub use loki::*; pub use loki::*;
pub use prom::*;

View File

@ -22,7 +22,7 @@ use tracing::debug;
use crate::dashboard::PlotMeta; use crate::dashboard::PlotMeta;
use super::{QueryType, TimeSpan, QueryResult, DataPoint}; use super::{DataPoint, QueryResult, QueryType, TimeSpan};
#[derive(Debug)] #[derive(Debug)]
pub struct PromQueryConn<'conn> { pub struct PromQueryConn<'conn> {

View File

@ -22,10 +22,12 @@ use axum::{
// https://maud.lambda.xyz/getting-started.html // https://maud.lambda.xyz/getting-started.html
use maud::{html, Markup}; use maud::{html, Markup};
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
use tracing::debug; use tracing::debug;
use crate::dashboard::{Dashboard, Graph, GraphSpan, AxisDefinition, Orientation, prom_query_data, loki_query_data}; use crate::dashboard::{
loki_query_data, prom_query_data, AxisDefinition, Dashboard, Graph, GraphSpan, Orientation,
};
use crate::query::QueryResult; use crate::query::QueryResult;
type Config = State<Arc<Vec<Dashboard>>>; type Config = State<Arc<Vec<Dashboard>>>;
@ -43,12 +45,23 @@ pub async fn loki_query(
Path((dash_idx, loki_idx)): Path<(usize, usize)>, Path((dash_idx, loki_idx)): Path<(usize, usize)>,
Query(query): Query<HashMap<String, String>>, Query(query): Query<HashMap<String, String>>,
) -> Json<GraphPayload> { ) -> Json<GraphPayload> {
let dash = config.get(dash_idx).expect(&format!("No such dashboard index {}", dash_idx)); let dash = config
let log = dash.logs .get(dash_idx)
.as_ref().expect("No logs in this dashboard") .expect(&format!("No such dashboard index {}", dash_idx));
.get(loki_idx).expect(&format!("No such log query {}", loki_idx)); let log = dash
let plots = vec![loki_query_data(log, dash, query_to_graph_span(query)).await.expect("Unable to get log query results")]; .logs
Json(GraphPayload{legend_orientation: None, yaxes: log.yaxes.clone(), plots}) .as_ref()
.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))
.await
.expect("Unable to get log query results")];
Json(GraphPayload {
legend_orientation: None,
yaxes: log.yaxes.clone(),
plots,
})
} }
pub async fn graph_query( pub async fn graph_query(
@ -57,14 +70,23 @@ pub async fn graph_query(
Query(query): Query<HashMap<String, String>>, Query(query): Query<HashMap<String, String>>,
) -> Json<GraphPayload> { ) -> Json<GraphPayload> {
debug!("Getting data for query"); debug!("Getting data for query");
let dash = config.get(dash_idx).expect(&format!("No such dashboard index {}", dash_idx)); let dash = config
.get(dash_idx)
.expect(&format!("No such dashboard index {}", dash_idx));
let graph = dash let graph = dash
.graphs .graphs
.as_ref().expect("No graphs in this dashboard") .as_ref()
.expect("No graphs in this dashboard")
.get(graph_idx) .get(graph_idx)
.expect(&format!("No such graph in dasboard {}", dash_idx)); .expect(&format!("No such graph in dasboard {}", dash_idx));
let plots = prom_query_data(graph, dash, query_to_graph_span(query)).await.expect("Unable to get query results"); let plots = prom_query_data(graph, dash, query_to_graph_span(query))
Json(GraphPayload{legend_orientation: graph.legend_orientation.clone(), yaxes: graph.yaxes.clone(), plots}) .await
.expect("Unable to get query results");
Json(GraphPayload {
legend_orientation: graph.legend_orientation.clone(),
yaxes: graph.yaxes.clone(),
plots,
})
} }
fn query_to_graph_span(query: HashMap<String, String>) -> Option<GraphSpan> { fn query_to_graph_span(query: HashMap<String, String>) -> Option<GraphSpan> {
@ -89,13 +111,13 @@ pub fn mk_api_routes(config: Arc<Vec<Dashboard>>) -> Router<Config> {
// Query routes // Query routes
Router::new() Router::new()
.route( .route(
"/dash/:dash_idx/graph/:graph_idx", "/dash/:dash_idx/graph/:graph_idx",
get(graph_query).with_state(config.clone()), get(graph_query).with_state(config.clone()),
) )
.route( .route(
"/dash/:dash_idx/log/:log_idx", "/dash/:dash_idx/log/:log_idx",
get(loki_query).with_state(config), get(loki_query).with_state(config),
) )
} }
pub fn graph_component(dash_idx: usize, graph_idx: usize, graph: &Graph) -> Markup { pub fn graph_component(dash_idx: usize, graph_idx: usize, graph: &Graph) -> Markup {
@ -105,7 +127,7 @@ pub fn graph_component(dash_idx: usize, graph_idx: usize, graph: &Graph) -> Mark
html!( html!(
div { div {
h2 { (graph.title) " - " a href=(graph_embed_uri) { "embed url" } } h2 { (graph.title) " - " a href=(graph_embed_uri) { "embed url" } }
@if graph.d3_tick_format.is_some() { @if graph.d3_tick_format.is_some() {
graph-plot uri=(graph_data_uri) id=(graph_id) d3-tick-format=(graph.d3_tick_format.as_ref().unwrap()) { } graph-plot uri=(graph_data_uri) id=(graph_id) d3-tick-format=(graph.d3_tick_format.as_ref().unwrap()) { }
} @else { } @else {
graph-plot uri=(graph_data_uri) id=(graph_id) { } graph-plot uri=(graph_data_uri) id=(graph_id) { }
@ -122,7 +144,8 @@ pub async fn graph_ui(
.get(dash_idx) .get(dash_idx)
.expect(&format!("No such dashboard {}", dash_idx)) .expect(&format!("No such dashboard {}", dash_idx))
.graphs .graphs
.as_ref().expect("No graphs in this dashboard") .as_ref()
.expect("No graphs in this dashboard")
.get(graph_idx) .get(graph_idx)
.expect("No such graph"); .expect("No such graph");
graph_component(dash_idx, graph_idx, graph) graph_component(dash_idx, graph_idx, graph)
@ -134,10 +157,13 @@ pub async fn dash_ui(State(config): State<Config>, Path(dash_idx): Path<usize>)
} }
fn dash_elements(config: State<Arc<Vec<Dashboard>>>, dash_idx: usize) -> maud::PreEscaped<String> { fn dash_elements(config: State<Arc<Vec<Dashboard>>>, dash_idx: usize) -> maud::PreEscaped<String> {
let dash = config.get(dash_idx).expect(&format!("No such dashboard {}", dash_idx)); let dash = config
.get(dash_idx)
.expect(&format!("No such dashboard {}", dash_idx));
let graph_iter = dash let graph_iter = dash
.graphs .graphs
.as_ref().expect("No graphs in this dashboard") .as_ref()
.expect("No graphs in this dashboard")
.iter() .iter()
.enumerate() .enumerate()
.collect::<Vec<(usize, &Graph)>>(); .collect::<Vec<(usize, &Graph)>>();

View File

@ -86,7 +86,6 @@ class GraphPlot extends HTMLElement {
this.#duration = this.getAttribute('duration') || null; this.#duration = this.getAttribute('duration') || null;
this.#step_duration = this.getAttribute('step-duration') || null; this.#step_duration = this.getAttribute('step-duration') || null;
this.#d3TickFormat = this.getAttribute('d3-tick-format') || this.#d3TickFormat; this.#d3TickFormat = this.getAttribute('d3-tick-format') || this.#d3TickFormat;
var self = this;
this.reset(); this.reset();
} }