prometheus/web/ui/react-app/src/pages/graph/GraphHelpers.ts

296 lines
9.4 KiB
TypeScript
Raw Normal View History

import $ from 'jquery';
import { escapeHTML } from '../../utils';
import { Metric } from '../../types/types';
React UI: Add Exemplar Support to Graph (#8832) * Added exemplar support Signed-off-by: Levi Harrison <git@leviharrison.dev> * Modified tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint suggestions Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed undefined data property error Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added series label section to tooltip Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed spacing Signed-off-by: GitHub <noreply@github.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * Changed exemplar symbol Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Hide selected exemplar info when 'Show Exemplars' is unchecked Signed-off-by: Levi Harrison <git@leviharrison.dev> * Include series labels in exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * De-densify exemplars Signed-off-by: Levi Harrison <git@leviharrison.dev> * Moved showExemplars to per-panel control Signed-off-by: Levi Harrison <git@leviharrison.dev> * Eslint fixes Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix state bug Signed-off-by: Levi Harrison <git@leviharrison.dev> * Removed unused object Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint Signed-off-by: Levi Harrison <git@leviharrison.dev> * Encoded 'show_exemplars' in url Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com>
2021-06-12 09:02:40 -07:00
import { GraphProps, GraphData, GraphSeries, GraphExemplar } from './Graph';
import moment from 'moment-timezone';
export const formatValue = (y: number | null): string => {
if (y === null) {
return 'null';
}
const absY = Math.abs(y);
if (absY >= 1e24) {
return (y / 1e24).toFixed(2) + 'Y';
} else if (absY >= 1e21) {
return (y / 1e21).toFixed(2) + 'Z';
} else if (absY >= 1e18) {
return (y / 1e18).toFixed(2) + 'E';
} else if (absY >= 1e15) {
return (y / 1e15).toFixed(2) + 'P';
} else if (absY >= 1e12) {
return (y / 1e12).toFixed(2) + 'T';
} else if (absY >= 1e9) {
return (y / 1e9).toFixed(2) + 'G';
} else if (absY >= 1e6) {
return (y / 1e6).toFixed(2) + 'M';
} else if (absY >= 1e3) {
return (y / 1e3).toFixed(2) + 'k';
} else if (absY >= 1) {
return y.toFixed(2);
} else if (absY === 0) {
return y.toFixed(2);
} else if (absY < 1e-23) {
return (y / 1e-24).toFixed(2) + 'y';
} else if (absY < 1e-20) {
return (y / 1e-21).toFixed(2) + 'z';
} else if (absY < 1e-17) {
return (y / 1e-18).toFixed(2) + 'a';
} else if (absY < 1e-14) {
return (y / 1e-15).toFixed(2) + 'f';
} else if (absY < 1e-11) {
return (y / 1e-12).toFixed(2) + 'p';
} else if (absY < 1e-8) {
return (y / 1e-9).toFixed(2) + 'n';
} else if (absY < 1e-5) {
return (y / 1e-6).toFixed(2) + 'µ';
} else if (absY < 1e-2) {
return (y / 1e-3).toFixed(2) + 'm';
} else if (absY <= 1) {
return y.toFixed(2);
}
throw Error("couldn't format a value, this is a bug");
};
export const getHoverColor = (color: string, opacity: number, stacked: boolean) => {
const { r, g, b } = $.color.parse(color);
if (!stacked) {
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
}
/*
Spelling (#6517) * spelling: alertmanager Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: attributes Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: autocomplete Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: bootstrap Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: caught Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: chunkenc Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: compaction Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: corrupted Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: deletable Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: expected Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: fine-grained Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: initialized Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: iteration Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: javascript Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: multiple Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: number Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: overlapping Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: possible Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: postings Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: procedure Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: programmatic Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: queuing Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: querier Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: repairing Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: received Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: reproducible Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: retention Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: sample Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: segements Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: semantic Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: software [LICENSE] Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: staging Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: timestamp Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: unfortunately Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: uvarint Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: subsequently Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: ressamples Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2020-01-02 06:54:09 -08:00
Unfortunately flot doesn't take into consideration
the alpha value when adjusting the color on the stacked series.
TODO: find better way to set the opacity.
*/
const base = (1 - opacity) * 255;
return `rgb(${Math.round(base + opacity * r)},${Math.round(base + opacity * g)},${Math.round(base + opacity * b)})`;
};
export const toHoverColor = (index: number, stacked: boolean) => (series: GraphSeries, i: number) => ({
...series,
color: getHoverColor(series.color, i !== index ? 0.3 : 1, stacked),
});
export const getOptions = (stacked: boolean, useLocalTime: boolean): jquery.flot.plotOptions => {
return {
grid: {
hoverable: true,
clickable: true,
autoHighlight: true,
mouseActiveRadius: 100,
},
legend: {
show: false,
},
xaxis: {
mode: 'time',
showTicks: true,
showMinorTicks: true,
timeBase: 'milliseconds',
timezone: useLocalTime ? 'browser' : undefined,
},
yaxis: {
tickFormatter: formatValue,
},
crosshair: {
mode: 'xy',
color: '#bbb',
},
tooltip: {
show: true,
cssClass: 'graph-tooltip',
content: (_, xval, yval, { series }): string => {
React UI: Add Exemplar Support to Graph (#8832) * Added exemplar support Signed-off-by: Levi Harrison <git@leviharrison.dev> * Modified tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint suggestions Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed undefined data property error Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added series label section to tooltip Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed spacing Signed-off-by: GitHub <noreply@github.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * Changed exemplar symbol Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Hide selected exemplar info when 'Show Exemplars' is unchecked Signed-off-by: Levi Harrison <git@leviharrison.dev> * Include series labels in exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * De-densify exemplars Signed-off-by: Levi Harrison <git@leviharrison.dev> * Moved showExemplars to per-panel control Signed-off-by: Levi Harrison <git@leviharrison.dev> * Eslint fixes Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix state bug Signed-off-by: Levi Harrison <git@leviharrison.dev> * Removed unused object Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint Signed-off-by: Levi Harrison <git@leviharrison.dev> * Encoded 'show_exemplars' in url Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com>
2021-06-12 09:02:40 -07:00
const both = series as GraphExemplar | GraphSeries;
const { labels, color } = both;
let dateTime = moment(xval);
if (!useLocalTime) {
dateTime = dateTime.utc();
}
const formatLabels = (labels: { [key: string]: string }): string => `
<div class="labels">
${Object.keys(labels).length === 0 ? '<div class="mb-1 font-italic">no labels</div>' : ''}
${labels['__name__'] ? `<div class="mb-1"><strong>${labels['__name__']}</strong></div>` : ''}
${Object.keys(labels)
.filter(k => k !== '__name__')
.map(k => `<div class="mb-1"><strong>${k}</strong>: ${escapeHTML(labels[k])}</div>`)
.join('')}
</div>`;
return `
<div class="date">${dateTime.format('YYYY-MM-DD HH:mm:ss Z')}</div>
<div>
<span class="detail-swatch" style="background-color: ${color}"></span>
<span>${labels.__name__ || 'value'}: <strong>${yval}</strong></span>
</div>
<div class="mt-2 mb-1 font-weight-bold">${'seriesLabels' in both ? 'Trace exemplar:' : 'Series:'}</div>
${formatLabels(labels)}
React UI: Add Exemplar Support to Graph (#8832) * Added exemplar support Signed-off-by: Levi Harrison <git@leviharrison.dev> * Modified tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint suggestions Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed undefined data property error Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added series label section to tooltip Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed spacing Signed-off-by: GitHub <noreply@github.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * Changed exemplar symbol Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Hide selected exemplar info when 'Show Exemplars' is unchecked Signed-off-by: Levi Harrison <git@leviharrison.dev> * Include series labels in exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * De-densify exemplars Signed-off-by: Levi Harrison <git@leviharrison.dev> * Moved showExemplars to per-panel control Signed-off-by: Levi Harrison <git@leviharrison.dev> * Eslint fixes Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix state bug Signed-off-by: Levi Harrison <git@leviharrison.dev> * Removed unused object Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint Signed-off-by: Levi Harrison <git@leviharrison.dev> * Encoded 'show_exemplars' in url Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com>
2021-06-12 09:02:40 -07:00
${
'seriesLabels' in both
? `
<div class="mt-2 mb-1 font-weight-bold">Associated series:</div>${formatLabels(both.seriesLabels)}
`
React UI: Add Exemplar Support to Graph (#8832) * Added exemplar support Signed-off-by: Levi Harrison <git@leviharrison.dev> * Modified tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint suggestions Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed undefined data property error Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added series label section to tooltip Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed spacing Signed-off-by: GitHub <noreply@github.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * Changed exemplar symbol Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Hide selected exemplar info when 'Show Exemplars' is unchecked Signed-off-by: Levi Harrison <git@leviharrison.dev> * Include series labels in exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * De-densify exemplars Signed-off-by: Levi Harrison <git@leviharrison.dev> * Moved showExemplars to per-panel control Signed-off-by: Levi Harrison <git@leviharrison.dev> * Eslint fixes Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix state bug Signed-off-by: Levi Harrison <git@leviharrison.dev> * Removed unused object Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint Signed-off-by: Levi Harrison <git@leviharrison.dev> * Encoded 'show_exemplars' in url Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com>
2021-06-12 09:02:40 -07:00
: ''
}
`.trimEnd();
},
defaultTheme: false,
lines: true,
},
series: {
React UI: Add Exemplar Support to Graph (#8832) * Added exemplar support Signed-off-by: Levi Harrison <git@leviharrison.dev> * Modified tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint suggestions Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed undefined data property error Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added series label section to tooltip Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed spacing Signed-off-by: GitHub <noreply@github.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * Changed exemplar symbol Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Hide selected exemplar info when 'Show Exemplars' is unchecked Signed-off-by: Levi Harrison <git@leviharrison.dev> * Include series labels in exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * De-densify exemplars Signed-off-by: Levi Harrison <git@leviharrison.dev> * Moved showExemplars to per-panel control Signed-off-by: Levi Harrison <git@leviharrison.dev> * Eslint fixes Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix state bug Signed-off-by: Levi Harrison <git@leviharrison.dev> * Removed unused object Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint Signed-off-by: Levi Harrison <git@leviharrison.dev> * Encoded 'show_exemplars' in url Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com>
2021-06-12 09:02:40 -07:00
stack: false, // Stacking is set on a per-series basis because exemplar symbols don't support it.
lines: {
lineWidth: stacked ? 1 : 2,
steps: false,
fill: stacked,
},
shadowSize: 0,
},
};
};
// This was adapted from Flot's color generation code.
export const getColors = (data: { resultType: string; result: Array<{ metric: Metric; values: [number, string][] }> }) => {
const colorPool = ['#edc240', '#afd8f8', '#cb4b4b', '#4da74d', '#9440ed'];
const colorPoolSize = colorPool.length;
let variation = 0;
return data.result.map((_, i) => {
// Each time we exhaust the colors in the pool we adjust
// a scaling factor used to produce more variations on
// those colors. The factor alternates negative/positive
// to produce lighter/darker colors.
// Reset the variation after every few cycles, or else
// it will end up producing only white or black colors.
if (i % colorPoolSize === 0 && i) {
if (variation >= 0) {
variation = variation < 0.5 ? -variation - 0.2 : 0;
} else {
variation = -variation;
}
}
return $.color.parse(colorPool[i % colorPoolSize] || '#666').scale('rgb', 1 + variation);
});
};
React UI: Add Exemplar Support to Graph (#8832) * Added exemplar support Signed-off-by: Levi Harrison <git@leviharrison.dev> * Modified tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint suggestions Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed undefined data property error Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added series label section to tooltip Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed spacing Signed-off-by: GitHub <noreply@github.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * Changed exemplar symbol Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Hide selected exemplar info when 'Show Exemplars' is unchecked Signed-off-by: Levi Harrison <git@leviharrison.dev> * Include series labels in exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * De-densify exemplars Signed-off-by: Levi Harrison <git@leviharrison.dev> * Moved showExemplars to per-panel control Signed-off-by: Levi Harrison <git@leviharrison.dev> * Eslint fixes Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix state bug Signed-off-by: Levi Harrison <git@leviharrison.dev> * Removed unused object Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint Signed-off-by: Levi Harrison <git@leviharrison.dev> * Encoded 'show_exemplars' in url Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com>
2021-06-12 09:02:40 -07:00
export const normalizeData = ({ queryParams, data, exemplars, stacked }: GraphProps): GraphData => {
const colors = getColors(data);
const { startTime, endTime, resolution } = queryParams!;
React UI: Add Exemplar Support to Graph (#8832) * Added exemplar support Signed-off-by: Levi Harrison <git@leviharrison.dev> * Modified tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint suggestions Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed undefined data property error Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added series label section to tooltip Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed spacing Signed-off-by: GitHub <noreply@github.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * Changed exemplar symbol Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Hide selected exemplar info when 'Show Exemplars' is unchecked Signed-off-by: Levi Harrison <git@leviharrison.dev> * Include series labels in exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * De-densify exemplars Signed-off-by: Levi Harrison <git@leviharrison.dev> * Moved showExemplars to per-panel control Signed-off-by: Levi Harrison <git@leviharrison.dev> * Eslint fixes Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix state bug Signed-off-by: Levi Harrison <git@leviharrison.dev> * Removed unused object Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint Signed-off-by: Levi Harrison <git@leviharrison.dev> * Encoded 'show_exemplars' in url Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com>
2021-06-12 09:02:40 -07:00
let sum = 0;
const values: number[] = [];
// Exemplars are grouped into buckets by time to use for de-densifying.
const buckets: { [time: number]: GraphExemplar[] } = {};
for (const exemplar of exemplars || []) {
for (const { labels, value, timestamp } of exemplar.exemplars) {
const parsed = parseValue(value) || 0;
sum += parsed;
values.push(parsed);
const bucketTime = Math.floor((timestamp / ((endTime - startTime) / 60)) * 0.8) * 1000;
if (!buckets[bucketTime]) {
buckets[bucketTime] = [];
}
React UI: Add Exemplar Support to Graph (#8832) * Added exemplar support Signed-off-by: Levi Harrison <git@leviharrison.dev> * Modified tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint suggestions Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed undefined data property error Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added series label section to tooltip Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed spacing Signed-off-by: GitHub <noreply@github.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * Changed exemplar symbol Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Hide selected exemplar info when 'Show Exemplars' is unchecked Signed-off-by: Levi Harrison <git@leviharrison.dev> * Include series labels in exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * De-densify exemplars Signed-off-by: Levi Harrison <git@leviharrison.dev> * Moved showExemplars to per-panel control Signed-off-by: Levi Harrison <git@leviharrison.dev> * Eslint fixes Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix state bug Signed-off-by: Levi Harrison <git@leviharrison.dev> * Removed unused object Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint Signed-off-by: Levi Harrison <git@leviharrison.dev> * Encoded 'show_exemplars' in url Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com>
2021-06-12 09:02:40 -07:00
buckets[bucketTime].push({
seriesLabels: exemplar.seriesLabels,
labels: labels,
data: [[timestamp * 1000, parsed]],
points: { symbol: exemplarSymbol },
color: '#0275d8',
});
}
React UI: Add Exemplar Support to Graph (#8832) * Added exemplar support Signed-off-by: Levi Harrison <git@leviharrison.dev> * Modified tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint suggestions Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed undefined data property error Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added series label section to tooltip Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed spacing Signed-off-by: GitHub <noreply@github.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * Changed exemplar symbol Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Hide selected exemplar info when 'Show Exemplars' is unchecked Signed-off-by: Levi Harrison <git@leviharrison.dev> * Include series labels in exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * De-densify exemplars Signed-off-by: Levi Harrison <git@leviharrison.dev> * Moved showExemplars to per-panel control Signed-off-by: Levi Harrison <git@leviharrison.dev> * Eslint fixes Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix state bug Signed-off-by: Levi Harrison <git@leviharrison.dev> * Removed unused object Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint Signed-off-by: Levi Harrison <git@leviharrison.dev> * Encoded 'show_exemplars' in url Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com>
2021-06-12 09:02:40 -07:00
}
const deviation = stdDeviation(sum, values);
React UI: Add Exemplar Support to Graph (#8832) * Added exemplar support Signed-off-by: Levi Harrison <git@leviharrison.dev> * Modified tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint suggestions Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed undefined data property error Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added series label section to tooltip Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed spacing Signed-off-by: GitHub <noreply@github.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * Changed exemplar symbol Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Hide selected exemplar info when 'Show Exemplars' is unchecked Signed-off-by: Levi Harrison <git@leviharrison.dev> * Include series labels in exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * De-densify exemplars Signed-off-by: Levi Harrison <git@leviharrison.dev> * Moved showExemplars to per-panel control Signed-off-by: Levi Harrison <git@leviharrison.dev> * Eslint fixes Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix state bug Signed-off-by: Levi Harrison <git@leviharrison.dev> * Removed unused object Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint Signed-off-by: Levi Harrison <git@leviharrison.dev> * Encoded 'show_exemplars' in url Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com>
2021-06-12 09:02:40 -07:00
return {
series: data.result.map(({ values, metric }, index) => {
// Insert nulls for all missing steps.
const data = [];
let pos = 0;
for (let t = startTime; t <= endTime; t += resolution) {
// Allow for floating point inaccuracy.
const currentValue = values[pos];
if (values.length > pos && currentValue[0] < t + resolution / 100) {
data.push([currentValue[0] * 1000, parseValue(currentValue[1])]);
pos++;
} else {
data.push([t * 1000, null]);
}
}
return {
labels: metric !== null ? metric : {},
color: colors[index].toString(),
stack: stacked,
data,
index,
};
}),
exemplars: Object.values(buckets).flatMap(bucket => {
if (bucket.length === 1) {
return bucket[0];
}
return bucket
.sort((a, b) => exValue(b) - exValue(a)) // Sort exemplars by value in descending order.
.reduce((exemplars: GraphExemplar[], exemplar) => {
if (exemplars.length === 0) {
exemplars.push(exemplar);
} else {
const prev = exemplars[exemplars.length - 1];
// Don't plot this exemplar if it's less than two times the standard
// deviation spaced from the last.
if (exValue(prev) - exValue(exemplar) >= 2 * deviation) {
exemplars.push(exemplar);
}
}
return exemplars;
}, []);
}),
};
};
export const parseValue = (value: string) => {
const val = parseFloat(value);
// "+Inf", "-Inf", "+Inf" will be parsed into NaN by parseFloat(). They
// can't be graphed, so show them as gaps (null).
return isNaN(val) ? null : val;
};
React UI: Add Exemplar Support to Graph (#8832) * Added exemplar support Signed-off-by: Levi Harrison <git@leviharrison.dev> * Modified tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint suggestions Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed undefined data property error Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added series label section to tooltip Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed spacing Signed-off-by: GitHub <noreply@github.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Added exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * Changed exemplar symbol Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com> Signed-off-by: Levi Harrison <git@leviharrison.dev> * Hide selected exemplar info when 'Show Exemplars' is unchecked Signed-off-by: Levi Harrison <git@leviharrison.dev> * Include series labels in exemplar info Signed-off-by: Levi Harrison <git@leviharrison.dev> * De-densify exemplars Signed-off-by: Levi Harrison <git@leviharrison.dev> * Moved showExemplars to per-panel control Signed-off-by: Levi Harrison <git@leviharrison.dev> * Eslint fixes Signed-off-by: Levi Harrison <git@leviharrison.dev> * Address review comments Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fixed tests Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix state bug Signed-off-by: Levi Harrison <git@leviharrison.dev> * Removed unused object Signed-off-by: Levi Harrison <git@leviharrison.dev> * Fix eslint Signed-off-by: Levi Harrison <git@leviharrison.dev> * Encoded 'show_exemplars' in url Signed-off-by: Levi Harrison <git@leviharrison.dev> Co-authored-by: Julius Volz <julius.volz@gmail.com>
2021-06-12 09:02:40 -07:00
const exemplarSymbol = (ctx: CanvasRenderingContext2D, x: number, y: number) => {
// Center the symbol on the point.
y = y - 3.5;
// Correct if the symbol is overflowing off the grid.
if (x > ctx.canvas.clientWidth - 59) {
x = ctx.canvas.clientWidth - 59;
}
if (y > ctx.canvas.clientHeight - 40) {
y = ctx.canvas.clientHeight - 40;
}
ctx.translate(x, y);
ctx.rotate(Math.PI / 4);
ctx.translate(-x, -y);
ctx.fillStyle = '#92bce1';
ctx.fillRect(x, y, 7, 7);
ctx.strokeStyle = '#0275d8';
ctx.lineWidth = 1;
ctx.strokeRect(x, y, 7, 7);
};
const stdDeviation = (sum: number, values: number[]): number => {
const avg = sum / values.length;
let squaredAvg = 0;
values.map(value => (squaredAvg += (value - avg) ** 2));
squaredAvg = squaredAvg / values.length;
return Math.sqrt(squaredAvg);
};
const exValue = (exemplar: GraphExemplar): number => exemplar.data[0][1];