Skip to content

Commit

Permalink
fix: fix wrong time returned (#27)
Browse files Browse the repository at this point in the history
* ♻️ add type condtition to get time field

* ✅ add tests to time field conditions

* fix: fix wrong time returned
The time field is not retrieved when there are multiple series
and the data is retrieved based on the field name
instead of the series name.

Co-authored-by: Flesaker <[email protected]>
  • Loading branch information
ZuperZee and flesa authored Aug 3, 2021
1 parent ff4aab0 commit 481b4fa
Show file tree
Hide file tree
Showing 5 changed files with 316 additions and 44 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export { ReducerID } from "./utils/field";
export * from "./utils/metricValue";
export * from "./utils/metricData";
export * from "./utils/getDataFieldsFromName";
export * from "./utils/getFieldFromName";
export * from "./utils/getSeriesFromName";
export * from "./utils/evaluateString";
87 changes: 87 additions & 0 deletions src/utils/getDataFieldsFromName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { DataFrame, Field, PanelData } from "@grafana/data";

import { SearchOptions } from "./getFieldFromName";
import { getSeriesFromName } from "./getSeriesFromName";

declare const data: PanelData;

export interface DataFields {
valueField?: Field;
timeField?: Field;
}

export interface DataFieldOptions extends SearchOptions {
/**
* Get time field
*
* @default true
*/
getTime?: boolean;
}

function getValueField(
series: DataFrame,
name: string,
{ searchLabels = true }: SearchOptions = {}
) {
return series.fields.find((field) =>
[
field.name,
...(searchLabels && field.labels ? [field.labels.name] : []),
].includes(name)
);
}

function getTimeField(series: DataFrame) {
return (
series.fields.find((field) => field.type == "time") ??
series.fields.find((field) => field.name == "Time" || field.name == "time")
);
}

function getSeriesAndValueField(
name: string,
{ searchLabels = true }: SearchOptions = {}
) {
const series = getSeriesFromName(name);
if (series) {
const valueField =
getValueField(series, "Value", { searchLabels: false }) ??
getValueField(series, name, { searchLabels });

return { series, valueField };
}

for (const series of data.series) {
const valueField = getValueField(series, name, { searchLabels });
if (valueField) return { series, valueField };
}

return {};
}

/**
* Gets the series that contains the name (searches through series, fields and labels)
*
* @example
* ```ts
* getDataFieldsFromName("series-name");
* ```
*
* @param name
* @param DataFieldOptions
*
* @returns value and time field
*/
export function getDataFieldsFromName(
name: string,
{ searchLabels = true, getTime = true }: DataFieldOptions = {}
): DataFields | Record<string, never> {
const { series, valueField } = getSeriesAndValueField(name, { searchLabels });
if (series && valueField)
return {
valueField,
timeField: getTime ? getTimeField(series) : undefined,
};
return {};
}
217 changes: 217 additions & 0 deletions src/utils/metricData/getMetricDataFromName.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,22 @@ describe("getMetricDataFromName", () => {
window.data = {
state: LoadingState.Done,
series: [
{
fields: [
field({
name: "Time",
type: FieldType.time,
calcs: {},
values: [1577736800, 1577936800],
}),
field({
name: "field-0",
type: FieldType.number,
calcs: { [ReducerID.last]: 100 },
}),
],
length: 1,
},
{
name: "series-1",
fields: [
Expand Down Expand Up @@ -145,6 +161,22 @@ describe("getMetricDataFromName", () => {
window.data = {
state: LoadingState.Done,
series: [
{
fields: [
field({
name: "Time",
type: FieldType.time,
calcs: {},
values: [1577736800, 1577936800],
}),
field({
name: "field-0",
type: FieldType.number,
calcs: { [ReducerID.last]: 100 },
}),
],
length: 1,
},
{
fields: [
TIME_FIELD,
Expand All @@ -156,6 +188,22 @@ describe("getMetricDataFromName", () => {
],
length: 1,
},
{
fields: [
field({
name: "Time",
type: FieldType.time,
calcs: {},
values: [1577736800, 1577936800],
}),
field({
name: "field-2",
type: FieldType.number,
calcs: { [ReducerID.last]: 100 },
}),
],
length: 1,
},
],
timeRange: minimalTimeRange,
};
Expand All @@ -182,6 +230,22 @@ describe("getMetricDataFromName", () => {
window.data = {
state: LoadingState.Done,
series: [
{
fields: [
field({
name: "Time",
type: FieldType.time,
calcs: {},
values: [1577736800, 1577936800],
}),
field({
name: "field-0",
type: FieldType.number,
calcs: { [ReducerID.last]: 100 },
}),
],
length: 1,
},
{
fields: [
TIME_FIELD,
Expand Down Expand Up @@ -263,4 +327,157 @@ describe("getMetricDataFromName", () => {
});
});
});

describe("timeField name is time", () => {
beforeEach(() => {
window.data = {
state: LoadingState.Done,
series: [
{
name: "series-1",
fields: [
field({
name: "time",
type: FieldType.time,
calcs: {},
values: TIME_VALUES,
}),
field({
name: "Value",
type: FieldType.number,
calcs: {
[ReducerID.last]: 1000,
[ReducerID.first]: 100,
[ReducerID.max]: 1000,
},
}),
],
length: 1,
},
],
timeRange: minimalTimeRange,
};
});

afterEach(() => {
delete window.data;
});

it("get correct time", () => {
expect(getMetricDataFromName("series-1")).toStrictEqual({
calcs: {
[ReducerID.last]: 1000,
[ReducerID.first]: 100,
[ReducerID.max]: 1000,
},
time: {
[ReducerID.first]: TIME_VALUES[0],
[ReducerID.last]: TIME_VALUES[TIME_VALUES.length - 1],
},
hasData: true,
});
});
});

describe("timeField relies on type", () => {
beforeEach(() => {
window.data = {
state: LoadingState.Done,
series: [
{
name: "series-1",
fields: [
field({
name: "Random",
type: FieldType.time,
calcs: {},
values: TIME_VALUES,
}),
field({
name: "Value",
type: FieldType.number,
calcs: {
[ReducerID.last]: 1000,
[ReducerID.first]: 100,
[ReducerID.max]: 1000,
},
}),
],
length: 1,
},
],
timeRange: minimalTimeRange,
};
});

afterEach(() => {
delete window.data;
});

it("get correct time", () => {
expect(getMetricDataFromName("series-1")).toStrictEqual({
calcs: {
[ReducerID.last]: 1000,
[ReducerID.first]: 100,
[ReducerID.max]: 1000,
},
time: {
[ReducerID.first]: TIME_VALUES[0],
[ReducerID.last]: TIME_VALUES[TIME_VALUES.length - 1],
},
hasData: true,
});
});
});

describe("timeField with wrong type but correct name", () => {
beforeEach(() => {
window.data = {
state: LoadingState.Done,
series: [
{
name: "series-1",
fields: [
field({
name: "Time",
type: FieldType.number,
calcs: {},
values: TIME_VALUES,
}),
field({
name: "Value",
type: FieldType.number,
calcs: {
[ReducerID.last]: 1000,
[ReducerID.first]: 100,
[ReducerID.max]: 1000,
},
}),
],
length: 1,
},
],
timeRange: minimalTimeRange,
};
});

afterEach(() => {
delete window.data;
});

it("get correct time", () => {
expect(getMetricDataFromName("series-1")).toStrictEqual({
calcs: {
[ReducerID.last]: 1000,
[ReducerID.first]: 100,
[ReducerID.max]: 1000,
},
time: {
[ReducerID.first]: TIME_VALUES[0],
[ReducerID.last]: TIME_VALUES[TIME_VALUES.length - 1],
},
hasData: true,
});
});
});
});
28 changes: 9 additions & 19 deletions src/utils/metricData/getMetricDataFromName.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import { DataFrame } from "@grafana/data";
import { Field } from "@grafana/data";

import { getFieldFromName } from "../getFieldFromName";
import { getSeriesFromName } from "../getSeriesFromName";

function getTime(series?: DataFrame) {
const timeField =
series?.fields.find((field) => field.name == "Time") ??
getFieldFromName("Time");
import { getDataFieldsFromName } from "../getDataFieldsFromName";

function getTime(timeField?: Field) {
const timeValues = timeField?.values;
const time = timeValues
? {
Expand All @@ -20,18 +15,12 @@ function getTime(series?: DataFrame) {
}

function getCalcs({
series,
metricName,
valueField,
reducerIDs,
}: {
series?: DataFrame;
metricName?: string;
valueField?: Field;
reducerIDs?: string[];
}) {
const valueField =
series?.fields.find((field) => field.name == "Value") ??
(metricName ? getFieldFromName(metricName) : undefined);

const calcs = valueField?.state?.calcs ?? {};
const enquiredCalcs =
reducerIDs?.reduce(
Expand Down Expand Up @@ -74,10 +63,11 @@ export function getMetricDataFromName(
metricName: string,
{ reducerIDs }: MetricDataFromNameOptions = {}
): MetricData {
const series = getSeriesFromName(metricName);
const calcs = getCalcs({ series, metricName, reducerIDs });
const { valueField, timeField } = getDataFieldsFromName(metricName);

const calcs = getCalcs({ valueField, reducerIDs });
const hasData = Object.keys(calcs).length > 0;
const time = hasData ? getTime(series) : {};
const time = hasData ? getTime(timeField) : {};

return { calcs, time, hasData };
}
Loading

0 comments on commit 481b4fa

Please sign in to comment.