Skip to content

Commit

Permalink
Merge pull request #44 from andymchugh/datatype
Browse files Browse the repository at this point in the history
add support for string data
  • Loading branch information
andymchugh authored May 14, 2024
2 parents e18d5b6 + 0c16442 commit b4a0dcd
Show file tree
Hide file tree
Showing 9 changed files with 331 additions and 16 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ Adds support for grafana variables in the SVG URL. Before this was only availabl
URLs. It also corrects the variable change detection logic for all url variables to ensure we
get a fresh fetch when relevant variables change.

String Data
-----------
This adds support for string timeseries for label drives. Color can still be driven by having
number timeseries for colors and string timeseries for the label text. This is also compatible
with value mappings.

## 1.11.0
Flow Animations
---------------
Expand Down
84 changes: 84 additions & 0 deletions provisioning/dashboardData/stringData.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---

#------------------------------------------------------------------------------
# YAML Aliases to simplify maintenance

anchorLinks:
- link: &grafana-home
url: "https://grafana.com/"
params: "time"

#------------------------------------------------------------------------------
# Panel Config

test:
testDataExtendedZero: true
testDataStringData: true

cellIdPreamble: "cell-"
gradientMode: "hue"
tagConfig:
condensed: false
cells:
drawio:
link:
url: "https://app.diagrams.net/?p=svgdata"
docs:
link:
url: "https://github.com/andymchugh/andrewbmchugh-flow-panel/blob/main/src/README.md"
inbox_depth:
tags: ['depth']
dataRef: "test-data-large-sin"
label:
dataRef: "test-data-string"
valueMappings:
- {value: "*0*", text: "*mapped to 0*"}
- {value: "*29*", text: "*mapped to 29*"}
- {valueMin: 300, valueMax: 600, text: "will never get here as data not a number"}
separator: "cr"
units: "none"
labelColor:
gradientMode: "hue"
thresholds:
- {color: "green", level: 0}
- {color: "orange", level: 500}
- {color: "red", level: 1000}
link: *grafana-home
db_transactions:
dataRef: "test-data-large-cos"
label:
separator: "cr"
units: "ops"
fillColor:
thresholds:
- {color: "semi-dark-green", level: 0}
- {color: "orange", level: 400}
- {color: "red", level: 800}
link: *grafana-home
inbox_transactions:
tags: ['db']
dataRef: "test-data-large-cos"
inbox_workers:
tags: ['worker']
dataRef: "test-data-small-sin"
workers_reads:
dataRef: "test-data-small-sin"
start_rate:
dataRef: "test-data-small-sin"
label:
separator: "colon"
units: "pps"
labelColor:
thresholds:
- {color: "green", level: 0}
- {color: "orange", level: 100}
link: *grafana-home
active_workers:
dataRef: "test-data-string"
label:
separator: "cr"
units: "none"
labelColor:
thresholds:
- {color: "#888888", level: 0}
- {color: "light-blue", level: 100}
85 changes: 85 additions & 0 deletions provisioning/dashboardData/stringDataSparse.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---

#------------------------------------------------------------------------------
# YAML Aliases to simplify maintenance

anchorLinks:
- link: &grafana-home
url: "https://grafana.com/"
params: "time"

#------------------------------------------------------------------------------
# Panel Config

test:
testDataExtendedZero: true
testDataStringData: true
testDataSparse: true

