generated from gapitio/utility-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* fix: fix return type * feat: add method to get value by multiple filters * chore: update changelog * Update src/utils/getMetricValueWithFilters/getMetricValueWithFilters.ts Co-authored-by: Ole Kristian (Zee) <[email protected]> * Update src/utils/getMetricValueWithFilters/getMetricValueWithFilters.ts Co-authored-by: Ole Kristian (Zee) <[email protected]> * Update CHANGELOG.md Co-authored-by: Ole Kristian (Zee) <[email protected]> * Update src/utils/getMetricValueWithFilters/getMetricValueWithFilters.ts Co-authored-by: Ole Kristian (Zee) <[email protected]> * Update src/utils/getMetricValueWithFilters/getMetricValueWithFilters.ts Co-authored-by: Ole Kristian (Zee) <[email protected]> * refac: add noDataValue & remove excessive type check * feat: add reducerId to getMetricValueWithFilter * fix: change import to correct reducerid --------- Co-authored-by: Ole Kristian (Zee) <[email protected]>
- Loading branch information
Showing
6 changed files
with
359 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
227 changes: 227 additions & 0 deletions
227
src/utils/getMetricValueWithFilters/getMetricValueWithFilters.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
import { FieldType, LoadingState, PanelData, dateTime } from "@grafana/data"; | ||
|
||
import { TIME_FIELD, field } from "../field"; | ||
|
||
import { getMetricValueWithFilters } from "./getMetricValueWithFilters"; | ||
|
||
declare global { | ||
interface Window { | ||
data?: PanelData; | ||
} | ||
} | ||
|
||
window.data = { | ||
state: LoadingState.Done, | ||
series: [ | ||
{ | ||
name: "series-1", | ||
fields: [ | ||
TIME_FIELD, | ||
field({ | ||
name: "Value", | ||
type: FieldType.number, | ||
values: [47, 100], | ||
labels: { label1: "label1" }, | ||
}), | ||
], | ||
length: 1, | ||
}, | ||
{ | ||
name: "series-2", | ||
fields: [ | ||
TIME_FIELD, | ||
field({ | ||
name: "Value", | ||
type: FieldType.number, | ||
values: [200], | ||
labels: { label2: "label2" }, | ||
}), | ||
], | ||
length: 1, | ||
}, | ||
{ | ||
name: "series-3", | ||
fields: [ | ||
TIME_FIELD, | ||
field({ | ||
name: "FieldName", | ||
type: FieldType.number, | ||
values: [300], | ||
labels: { label3: "label3" }, | ||
}), | ||
], | ||
length: 1, | ||
}, | ||
{ | ||
name: "series-3", | ||
fields: [ | ||
TIME_FIELD, | ||
field({ | ||
name: "FieldName", | ||
type: FieldType.number, | ||
values: [400], | ||
labels: { label3: "label3", label4: "first" }, | ||
}), | ||
], | ||
length: 1, | ||
}, | ||
{ | ||
name: "series-3", | ||
fields: [ | ||
TIME_FIELD, | ||
field({ | ||
name: "FieldName", | ||
type: FieldType.number, | ||
values: [500], | ||
labels: { label3: "label3", label4: "second" }, | ||
}), | ||
], | ||
length: 1, | ||
}, | ||
{ | ||
name: "series-12", | ||
fields: [ | ||
TIME_FIELD, | ||
field({ | ||
name: "FieldName", | ||
type: FieldType.number, | ||
values: [100, 200, 300, 400, 500], | ||
labels: { label3: "label3", label4: "second" }, | ||
}), | ||
], | ||
length: 5, | ||
}, | ||
], | ||
timeRange: { | ||
from: dateTime(0), | ||
to: dateTime(0), | ||
raw: { | ||
from: dateTime(0), | ||
to: dateTime(0), | ||
}, | ||
}, | ||
}; | ||
|
||
describe("getMetricValue", () => { | ||
beforeEach(() => { | ||
jest.spyOn(global.Math, "random").mockReturnValue(0.5); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.spyOn(global.Math, "random").mockRestore(); | ||
}); | ||
|
||
it("retrieves random value", () => { | ||
expect( | ||
getMetricValueWithFilters({ seriesName: "series-1", showcase: true }) | ||
).toEqual(500); | ||
expect( | ||
getMetricValueWithFilters({ | ||
seriesName: "series-1", | ||
showcase: true, | ||
range: { min: 0, max: 10 }, | ||
decimals: 2, | ||
}) | ||
).toEqual(5); | ||
}); | ||
|
||
it("retrieves metric value w/o set fieldName & labels", () => { | ||
expect(getMetricValueWithFilters({ seriesName: "series-1" })).toEqual(100); | ||
}); | ||
|
||
it("retrieves metric value w/o set fieldName", () => { | ||
expect( | ||
getMetricValueWithFilters({ | ||
seriesName: "series-1", | ||
labels: { label1: "label1" }, | ||
}) | ||
).toEqual(100); | ||
}); | ||
|
||
it("retrieves metric value with all variables", () => { | ||
expect( | ||
getMetricValueWithFilters({ | ||
seriesName: "series-3", | ||
fieldName: "FieldName", | ||
labels: { label3: "label3" }, | ||
}) | ||
).toEqual(300); | ||
}); | ||
|
||
it("retrieves first object when multiple is available", () => { | ||
expect( | ||
getMetricValueWithFilters({ | ||
seriesName: "series-3", | ||
fieldName: "FieldName", | ||
labels: { label3: "label3" }, | ||
}) | ||
).toEqual(300); | ||
}); | ||
|
||
it("retrieves null when no match is found", () => { | ||
expect( | ||
getMetricValueWithFilters({ | ||
seriesName: "series-4", | ||
fieldName: "FieldName", | ||
labels: { label3: "label3" }, | ||
}) | ||
).toEqual(null); | ||
}); | ||
|
||
it("retrieves null when including existing and nonexisting labels", () => { | ||
expect( | ||
getMetricValueWithFilters({ | ||
seriesName: "series-3", | ||
fieldName: "FieldName", | ||
labels: { label3: "label3", nonExistent: "nonExistent" }, | ||
}) | ||
).toEqual(null); | ||
}); | ||
|
||
it("retrieves 'No data' when including noDataValue = 'No data'", () => { | ||
expect( | ||
getMetricValueWithFilters({ | ||
seriesName: "series-3", | ||
fieldName: "FieldName", | ||
labels: { label3: "label3", nonExistent: "nonExistent" }, | ||
noDataValue: "No data", | ||
}) | ||
).toEqual("No data"); | ||
}); | ||
|
||
it("retrieves correct metric value when multiple labels", () => { | ||
expect( | ||
getMetricValueWithFilters({ | ||
seriesName: "series-3", | ||
fieldName: "FieldName", | ||
labels: { label3: "label3", label4: "first" }, | ||
}) | ||
).toEqual(400); | ||
expect( | ||
getMetricValueWithFilters({ | ||
seriesName: "series-3", | ||
fieldName: "FieldName", | ||
labels: { label3: "label3", label4: "second" }, | ||
}) | ||
).toEqual(500); | ||
}); | ||
|
||
it("retrieves correct metric value with reducerId", () => { | ||
expect( | ||
getMetricValueWithFilters({ | ||
seriesName: "series-12", | ||
fieldName: "FieldName", | ||
labels: { label3: "label3" }, | ||
reducerID: "first", | ||
}) | ||
).toEqual(100); | ||
expect( | ||
getMetricValueWithFilters({ | ||
seriesName: "series-12", | ||
fieldName: "FieldName", | ||
labels: { label3: "label3" }, | ||
reducerID: "last", | ||
}) | ||
).toEqual(500); | ||
}); | ||
}); |
123 changes: 123 additions & 0 deletions
123
src/utils/getMetricValueWithFilters/getMetricValueWithFilters.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import { DataFrame, Field, PanelData } from "@grafana/data"; | ||
|
||
import { ReducerID } from "../field"; | ||
import { getValue } from "../metricValue"; | ||
import { getShowcaseMetricValue } from "../metricValue/getShowcaseMetricValue"; | ||
|
||
declare const data: PanelData; | ||
|
||
function getMultipleSeriesFromName(seriesName: string): DataFrame[] { | ||
return data.series.filter((series) => series.name === seriesName); | ||
} | ||
|
||
function getValueFieldsFromSeries(series: DataFrame[], fieldName: string) { | ||
return series | ||
.map(({ fields }) => | ||
fields.find((field) => | ||
[field.name, field.state?.displayName].includes(fieldName) | ||
) | ||
) | ||
.filter((x): x is Exclude<typeof x, undefined> => x !== undefined); | ||
} | ||
|
||
function getValueFieldsFromName(metricName: string, fieldName: string) { | ||
const series = getMultipleSeriesFromName(metricName); | ||
return getValueFieldsFromSeries(series, fieldName); | ||
} | ||
|
||
function getValueFieldFromLabels( | ||
valueFields: Field[], | ||
labels: Record<string, string> | ||
) { | ||
return valueFields.find(({ labels: fieldLabels }) => | ||
Object.entries(labels).every( | ||
([k, v]) => fieldLabels && fieldLabels[k] === v | ||
) | ||
); | ||
} | ||
|
||
function getMetricSeries({ | ||
seriesName, | ||
fieldName, | ||
labels, | ||
noDataValue, | ||
reducerID, | ||
}: { | ||
seriesName: string; | ||
fieldName: string; | ||
labels: Record<string, string>; | ||
noDataValue: unknown; | ||
reducerID: string; | ||
}) { | ||
const valueFields = getValueFieldsFromName(seriesName, fieldName); | ||
const valueField = getValueFieldFromLabels(valueFields, labels); | ||
const value = | ||
valueField?.state?.calcs?.[reducerID] ?? getValue(valueField, reducerID); | ||
return value ?? noDataValue; | ||
} | ||
|
||
/** | ||
* Function provides value from grafana queries based on given filters. | ||
* | ||
* @example | ||
* | ||
* getMetricValueWithFilters({seriesName: "series-1"}); // Returns first series with name "series-1". | ||
* | ||
* getMetricValueWithFilters({ | ||
seriesName: "series-1", | ||
fieldName: "field-1", | ||
}); // Returns first series with name "series-1" and fieldName "field-1". | ||
* | ||
* getMetricValueWithFilters({ | ||
seriesName: "series-1", | ||
fieldName: "field-1", | ||
labels: { someLabelKey: "label-1", anotherLabelKey: "label-2" }, | ||
}) // Returns first series with name "series-1", fieldName "field-1" and field contains matching labels. | ||
* | ||
* // Showcase | ||
* getMetricValueWithFilters({ seriesName: "series-1", showcase: true }) // Returns a random value between 0 and 1000. | ||
* | ||
* getMetricValueWithFilters({ | ||
seriesName: "series-1", | ||
showcase: true, | ||
range: { min: 0, max: 10 }, | ||
decimals: 2, | ||
}) // Returns random value between 1-10. | ||
* | ||
* @param seriesName - String for identifying correct series in Grafana's data object. | ||
* @param fieldName - String for identifying correct field in series(Defaults to "Value"). | ||
* @param labels - Object for filtering a specific series when multiple series have the same seriesName. | ||
* @param showcase - Boolean for returning random showcase value. | ||
* @param range - Object for setting minimum(min:) or maximum(max:) range for showcase value. | ||
* @param decimals - Number for setting static amount of decimals for showcase value. | ||
*/ | ||
export function getMetricValueWithFilters({ | ||
seriesName, | ||
fieldName = "Value", | ||
labels = {}, | ||
showcase, | ||
range, | ||
decimals, | ||
noDataValue = null, | ||
reducerID = ReducerID.last, | ||
}: { | ||
seriesName: string; | ||
fieldName?: string; | ||
labels?: Record<string, string>; | ||
showcase?: boolean; | ||
range?: { min: number; max: number }; | ||
decimals?: number; | ||
noDataValue?: unknown; | ||
reducerID?: string; | ||
}): unknown { | ||
if (showcase) { | ||
return getShowcaseMetricValue({ range, decimals }); | ||
} | ||
return getMetricSeries({ | ||
seriesName, | ||
fieldName, | ||
labels, | ||
noDataValue, | ||
reducerID, | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from "./getMetricValueWithFilters"; |