-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat: Adds new run-time metrics visualisation to a test (#833)
- Loading branch information
1 parent
5ac67a6
commit 58c653b
Showing
8 changed files
with
261 additions
and
1 deletion.
There are no files selected for viewing
21 changes: 21 additions & 0 deletions
21
web/frontend/src/components/Run/RunningStatus/OverviewMetrics/MetricCard/MetricCard.js
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,21 @@ | ||
import { Statistic } from "antd"; | ||
import React from "react"; | ||
|
||
const MetricCard = ({ value, title, unit, borderColor }) => ( | ||
<Statistic | ||
title={title} | ||
value={value} | ||
suffix={unit} | ||
style={{ | ||
border: `1px solid ${borderColor}` || "#d9d9d9", | ||
borderRadius: "10px", | ||
boxShadow: "0px 2px 4px rgba(0, 0, 0, 0.2)", | ||
flex: "1 1 auto", | ||
margin: "8px", | ||
textAlign: "center", | ||
padding: "5px" | ||
}} | ||
/> | ||
); | ||
|
||
export default MetricCard; |
3 changes: 3 additions & 0 deletions
3
web/frontend/src/components/Run/RunningStatus/OverviewMetrics/MetricCard/index.js
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,3 @@ | ||
import MetricCard from "./MetricCard"; | ||
|
||
export default MetricCard; |
199 changes: 199 additions & 0 deletions
199
web/frontend/src/components/Run/RunningStatus/OverviewMetrics/OverviewMetrics.js
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,199 @@ | ||
/* eslint-disable max-statements */ | ||
import { Descriptions } from "antd"; | ||
import moment from "moment"; | ||
import React, { useEffect, useRef, useState } from "react"; | ||
|
||
import { fetchMetrics } from "../../../../lib/api/endpoints/runMetric"; | ||
import { runStatus as runStatusModel } from "../../../../lib/api/models"; | ||
import { avg } from "../../../../lib/utils"; | ||
import PageSpinner from "../../../layout/PageSpinner"; | ||
import MetricCard from "./MetricCard"; | ||
|
||
const OverviewMetrics = ({ run }) => { | ||
const [runMetrics, setrunMetrics] = useState([]); | ||
const [isLoading, setIsLoading] = useState(false); | ||
const [totals, setTotals] = useState({ | ||
totalLatencyAvg: 0, | ||
totallatencyP90: 0, | ||
totalSuccessCount: 0, | ||
totalCount: 0, | ||
totalRpm: 0 | ||
}); | ||
const refreshInterval = 3000; | ||
const timerRef = useRef(null); | ||
|
||
const calculateErrorRate = (successCount, totalCount) => { | ||
const errorRate = parseFloat((1 - successCount / totalCount) * 100).toFixed( | ||
2 | ||
); | ||
|
||
return errorRate; | ||
}; | ||
|
||
const updaterunMetrics = async (runIdToFetch) => { | ||
setIsLoading(true); | ||
|
||
const metricsRes = await fetchMetrics(runIdToFetch, 0, true); | ||
|
||
const getRpm = (minDatetime, maxDatetime, totalCount) => { | ||
const dateDuration = moment.duration(maxDatetime.diff(minDatetime)); | ||
const diffInSeconds = | ||
dateDuration.asSeconds() > 0 ? dateDuration.asSeconds() : 1; | ||
|
||
return parseFloat((totalCount / diffInSeconds) * 60).toFixed(0); | ||
}; | ||
|
||
const formattedrunMetrics = metricsRes.map( | ||
({ | ||
minDatetime, | ||
maxDatetime, | ||
totalCount, | ||
successCount, | ||
label, | ||
latencyAvg, | ||
latencyP90, | ||
responses | ||
}) => { | ||
const errorsCount = totalCount - successCount; | ||
const errorRate = calculateErrorRate(successCount, totalCount); | ||
const rpm = getRpm(minDatetime, maxDatetime, totalCount); | ||
|
||
return { | ||
key: label, | ||
errorsCount, | ||
successCount, | ||
errorRate, | ||
label, | ||
rpm, | ||
totalCount, | ||
latencyAvg, | ||
latencyP90, | ||
responses | ||
}; | ||
} | ||
); | ||
|
||
setrunMetrics(formattedrunMetrics); | ||
|
||
setIsLoading(false); | ||
}; | ||
|
||
const calculateTotals = () => { | ||
const totalLatencyAvg = | ||
runMetrics.length > 0 | ||
? runMetrics.reduce((total, metric) => total + metric.latencyAvg, 0) | ||
: 0; | ||
const totallatencyP90 = | ||
runMetrics.length > 0 | ||
? runMetrics.reduce((total, metric) => total + metric.latencyP90, 0) | ||
: 0; | ||
const totalSuccessCount = | ||
runMetrics.length > 0 | ||
? runMetrics.reduce((total, metric) => total + metric.successCount, 0) | ||
: 0; | ||
const totalCount = | ||
runMetrics.length > 0 | ||
? runMetrics.reduce((total, metric) => total + metric.totalCount, 0) | ||
: 0; | ||
const totalRpm = | ||
runMetrics.length > 0 | ||
? runMetrics.reduce( | ||
(total, metric) => total + parseFloat(metric.rpm), | ||
0 | ||
) | ||
: 0; | ||
|
||
setTotals({ | ||
totalLatencyAvg, | ||
totallatencyP90, | ||
totalSuccessCount, | ||
totalCount, | ||
totalRpm | ||
}); | ||
}; | ||
|
||
const startMetricsRefreshTimer = () => { | ||
if (run.runStatus === runStatusModel.RUNNING) { | ||
timerRef.current = setInterval(() => { | ||
updaterunMetrics(run.id); | ||
}, refreshInterval); | ||
} | ||
}; | ||
|
||
const stopMetricsRefreshTimer = () => { | ||
clearInterval(timerRef.current); | ||
}; | ||
|
||
useEffect(() => { | ||
updaterunMetrics(run.id); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [run]); | ||
|
||
useEffect(() => { | ||
calculateTotals(); | ||
startMetricsRefreshTimer(); | ||
return () => { | ||
stopMetricsRefreshTimer(); | ||
}; | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [runMetrics, run.runStatus]); | ||
|
||
return isLoading ? ( | ||
<PageSpinner /> | ||
) : ( | ||
<div | ||
style={{ | ||
border: "1px solid #fff " | ||
}} | ||
> | ||
<Descriptions> | ||
<div | ||
style={{ | ||
flexWrap: "wrap" | ||
}} | ||
> | ||
<Descriptions.Item> | ||
<MetricCard | ||
title="Average Latency" | ||
value={avg(totals.totalLatencyAvg, runMetrics.length).toFixed(2)} | ||
unit="ms" | ||
borderColor="#ffd166" | ||
/> | ||
</Descriptions.Item> | ||
<Descriptions.Item> | ||
<MetricCard | ||
title="90% Latency" | ||
value={avg(totals.totallatencyP90, runMetrics.length).toFixed(2)} | ||
unit="ms" | ||
borderColor="#ffab40" | ||
/> | ||
</Descriptions.Item> | ||
<Descriptions.Item> | ||
<MetricCard | ||
title="Errors" | ||
value={calculateErrorRate( | ||
totals.totalSuccessCount, | ||
totals.totalCount | ||
)} | ||
unit="%" | ||
borderColor="#ff6b6b" | ||
/> | ||
</Descriptions.Item> | ||
<Descriptions.Item> | ||
<MetricCard | ||
title="Average RPM" | ||
value={avg( | ||
parseFloat(totals.totalRpm), | ||
runMetrics.length | ||
).toFixed(0)} | ||
unit="req/min" | ||
borderColor="#64b5f6" | ||
/> | ||
</Descriptions.Item> | ||
</div> | ||
</Descriptions> | ||
</div> | ||
); | ||
}; | ||
|
||
export default OverviewMetrics; |
17 changes: 17 additions & 0 deletions
17
web/frontend/src/components/Run/RunningStatus/OverviewMetrics/OverviewMetrics.test.js
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,17 @@ | ||
import { render } from "@testing-library/react"; | ||
import React from "react"; | ||
|
||
import OverviewMetrics from "./OverviewMetrics"; | ||
|
||
describe("OverviewMetrics", () => { | ||
const mockRun = { | ||
id: "123", | ||
runStatus: "RUNNING" | ||
}; | ||
|
||
test("should render OverviewMetrics component", () => { | ||
const rendered = render(<OverviewMetrics run={mockRun} />); | ||
const component = rendered.container; | ||
expect(component.outerHTML).toMatchSnapshot(); | ||
}); | ||
}); |
3 changes: 3 additions & 0 deletions
3
...c/components/Run/RunningStatus/OverviewMetrics/__snapshots__/OverviewMetrics.test.js.snap
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,3 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`OverviewMetrics should render OverviewMetrics component 1`] = `"<div><div class=\\"ant-row ant-row-center ant-row-middle\\" style=\\"align-self: center;\\"><div class=\\"ant-spin ant-spin-spinning\\"><span role=\\"img\\" aria-label=\\"loading\\" style=\\"font-size: 64px;\\" class=\\"anticon anticon-loading anticon-spin ant-spin-dot\\"><svg viewBox=\\"0 0 1024 1024\\" focusable=\\"false\\" data-icon=\\"loading\\" width=\\"1em\\" height=\\"1em\\" fill=\\"currentColor\\" aria-hidden=\\"true\\"><path d=\\"M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z\\"></path></svg></span></div></div></div>"`; |
3 changes: 3 additions & 0 deletions
3
web/frontend/src/components/Run/RunningStatus/OverviewMetrics/index.js
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,3 @@ | ||
import OverviewMetrics from "./OverviewMetrics"; | ||
|
||
export default OverviewMetrics; |
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