diff --git a/examples/example_dashboards.yaml b/examples/example_dashboards.yaml index 786e754..2794302 100644 --- a/examples/example_dashboards.yaml +++ b/examples/example_dashboards.yaml @@ -3,15 +3,15 @@ graphs: - title: Node cpu source: http://heimdall:9001 - query: 'node_cpu_seconds_total{job="nodestats"}' + query: 'sum by (instance)(irate(node_cpu_seconds_total{mode="system",job="nodestats"}[5m])) * 100' - title: Node memory source: http://heimdall:9001 - query: 'node_memory_MemFree_bytes{instance="andrew:9002",job="nodestats"}' + query: 'node_memory_MemFree_bytes{job="nodestats"}' - title: Test Dasbboard 2 graphs: - title: Node cpu source: http://heimdall:9001 - query: 'node_cpu_seconds_total{job="nodestats"}' + query: 'sum by (instance)(irate(node_cpu_seconds_total{mode="system",job="nodestats"}[5m])) * 100' - title: Node memory source: http://heimdall:9001 - query: 'node_memory_MemFree_bytes{instance="andrew:9002",job="nodestats"}' + query: 'node_memory_MemFree_bytes{,job="nodestats"}' diff --git a/src/routes.rs b/src/routes.rs index 52d05bd..8c68845 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -64,21 +64,10 @@ pub fn mk_api_routes(config: Arc>) -> Router { pub fn graph_component(dash_idx: usize, graph_idx: usize, graph: &Graph) -> Markup { let graph_id = format!("graph-{}-{}", dash_idx, graph_idx); let graph_data_uri = format!("/api/dash/{}/graph/{}", dash_idx, graph_idx); - // initialize the plot with Plotly.react - // Update plot with Plotly.react which is more efficient - let script = format!( - "var graph{graph_idx} = new Timeseries('{uri}', '{graph_id}'); graph{graph_idx}.updateGraph();", - uri = graph_data_uri, - graph_id = graph_id, - graph_idx = graph_idx, - ); html!( div { h2 { (graph.title) } - script { - (script) - } - div id=(graph_id) { } + timeseries-graph uri=(graph_data_uri) id=(graph_id) { } } ) } @@ -134,6 +123,9 @@ pub async fn index(State(config): State) -> Markup { script src="/js/plotly.js" { } script src="/js/htmx.js" { } script src="/js/lib.js" { } + template id="timeseries_template" { + div; + } (app(State(config.clone())).await) } } diff --git a/static/lib.js b/static/lib.js index 3eb1899..ccd9ab6 100644 --- a/static/lib.js +++ b/static/lib.js @@ -1,18 +1,61 @@ - -class Timeseries { +class TimeseriesGraph extends HTMLElement { #uri; - #title; - #targetEl; - //#width; - //#height; - - constructor(uri, targetEl, /** width, height **/) { - this.#uri = uri; - this.#targetEl = targetEl; - //this.#width = width; - //this.#height = height; + #width; + #height; + constructor() { + super(); + const root = this.attachShadow({ mode: "open" }); + var template = document.getElementById("timeseries_template"); + this.#width = 1000; + this.height = 500; + root.appendChild(template.content.cloneNode(true)); } + static observedAttributes = ['uri', 'width', 'height']; + + attributeChanged(name, _oldValue, newValue) { + switch (name) { + case 'uri': + this.#uri = newValue; + break; + case 'width': + this.#width = newValue; + break; + case 'height': + this.#height = newValue; + break; + default: // do nothing; + break; + } + this.updateGraph(); + // TODO(zaphar): reset update timer as well + } + + getTargetNode() { + console.log("shadowroot: ", this.shadowRoot); + return this.shadowRoot.firstChild; + } + + connectedCallback() { + // TODO(zaphar): Set up the timer loop to update graph data. + this.#uri = this.getAttribute('uri'); + if (this.#uri) { + this.updateGraph(); + } + } + + disconnectedCallback() { + // TODO(zaphar): Turn off the timer loop to update graph. + } + + static elementName = "timeseries-graph"; + + static registerElement() { + if (!customElements.get(TimeseriesGraph.elementName)) { + customElements.define(TimeseriesGraph.elementName, TimeseriesGraph); + } + } + async fetchData() { const response = await fetch(this.#uri); const data = await response.json(); @@ -39,9 +82,11 @@ class Timeseries { traces.push(trace); } console.log("Traces: ", traces); - Plotly.react(this.#targetEl, traces, { width: 500, height: 500 }); + Plotly.react(this.getTargetNode(), traces, { width: this.#width, height: this.#height }); } else if (data.Scalar) { // The graph should be a single value } } } + +TimeseriesGraph.registerElement();