You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

159 lines
5.0 KiB

import { PanelOptions, Threshold, Icon, IconPosition, Condition } from 'types';
import { formatValue, getLastMetricValue } from '../../utils';
import _ from 'lodash';
// Convert Grafana options into Chartwerk Gauge options
export class GaugeOptions {
private minValue: number | undefined;
private maxValue: number | undefined;
private thresholds: Array<{ value: number; color: string }> = [];
private icons: Array<{ src: string; position: string; size: number }> = [];
constructor(private grafanaSeriesList: any[], private grafanaOptions: PanelOptions) {
this._setMin();
this._setMax();
this._setThresholds();
this._setIcons();
}
private _setMin(): void {
if (!this.grafanaOptions.gauge.min) {
throw new Error(`Min Config is not selected: [See options: Extremum -> Min]`);
}
if (!this.grafanaOptions.gauge.min?.useMetric) {
this.minValue = this.grafanaOptions.gauge.min.value;
return;
}
const aggregatedValue = getLastMetricValue(this.grafanaSeriesList, this.grafanaOptions.gauge.min.metricName, 'Min');
this.minValue = aggregatedValue ? aggregatedValue : undefined;
}
private _setMax(): void {
if (!this.grafanaOptions.gauge.max) {
throw new Error(`Max Config is not selected: [See options: Extremum -> Max]`);
}
if (!this.grafanaOptions.gauge.max?.useMetric) {
this.maxValue = this.grafanaOptions.gauge.max.value;
return;
}
const aggregatedValue = getLastMetricValue(this.grafanaSeriesList, this.grafanaOptions.gauge.max.metricName, 'Max');
this.maxValue = aggregatedValue ? aggregatedValue : undefined;
}
private _setThresholds(): void {
if (_.isEmpty(this.grafanaOptions.gauge.thresholds.thresholds)) {
return;
}
for (let [idx, threshold] of this.grafanaOptions.gauge.thresholds.thresholds.entries()) {
this._setThreshold(threshold, idx);
}
}
private _setThreshold(threshold: Threshold, idx: number): void {
const value = threshold.useMetric
? getLastMetricValue(this.grafanaSeriesList, threshold.metricName, `Threshold ${idx + 1}`)
: threshold.value;
if (value === null || value === undefined) {
// TODO: may be throw an error
return;
}
this.thresholds.push({
value,
color: threshold.color,
});
}
private _setIcons(): void {
if (_.isEmpty(this.grafanaOptions.gauge.icons)) {
return;
}
for (let [idx, icon] of this.grafanaOptions.gauge.icons.entries()) {
this._setIcon(icon, idx);
}
}
private _setIcon(icon: Icon, idx: number): void {
if (!this._areIconConditionsFulfilled(icon, idx)) {
return;
}
this.icons.push({
src: icon.url,
size: icon.size,
position: this._getChartwerkIconPosition(icon.position),
});
}
private _areIconConditionsFulfilled(icon: Icon, iconIdx: number): boolean {
if (_.isEmpty(icon.metrics)) {
return true;
}
// check each condition and return false if something goes wrong
for (let [conditionIdx, metric] of icon.metrics.entries()) {
const value = getLastMetricValue(
this.grafanaSeriesList,
metric,
`Icon ${iconIdx + 1}, Condition ${conditionIdx + 1}`
);
if (value === null || value === undefined) {
// TODO: may be throw an error
return false;
}
if (!this._checkIconCondition(value, icon.values[conditionIdx], icon.conditions[conditionIdx])) {
return false;
}
}
return true;
}
private _checkIconCondition(metricValue: number, inputValue: number, condition: Condition): boolean {
if (inputValue === undefined || inputValue === null) {
return true;
}
switch (condition) {
case Condition.EQUAL:
return metricValue === inputValue;
case Condition.GREATER:
return metricValue > inputValue;
case Condition.GREATER_OR_EQUAL:
return metricValue >= inputValue;
case Condition.LESS:
return metricValue < inputValue;
case Condition.LESS_OR_EQUAL:
return metricValue <= inputValue;
default:
throw new Error(`Unknown condition: ${condition}`);
}
}
private _getChartwerkIconPosition(position: IconPosition): string {
// TODO: use chartwerk types
switch (position) {
case IconPosition.MIDDLE:
return 'middle';
case IconPosition.UPPER_LEFT:
return 'left';
case IconPosition.UPPER_RIGHT:
return 'right';
default:
throw new Error(`Unknown Icon Position ${position}`);
}
}
getChartwerkOptions(): any {
return {
maxValue: this.maxValue,
minValue: this.minValue,
valueFormatter: (val: number) => formatValue(val, this.grafanaOptions.gauge),
defaultColor: this.grafanaOptions.gauge.thresholds.defaultColor,
valueArcBackgroundColor: this.grafanaOptions.gauge.thresholds.arcBackground,
reversed: this.grafanaOptions.gauge.reversed,
stops: this.thresholds,
valueFontSize: this.grafanaOptions.gauge.valueSize,
icons: this.icons,
};
}
}