cellIdPreamble: "cell-"
gradientMode: "hue"
tagConfig:
condensed: false
cells:
drawio:
link:
url: "https://app.diagrams.net/?p=svgdata"
docs:
link:
url: "https://github.com/andymchugh/andrewbmchugh-flow-panel/blob/main/src/README.md"
inbox_depth:
tags: ['depth']
dataRef: "test-data-large-sin"
label:
dataRef: "test-data-string"
valueMappings:
- {value: "*0*", text: "*mapped to 0*"}
- {value: "*29*", text: "*mapped to 29*"}
- {valueMin: 300, valueMax: 600, text: "will never get here as data not a number"}
separator: "cr"
units: "none"
labelColor:
gradientMode: "hue"
thresholds:
- {color: "green", level: 0}
- {color: "orange", level: 500}
- {color: "red", level: 1000}
link: *grafana-home
db_transactions:
dataRef: "test-data-large-cos"
label:
separator: "cr"
units: "ops"
fillColor:
thresholds:
- {color: "semi-dark-green", level: 0}
- {color: "orange", level: 400}
- {color: "red", level: 800}
link: *grafana-home
inbox_transactions:
tags: ['db']
dataRef: "test-data-large-cos"
inbox_workers:
tags: ['worker']
dataRef: "test-data-small-sin"
workers_reads:
dataRef: "test-data-small-sin"
start_rate:
dataRef: "test-data-small-sin"
label:
separator: "colon"
units: "pps"
labelColor:
thresholds:
- {color: "green", level: 0}
- {color: "orange", level: 100}
link: *grafana-home
active_workers:
dataRef: "test-data-string"
label:
separator: "cr"
units: "none"
labelColor:
thresholds:
- {color: "#888888", level: 0}
- {color: "light-blue", level: 100}
130 changes: 130 additions & 0 deletions provisioning/dashboards/stringData.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/components/Config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ export type TestConfig = {
testDataSparse: boolean | undefined;
testDataBaseOffset: number | undefined;
testDataExtendedZero: boolean | undefined;
testDataStringData: boolean | undefined;
};

