mirror of
https://github.com/zaphar/Heracles.git
synced 2025-07-25 21:39:52 -04:00
Compare commits
4 Commits
00e84bd99a
...
02314a3309
Author | SHA1 | Date | |
---|---|---|---|
02314a3309 | |||
2f6b9b6c58 | |||
75264dc095 | |||
a356eba786 |
82
static/lib.d.js
Normal file
82
static/lib.d.js
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
// Copyright 2023 Jeremy Wall
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef PlotList
|
||||||
|
* @type {object}
|
||||||
|
* @property {Array=} Series
|
||||||
|
* @property {Array=} Scalar
|
||||||
|
* @property {Array=} StreamInstant - Timestamps are in seconds
|
||||||
|
* @property {Array=} Stream - Timestamps are in nanoseconds
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef QueryData
|
||||||
|
* @type {object}
|
||||||
|
* @property {object} yaxes
|
||||||
|
* @property {?string} legend_orientation
|
||||||
|
* @property {Array<PlotList>} plots
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef HeaderOrCell
|
||||||
|
* @type {object}
|
||||||
|
* @property {array} values
|
||||||
|
* @property {{color: string}=} fill
|
||||||
|
* @property {object=} font
|
||||||
|
* @property {string=} font.family
|
||||||
|
* @property {number=} font.size
|
||||||
|
* @property {string=} font.color
|
||||||
|
* @property {{width: number, color: string}=} line
|
||||||
|
* @property {Array<number>=} columnwidth
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef TableTrace
|
||||||
|
* @type {object}
|
||||||
|
* @property {string=} name
|
||||||
|
* @property {string} type
|
||||||
|
* @property {string=} mode
|
||||||
|
* @property {HeaderOrCell} header
|
||||||
|
* @property {HeaderOrCell} cells - An Array of columns for the table.
|
||||||
|
* @property {string=} xaxis
|
||||||
|
* @property {string=} yaxis
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef GraphTrace
|
||||||
|
* @type {object}
|
||||||
|
* @property {string=} name
|
||||||
|
* @property {string=} fill
|
||||||
|
* @property type {string}
|
||||||
|
* @property {string=} mode
|
||||||
|
* @property {Array} x
|
||||||
|
* @property {Array} y
|
||||||
|
* @property {string=} xaxis
|
||||||
|
* @property {string=} yaxis
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef PlotTrace
|
||||||
|
* @type {(TableTrace|GraphTrace)}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef PlotMeta
|
||||||
|
* @type {object}
|
||||||
|
* @property {string=} name_format
|
||||||
|
* @property {string=} yaxis
|
||||||
|
* @property {("tonexty"|"tozeroy"|"tonextx"|"tozerox"|"toself"|"tonext")=} fill
|
||||||
|
*/
|
||||||
|
|
244
static/lib.js
244
static/lib.js
@ -12,66 +12,6 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef PlotList
|
|
||||||
* @type {object}
|
|
||||||
* @property {Array=} Series
|
|
||||||
* @property {Array=} Scalar
|
|
||||||
* @property {Array<{timestamp: string, line: string}>=} StreamInstant - Timestamps are in seconds
|
|
||||||
* @property {Array<{timestamp: string, line: string}>=} Stream - Timestamps are in nanoseconds
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef QueryData
|
|
||||||
* @type {object}
|
|
||||||
* @property {object} yaxes
|
|
||||||
* @property {?string} legend_orientation
|
|
||||||
* @property {Array<PlotList>} plots
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef HeaderOrCell
|
|
||||||
* @type {object}
|
|
||||||
* @property {array} values
|
|
||||||
* @property {{color: string}=} fill
|
|
||||||
* @property {object=} font
|
|
||||||
* @property {string=} font.family
|
|
||||||
* @property {number=} font.size
|
|
||||||
* @property {string=} font.color
|
|
||||||
* @property {{width: number, color: string}=} line
|
|
||||||
* @property {Array<number>=} columnwidth
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef TableTrace
|
|
||||||
* @type {object}
|
|
||||||
* @property {string=} name
|
|
||||||
* @property {string} type
|
|
||||||
* @property {string=} mode
|
|
||||||
* @property {HeaderOrCell} header
|
|
||||||
* @property {HeaderOrCell} cells - An Array of columns for the table.
|
|
||||||
* @property {string=} xaxis
|
|
||||||
* @property {string=} yaxis
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef GraphTrace
|
|
||||||
* @type {object}
|
|
||||||
* @property {string=} name
|
|
||||||
* @property {string=} fill
|
|
||||||
* @property type {string}
|
|
||||||
* @property {string=} mode
|
|
||||||
* @property {Array} x
|
|
||||||
* @property {Array} y
|
|
||||||
* @property {string=} xaxis
|
|
||||||
* @property {string=} yaxis
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef PlotTrace
|
|
||||||
* @type {(TableTrace|GraphTrace)}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map ansi terminal codes to html color codes.
|
* Map ansi terminal codes to html color codes.
|
||||||
* @param {string} line
|
* @param {string} line
|
||||||
@ -293,7 +233,7 @@ export class GraphPlot extends HTMLElement {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats the name for the plot trace.
|
* Formats the name for the plot trace.
|
||||||
* @param {{name_format: ?string}} meta
|
* @param {PlotMeta} meta
|
||||||
* @param {Map<string, string>} labels
|
* @param {Map<string, string>} labels
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -337,8 +277,9 @@ export class GraphPlot extends HTMLElement {
|
|||||||
const element = document.createElement("div");
|
const element = document.createElement("div");
|
||||||
const select = document.createElement("select");
|
const select = document.createElement("select");
|
||||||
select.setAttribute("name", id);
|
select.setAttribute("name", id);
|
||||||
// TODO(jwall): This is how you set boolean attributes. Use the attribute named... :-(
|
// TODO(jwall): This is how you set boolean attributes. Use the attribute name... :-(
|
||||||
select.setAttribute("multiple", "multiple");
|
select.setAttribute("multiple", "multiple");
|
||||||
|
select.setAttribute("size", "3");
|
||||||
const optElement = document.createElement("option");
|
const optElement = document.createElement("option");
|
||||||
const optValue = "Select All: " + key;
|
const optValue = "Select All: " + key;
|
||||||
optElement.innerText = optValue;
|
optElement.innerText = optValue;
|
||||||
@ -440,6 +381,100 @@ export class GraphPlot extends HTMLElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {any} triple
|
||||||
|
*/
|
||||||
|
buildSeriesPlot(triple) {
|
||||||
|
const labels = /** @type {Map<String, String>} */(triple[0]);
|
||||||
|
for (var label in labels) {
|
||||||
|
var show = this.#filteredLabelSets[label];
|
||||||
|
if (show && !show.includes(labels[label])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const meta = /** @type {PlotMeta} */(triple[1]);
|
||||||
|
var yaxis = meta.yaxis || "y";
|
||||||
|
// https://plotly.com/javascript/reference/layout/yaxis/
|
||||||
|
const series = triple[2];
|
||||||
|
const trace = /** @type GraphTrace */({
|
||||||
|
type: "scatter",
|
||||||
|
mode: "lines+text",
|
||||||
|
x: [],
|
||||||
|
y: [],
|
||||||
|
// We always share the x axis for timeseries graphs.
|
||||||
|
xaxis: "x",
|
||||||
|
yaxis: yaxis,
|
||||||
|
//yhoverformat: yaxis.tickformat,
|
||||||
|
});
|
||||||
|
if (meta.fill) {
|
||||||
|
trace.fill = meta.fill;
|
||||||
|
}
|
||||||
|
var name = this.formatName(meta, labels);
|
||||||
|
if (name) { trace.name = name; }
|
||||||
|
for (const point of series) {
|
||||||
|
trace.x.push(new Date(point.timestamp * 1000));
|
||||||
|
trace.y.push(point.value);
|
||||||
|
}
|
||||||
|
return trace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {any} triple
|
||||||
|
*/
|
||||||
|
buildScalarPlot(triple) {
|
||||||
|
const labels = /** @type {Map<String,String>} */(triple[0]);
|
||||||
|
for (var label in labels) {
|
||||||
|
var show = this.#filteredLabelSets[label];
|
||||||
|
if (show && !show.includes(labels[label])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const meta = /** @type {PlotMeta} */(triple[1]);
|
||||||
|
const series = triple[2];
|
||||||
|
const trace = /** @type GraphTrace */({
|
||||||
|
type: "bar",
|
||||||
|
x: [],
|
||||||
|
y: [],
|
||||||
|
yhoverformat: meta["d3_tick_format"],
|
||||||
|
});
|
||||||
|
var name = this.formatName(meta, labels);
|
||||||
|
if (name) { trace.name = name; }
|
||||||
|
trace.y.push(series.value);
|
||||||
|
trace.x.push(trace.name);
|
||||||
|
return trace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array} stream
|
||||||
|
*/
|
||||||
|
buildStreamPlot(stream) {
|
||||||
|
const dateColumn = [];
|
||||||
|
const metaColumn = [];
|
||||||
|
const logColumn = [];
|
||||||
|
|
||||||
|
loopStream: for (const pair of stream) {
|
||||||
|
const labels = pair[0];
|
||||||
|
var labelList = [];
|
||||||
|
for (var label in labels) {
|
||||||
|
var show = this.#filteredLabelSets[label];
|
||||||
|
if (show && !show.includes(labels[label])) {
|
||||||
|
continue loopStream;
|
||||||
|
}
|
||||||
|
labelList.push(`${label}:${labels[label]}`);
|
||||||
|
}
|
||||||
|
const labelsName = labelList.join("<br>");
|
||||||
|
const lines = pair[1];
|
||||||
|
for (const line of lines) {
|
||||||
|
// For streams the timestamps are in nanoseconds
|
||||||
|
let timestamp = new Date(line.timestamp / 1000000);
|
||||||
|
dateColumn.push(timestamp.toISOString());
|
||||||
|
metaColumn.push(labelsName);
|
||||||
|
logColumn.push(ansiToHtml(line.line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [dateColumn, metaColumn, logColumn];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the graph with new data.
|
* Update the graph with new data.
|
||||||
*
|
*
|
||||||
@ -482,62 +517,19 @@ export class GraphPlot extends HTMLElement {
|
|||||||
var nextYaxis = this.yaxisNameGenerator();
|
var nextYaxis = this.yaxisNameGenerator();
|
||||||
if (subplot.Series) {
|
if (subplot.Series) {
|
||||||
// https://plotly.com/javascript/reference/scatter/
|
// https://plotly.com/javascript/reference/scatter/
|
||||||
loopSeries: for (const triple of subplot.Series) {
|
for (const triple of subplot.Series) {
|
||||||
const labels = triple[0];
|
const trace = this.buildSeriesPlot(triple);
|
||||||
for (var label in labels) {
|
if (trace) {
|
||||||
var show = this.#filteredLabelSets[label];
|
traces.push(trace);
|
||||||
if (show && !show.includes(labels[label])) {
|
|
||||||
continue loopSeries;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const meta = triple[1];
|
|
||||||
var yaxis = meta.yaxis || "y";
|
|
||||||
// https://plotly.com/javascript/reference/layout/yaxis/
|
|
||||||
const series = triple[2];
|
|
||||||
const trace = /** @type GraphTrace */({
|
|
||||||
type: "scatter",
|
|
||||||
mode: "lines+text",
|
|
||||||
x: [],
|
|
||||||
y: [],
|
|
||||||
// We always share the x axis for timeseries graphs.
|
|
||||||
xaxis: "x",
|
|
||||||
yaxis: yaxis,
|
|
||||||
//yhoverformat: yaxis.tickformat,
|
|
||||||
});
|
|
||||||
if (meta.fill) {
|
|
||||||
trace.fill = meta.fill;
|
|
||||||
}
|
|
||||||
var name = this.formatName(meta, labels);
|
|
||||||
if (name) { trace.name = name; }
|
|
||||||
for (const point of series) {
|
|
||||||
trace.x.push(new Date(point.timestamp * 1000));
|
|
||||||
trace.y.push(point.value);
|
|
||||||
}
|
|
||||||
traces.push(trace);
|
|
||||||
}
|
}
|
||||||
} else if (subplot.Scalar) {
|
} else if (subplot.Scalar) {
|
||||||
// https://plotly.com/javascript/reference/bar/
|
// https://plotly.com/javascript/reference/bar/
|
||||||
loopScalar: for (const triple of subplot.Scalar) {
|
for (const triple of subplot.Scalar) {
|
||||||
const labels = triple[0];
|
const trace = this.buildScalarPlot(triple);
|
||||||
for (var label in labels) {
|
if (trace) {
|
||||||
var show = this.#filteredLabelSets[label];
|
traces.push(trace);
|
||||||
if (show && !show.includes(labels[label])) {
|
|
||||||
continue loopScalar;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const meta = triple[1];
|
|
||||||
const series = triple[2];
|
|
||||||
const trace = /** @type GraphTrace */({
|
|
||||||
type: "bar",
|
|
||||||
x: [],
|
|
||||||
y: [],
|
|
||||||
yhoverformat: meta["d3_tick_format"],
|
|
||||||
});
|
|
||||||
var name = this.formatName(meta, labels);
|
|
||||||
if (name) { trace.name = name; }
|
|
||||||
trace.y.push(series.value);
|
|
||||||
trace.x.push(trace.name);
|
|
||||||
traces.push(trace);
|
|
||||||
}
|
}
|
||||||
} else if (subplot.Stream) {
|
} else if (subplot.Stream) {
|
||||||
// TODO(jwall): It would be nice if scroll behavior would handle replots better.
|
// TODO(jwall): It would be nice if scroll behavior would handle replots better.
|
||||||
@ -558,31 +550,7 @@ export class GraphPlot extends HTMLElement {
|
|||||||
fill: { color: layout.plot_bgcolor }
|
fill: { color: layout.plot_bgcolor }
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dateColumn = [];
|
const [dateColumn, metaColumn, logColumn] = this.buildStreamPlot(subplot.Stream);
|
||||||
const metaColumn = [];
|
|
||||||
const logColumn = [];
|
|
||||||
|
|
||||||
loopStream: for (const pair of subplot.Stream) {
|
|
||||||
const labels = pair[0];
|
|
||||||
var labelList = [];
|
|
||||||
for (var label in labels) {
|
|
||||||
var show = this.#filteredLabelSets[label];
|
|
||||||
if (show && !show.includes(labels[label])) {
|
|
||||||
continue loopStream;
|
|
||||||
}
|
|
||||||
labelList.push(`${label}:${labels[label]}`);
|
|
||||||
}
|
|
||||||
const labelsName = labelList.join("<br>");
|
|
||||||
const lines = pair[1];
|
|
||||||
// TODO(jwall): Headers
|
|
||||||
for (const line of lines) {
|
|
||||||
// For streams the timestamps are in nanoseconds
|
|
||||||
let timestamp = new Date(line.timestamp / 1000000);
|
|
||||||
dateColumn.push(timestamp.toISOString());
|
|
||||||
metaColumn.push(labelsName);
|
|
||||||
logColumn.push(ansiToHtml(line.line));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
trace.cells.values.push(dateColumn);
|
trace.cells.values.push(dateColumn);
|
||||||
trace.cells.values.push(metaColumn);
|
trace.cells.values.push(metaColumn);
|
||||||
trace.cells.values.push(logColumn);
|
trace.cells.values.push(logColumn);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user