mirror of
https://github.com/zaphar/Heracles.git
synced 2025-07-23 12:39:50 -04:00
maint: formatting fixes
This commit is contained in:
parent
1de77b189d
commit
464f5db99c
@ -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) {
|
||||||
|
10
src/main.rs
10
src/main.rs
@ -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(())
|
||||||
}
|
}
|
||||||
|
@ -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::*;
|
||||||
|
@ -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> {
|
||||||
|
@ -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)>>();
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user