export type FlowValueMapping = {
value: number | null | undefined;
value: string | number | null | undefined;
valueMin: number | undefined;
valueMax: number | undefined;
text: string;
Expand Down
8 changes: 4 additions & 4 deletions src/components/SvgUpdater.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ function getCellValue(datapoint: DatapointMode | undefined, tsName: string, tsDa
return value;
}

export function valueMapping(valueMappings: FlowValueMapping[], value: number | null) {
export function valueMapping(valueMappings: FlowValueMapping[], value: number | string | null) {
for (const mapping of valueMappings) {
if (mapping.valid) {
let match = false;
Expand Down Expand Up @@ -242,7 +242,7 @@ function formatCellValue(cellLabelData: PanelConfigCellLabel, value: number) {
return res;
}

export function getFlowAnimationState(config: PanelConfigCellFlowAnimation, cellValue: number | null) {
export function getFlowAnimationState(config: PanelConfigCellFlowAnimation, cellValue: number | string | null) {
if (typeof cellValue === 'number' && config.dataCoherent) {
const absValue = Math.abs(cellValue);
let durationSecs = 0;
Expand Down Expand Up @@ -294,7 +294,7 @@ export function svgUpdate(svgHolder: SvgHolder, tsData: TimeSeriesData, highligh
// This function sources the dataRef from the inner paramData and scales it using
// the variables to a threshold seed. If it doesn't exist it returns the passed in
// default.
function thresholdSeed(datapoint: DatapointMode | undefined, paramData: PanelConfigCellColor | PanelConfigCellFlowAnimation | undefined, defaultSeed: number | null) {
function thresholdSeed(datapoint: DatapointMode | undefined, paramData: PanelConfigCellColor | PanelConfigCellFlowAnimation | undefined, defaultSeed: number | string | null) {
if (paramData?.dataRef) {
const cellValue = getCellValue(datapoint, paramData.dataRef, tsData);
return variableThresholdScaleValue(variableValues, cellData, cellValue);
Expand All @@ -312,7 +312,7 @@ export function svgUpdate(svgHolder: SvgHolder, tsData: TimeSeriesData, highligh
const cellLabelDatapoint = cellLabelData?.datapoint;
const cellLabelValue = cellLabelData?.dataRef ? getCellValue(cellLabelDatapoint, cellLabelData.dataRef, tsData) : cellValue;
const cellLabelMappedValue = cellLabelData?.valueMappings ? valueMapping(cellLabelData.valueMappings, cellLabelValue) : null;
const cellLabel = cellLabelMappedValue || (cellLabelData && (typeof cellLabelValue === 'number') ? formatCellValue(cellLabelData, cellLabelValue) : null);
const cellLabel = cellLabelMappedValue || (cellLabelData && (typeof cellLabelValue === 'number') ? formatCellValue(cellLabelData, cellLabelValue) : cellLabelValue);

const cellFillColorData = cellData.cellProps.fillColor;
const cellFillColorDatapoint = cellFillColorData?.datapoint;
Expand Down
24 changes: 15 additions & 9 deletions src/components/TimeSeries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type TimeSeries = {
valuesIndex?: number | null;
values: number[];
}
values: Array<number | null>;
values: Array<number | string | null>;
};

export type TimeSeriesData = {
Expand All @@ -21,7 +21,7 @@ export function seriesExtend(tsData: TimeSeriesData, timeMin: number, timeMax: n
const dataSparse = testConfig?.testDataSparse;
const dataExtendedZero = testConfig?.testDataExtendedZero;
const baseOffset = typeof testConfig?.testDataBaseOffset === 'number' ? testConfig.testDataBaseOffset : 1;
const create = function(datapoints: number, scalar: number, fn: (inp: number) => number) {
const create = function(datapoints: number, scalar: number, fn: (inp: number) => number, asString: boolean) {
const intervalTime = Math.ceil((timeMax - timeMin) / datapoints);
const intervalValue = 2 * Math.PI / datapoints;
let timeValues = [];
Expand All @@ -30,24 +30,30 @@ export function seriesExtend(tsData: TimeSeriesData, timeMin: number, timeMax: n
timeValues.push(timeMin + (i * intervalTime));

const dv = scalar * (baseOffset + fn(i * intervalValue));
dataValues.push(dataSparse && ((i % 10) > 5) ? null : dataExtendedZero && Math.abs(dv) < 20 ? 0 : dv);
const val1 = dataSparse && ((i % 10) > 5) ? null : dataExtendedZero && Math.abs(dv) < 20 ? 0 : dv;
const val2 = asString && (typeof val1 === 'number') ? '*' + Math.ceil(val1).toString() + '*' : val1;
dataValues.push(val2);
}
return {
time: {values: timeValues},
values: dataValues,
};
}

const dataSets = [
{name: 'test-data-small-sin', datapoints: 75, scalar: 100, fn: Math.sin},
{name: 'test-data-large-sin', datapoints: 50, scalar: 500, fn: Math.sin},
{name: 'test-data-small-cos', datapoints: 60, scalar: 100, fn: Math.cos},
{name: 'test-data-large-cos', datapoints: 88, scalar: 500, fn: Math.cos},
let dataSets = [
{name: 'test-data-small-sin', datapoints: 75, scalar: 100, fn: Math.sin, asString: false},
{name: 'test-data-large-sin', datapoints: 50, scalar: 500, fn: Math.sin, asString: false},
{name: 'test-data-small-cos', datapoints: 60, scalar: 100, fn: Math.cos, asString: false},
{name: 'test-data-large-cos', datapoints: 88, scalar: 500, fn: Math.cos, asString: false},
];

if (testConfig?.testDataStringData) {
dataSets.push({name: 'test-data-string', datapoints: 65, scalar: 500, fn: Math.cos, asString: true});
}

dataSets.forEach((ds) => {
if (!tsData.ts.get(ds.name)) {
tsData.ts.set(ds.name, create(ds.datapoints, ds.scalar, ds.fn));
tsData.ts.set(ds.name, create(ds.datapoints, ds.scalar, ds.fn, ds.asString));
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/Utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,9 @@ export function variableThresholdScalarsInit(
}
}

export function variableThresholdScaleValue(variableValues: Map<string, string>, cellData: SvgCell, value: number | null) {
export function variableThresholdScaleValue(variableValues: Map<string, string>, cellData: SvgCell, value: number | string | null) {
if (typeof value !== 'number') {
return null;
return value;
}
let scalar = 1.0;
cellData.variableThresholdScalars.forEach((rules, variableName) => {
Expand Down
3 changes: 3 additions & 0 deletions yaml_defs/panelConfig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ test:
# testing in this region.
testDataExtendedZero: false

# Version 1.12.0 onwards: When set test data values are extended with a string-data timeseries.
testDataStringData: false

#------------------------------------------------------------------------------
# Grafana Variable Scalars

Expand Down

0 comments on commit b4a0dcd

Please sign in to comment.