Adding changes to frontend for interleaving chaos events on litmus-ui graphs. (#2521)

* Adding interleaving for chaos events.

Signed-off-by: ishangupta-ds <ishan@chaosnative.com>

* Fixes for interleaving

Signed-off-by: ishangupta-ds <ishan@chaosnative.com>

* Minor fix.

Signed-off-by: ishangupta-ds <ishan@chaosnative.com>

* Upgrading to litmus-ui version 1.0.1

Signed-off-by: ishangupta-ds <ishan@chaosnative.com>

* Minor fix

Signed-off-by: ishangupta-ds <ishan@chaosnative.com>

* npm install fix

Signed-off-by: ishangupta-ds <ishan@chaosnative.com>

* minor fix for events

Signed-off-by: ishangupta-ds <ishan@chaosnative.com>

* Updated git ignore to add build folder also updated litmus-ui version to 1.0.2

Signed-off-by: ishangupta-ds <ishan@chaosnative.com>

* Updated litmus-ui to 1.0.3

Signed-off-by: ishangupta-ds <ishan@chaosnative.com>

* minor fix

Signed-off-by: ishangupta-ds <ishan@chaosnative.com>

* minor fix

Signed-off-by: ishangupta-ds <ishan@chaosnative.com>

* minor fix

Signed-off-by: ishangupta-ds <ishan@chaosnative.com>
This commit is contained in:
Ishan Gupta 2021-03-11 15:45:05 +05:30 committed by GitHub
parent 32e35ad4fb
commit cbe2eb12e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 28001 additions and 7016 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
.nyc_output
__pycache__/
**/node_modules/
**/build/
**/cypress/videos/
**/cypress/screenshots/
**/.nyc_output/

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,7 @@
"jsonwebtoken": "^8.5.1",
"jspdf": "^2.1.1",
"jspdf-autotable": "^3.5.13",
"litmus-ui": "^0.1.4",
"litmus-ui": "^1.0.3",
"localforage": "^1.7.3",
"lodash": "^4.17.20",
"moment": "^2.27.0",

View File

@ -246,6 +246,7 @@ analyticsDashboard:
seconds: seconds
minutes: minutes
hours: hours
days: days
few: few
error:

View File

@ -9,7 +9,7 @@ export default [
information:
'This dashboard visualizes Node and Pod level CPU and memory utilization metrics interleaved with chaos events.',
chaosEventQueryTemplate:
'heptio_eventrouter_normal_total{reason="ChaosInject", involved_object_name="#{}", involved_object_namespace="*{}", involved_object_kind="ChaosEngine"} - on () (heptio_eventrouter_normal_total{reason="ChaosEngineCompleted", involved_object_name="#{}", involved_object_namespace="*{}", involved_object_kind="ChaosEngine"} OR on() vector(0))',
'litmuschaos_awaited_experiments{chaosresult_name="#{}",chaosresult_namespace="*{}", job="chaos-exporter"}',
panelGroupMap: [
{
groupName: 'CPU Usage Metrics',
@ -52,7 +52,7 @@ export default [
prom_queries: [
{
queryid: uuidv4(),
prom_query_name: 'instance:node_cpu_utilisation:rate1m',
prom_query_name: 'instance:node_cpu_utilisation:rate1m*100',
legend: '{{instance}}',
resolution: '1/2',
minstep: '5',
@ -104,7 +104,7 @@ export default [
prom_queries: [
{
queryid: uuidv4(),
prom_query_name: 'instance:node_memory_utilisation:ratio',
prom_query_name: 'instance:node_memory_utilisation:ratio*100',
legend: '{{instance}}',
resolution: '1/2',
minstep: '5',
@ -279,7 +279,7 @@ export default [
information:
'This dashboard visualizes Sock Shop application metrics metrics interleaved with chaos events and chaos exporter metrics.',
chaosEventQueryTemplate:
'heptio_eventrouter_normal_total{reason="ChaosInject", involved_object_name="#{}", involved_object_namespace="*{}", involved_object_kind="ChaosEngine"} - on () (heptio_eventrouter_normal_total{reason="ChaosEngineCompleted", involved_object_name="#{}", involved_object_namespace="*{}", involved_object_kind="ChaosEngine"} OR on() vector(0))',
'litmuschaos_awaited_experiments{chaosresult_name="#{}",chaosresult_namespace="*{}", job="chaos-exporter"}',
panelGroupMap: [
{
groupName: 'Orders Metrics',

View File

@ -42,7 +42,7 @@ const useStyles = makeStyles((theme: Theme) => ({
flexDirection: 'row',
justifyContent: 'center',
'&:hover': {
backgroundColor: theme.palette.secondary.light,
backgroundColor: theme.palette.primary.light,
color: theme.palette.secondary.contrastText,
'& path': {
fill: theme.palette.secondary.contrastText,

View File

@ -212,7 +212,7 @@ function App() {
}
}, [token]);
return (
<LitmusThemeProvider platform="litmus-portal">
<LitmusThemeProvider>
<Suspense fallback={<Loader />}>
<Router history={history}>
<div className={classes.root}>

View File

@ -181,8 +181,9 @@ const DashboardConfigurePage: React.FC<DashboardConfigurePageProps> = ({
const check: number = chaosEngineNamesAndNamespacesMap.filter(
(data, index) => {
if (
data.engineName ===
parsedEmbeddedYaml.metadata.name &&
data.engineName.includes(
parsedEmbeddedYaml.metadata.name
) &&
data.engineNamespace === engineNamespace
) {
matchIndex = index;
@ -193,7 +194,7 @@ const DashboardConfigurePage: React.FC<DashboardConfigurePageProps> = ({
).length;
if (check === 0) {
chaosEngineNamesAndNamespacesMap.push({
engineName: parsedEmbeddedYaml.metadata.name,
engineName: `${parsedEmbeddedYaml.metadata.name}-${parsedEmbeddedYaml.spec.experiments[0].name}`,
engineNamespace,
workflowName: workflowYaml.metadata.name,
});

View File

@ -7,11 +7,7 @@ interface ThemeWrapperProps {
}
const ThemeWrapper: React.FC<ThemeWrapperProps> = ({ children }) => {
return (
<LitmusThemeProvider platform="litmus-portal">
{children}
</LitmusThemeProvider>
);
return <LitmusThemeProvider>{children}</LitmusThemeProvider>;
};
export default ThemeWrapper;

View File

@ -3,12 +3,12 @@ import { ChaosEngineNamesAndNamespacesMap } from '../models/dashboardsData';
const getEngineNameAndNamespace = (chaosQueryString: string) => {
const parsedChaosInfoMap: ChaosEngineNamesAndNamespacesMap = {
engineName: chaosQueryString
.split(',')[1]
.split(',')[0]
.trim()
.split('=')[1]
.slice(1, -1),
engineNamespace: chaosQueryString
.split(',')[2]
.split(',')[1]
.trim()
.split('=')[1]
.slice(1, -1),

View File

@ -181,7 +181,9 @@ const TableData: React.FC<TableDataProps> = ({ data }) => {
const check: number = chaosEngineNamesAndNamespacesMap.filter(
(data, index) => {
if (
data.engineName === parsedEmbeddedYaml.metadata.name &&
data.engineName.includes(
parsedEmbeddedYaml.metadata.name
) &&
data.engineNamespace === engineNamespace
) {
matchIndex = index;
@ -192,7 +194,7 @@ const TableData: React.FC<TableDataProps> = ({ data }) => {
).length;
if (check === 0) {
chaosEngineNamesAndNamespacesMap.push({
engineName: parsedEmbeddedYaml.metadata.name,
engineName: `${parsedEmbeddedYaml.metadata.name}-${parsedEmbeddedYaml.spec.experiments[0].name}`,
engineNamespace,
workflowName: workflowYaml.metadata.name,
});
@ -217,7 +219,7 @@ const TableData: React.FC<TableDataProps> = ({ data }) => {
(existingPromQuery: PromQuery) => {
if (
existingPromQuery.prom_query_name.startsWith(
'heptio_eventrouter_normal_total{reason="ChaosInject"'
'litmuschaos_awaited_experiments'
)
) {
const chaosDetails: ChaosEngineNamesAndNamespacesMap = getEngineNameAndNamespace(
@ -229,8 +231,9 @@ const TableData: React.FC<TableDataProps> = ({ data }) => {
index: number
) => {
if (
chaosDetailsFomSchedule.engineName ===
chaosDetails.engineName &&
chaosDetailsFomSchedule.engineName.includes(
chaosDetails.engineName
) &&
chaosDetailsFomSchedule.engineNamespace ===
chaosDetails.engineNamespace
) {
@ -254,9 +257,7 @@ const TableData: React.FC<TableDataProps> = ({ data }) => {
panel.prom_queries.forEach((query: PromQuery) => {
let updatedLegend: string = query.legend;
if (
query.prom_query_name.startsWith(
'heptio_eventrouter_normal_total{reason="ChaosInject"'
)
query.prom_query_name.startsWith('litmuschaos_awaited_experiments')
) {
const chaosDetails: ChaosEngineNamesAndNamespacesMap = getEngineNameAndNamespace(
query.prom_query_name
@ -264,8 +265,9 @@ const TableData: React.FC<TableDataProps> = ({ data }) => {
chaosEngineNamesAndNamespacesMap.forEach(
(chaosDetailsFomSchedule: ChaosEngineNamesAndNamespacesMap) => {
if (
chaosDetailsFomSchedule.engineName ===
chaosDetails.engineName &&
chaosDetailsFomSchedule.engineName.includes(
chaosDetails.engineName
) &&
chaosDetailsFomSchedule.engineNamespace ===
chaosDetails.engineNamespace &&
!query.legend.includes(chaosDetailsFomSchedule.workflowName)

View File

@ -2,7 +2,7 @@
import { useQuery } from '@apollo/client';
import { Typography } from '@material-ui/core';
import useTheme from '@material-ui/core/styles/useTheme';
import { DateValue, GraphMetric, LineAreaGraph } from 'litmus-ui';
import { GraphMetric, LineAreaGraph } from 'litmus-ui';
import React, { useEffect } from 'react';
import { useSelector } from 'react-redux';
import Loader from '../../../components/Loader';
@ -20,20 +20,11 @@ import {
import { RootState } from '../../../redux/reducers';
import useStyles from './styles';
const filterUndefinedData = (data: GraphMetric[]): GraphMetric[] =>
data
? data
.filter((elem) => elem && elem.data && elem.data.length)
.filter((elem) =>
elem.data.filter(
(d: DateValue) =>
d &&
d.date &&
typeof d.date === 'number' &&
typeof d.value === 'number'
)
)
: data;
interface PrometheusQueryDataInterface {
promInput: PrometheusQueryInput;
chaosInput: string[];
}
const PanelContent: React.FC<PanelResponse> = ({
panel_id,
panel_name,
@ -46,18 +37,20 @@ const PanelContent: React.FC<PanelResponse> = ({
}) => {
const { palette } = useTheme();
const classes = useStyles();
const lineGraph: string[] = Object.values(palette.graph.line).map((elem) =>
typeof elem === 'string' ? elem : palette.graph.dashboard.lightBlue
);
const lineGraph: string[] = palette.graph.line;
const areaGraph: string[] = palette.graph.area;
const [
prometheusQueryData,
setPrometheusQueryData,
] = React.useState<PrometheusQueryInput>({
url: '',
start: '',
end: '',
queries: [],
] = React.useState<PrometheusQueryDataInterface>({
promInput: {
url: '',
start: '',
end: '',
queries: [],
},
chaosInput: [],
});
const [updateQueries, setUpdateQueries] = React.useState<boolean>(false);
@ -77,14 +70,18 @@ const PanelContent: React.FC<PanelResponse> = ({
PrometheusResponse,
PrometheusQueryVars
>(PROM_QUERY, {
variables: { prometheusInput: prometheusQueryData },
// fetchPolicy: 'cache-and-network',
variables: { prometheusInput: prometheusQueryData.promInput },
fetchPolicy: 'cache-and-network',
pollInterval: selectedDashboard.refreshRate,
});
const generatePrometheusQueryData = () => {
const promQueries: promQueryInput[] = [];
const chaosQueries: string[] = [];
prom_queries.forEach((query: PromQuery) => {
if (query.prom_query_name.startsWith('litmuschaos_awaited_experiments')) {
chaosQueries.push(query.queryid);
}
promQueries.push({
queryid: query.queryid,
query: query.prom_query_name,
@ -99,25 +96,18 @@ const PanelContent: React.FC<PanelResponse> = ({
end: `${Math.round(new Date().getTime() / 1000)}`,
queries: promQueries,
};
setPrometheusQueryData(prometheusQueryInput);
setPrometheusQueryData({
promInput: prometheusQueryInput,
chaosInput: chaosQueries,
});
};
useEffect(() => {
if (firstLoad === true && updateQueries === false) {
generatePrometheusQueryData();
setFirstLoad(false);
setUpdateQueries(true);
}
if (updateQueries === true && firstLoad === false) {
setTimeout(() => {
generatePrometheusQueryData();
}, selectedDashboard.refreshRate);
}
}, [prometheusQueryData]);
let seriesData: Array<GraphMetric> = [
{ metricName: '', data: [{ date: NaN, value: NaN }] },
];
let eventData: Array<GraphMetric> = [
{ metricName: '', data: [{ date: NaN, value: NaN }] },
];
if (
prometheusData &&
prometheusData.GetPromQuery.length &&
@ -133,9 +123,36 @@ const PanelContent: React.FC<PanelResponse> = ({
})),
baseColor: lineGraph[index % lineGraph.length],
}));
prometheusData.GetPromQuery.forEach((queryResponse) => {
if (prometheusQueryData.chaosInput.includes(queryResponse.queryid)) {
if (queryResponse.legends && queryResponse.legends[0]) {
eventData = queryResponse.legends.map((elem, index) => ({
metricName: elem[0] ?? 'test',
data: queryResponse.tsvs[index].map((dataPoint) => ({
date: parseInt(dataPoint.timestamp ?? '0', 10) * 1000,
value: parseInt(dataPoint.value ?? '0', 10),
})),
baseColor: areaGraph[index % areaGraph.length],
}));
}
}
});
}
if (error || !seriesData) {
useEffect(() => {
if (firstLoad === true && updateQueries === false) {
generatePrometheusQueryData();
setFirstLoad(false);
setUpdateQueries(true);
}
if (updateQueries === true && firstLoad === false) {
setTimeout(() => {
generatePrometheusQueryData();
}, selectedDashboard.refreshRate);
}
}, [prometheusQueryData]);
if (error) {
return (
<div className={classes.rootPanel}>
<Typography>{panel_name}</Typography>
@ -144,8 +161,6 @@ const PanelContent: React.FC<PanelResponse> = ({
);
}
// console.log(seriesData);
return (
<div className={classes.rootPanel}>
<div>
@ -172,11 +187,16 @@ const PanelContent: React.FC<PanelResponse> = ({
<div className={classes.singleGraph}>
<LineAreaGraph
legendTableHeight={120}
openSeries={filterUndefinedData(seriesData)}
openSeries={seriesData}
eventSeries={eventData}
showPoints={false}
showLegendTable
showTips
margin={{ left: 50, right: 20, top: 20, bottom: 10 }}
showEventMarkers
unit={unit}
yLabel={y_axis_left}
yLabelOffset={50}
margin={{ left: 70, right: 20, top: 20, bottom: 10 }}
/>
</div>
{/* <Typography>

View File

@ -39,7 +39,7 @@ const useStyles = makeStyles((theme) => ({
title: {
fontWeight: 700,
fontSize: '0.9rem',
color: theme.palette.primary.contrastText,
color: theme.palette.text.primary,
textAlign: 'center',
backgroundColor: theme.palette.background.paper,
paddingTop: theme.spacing(2.5),

View File

@ -149,7 +149,9 @@ const TableDashboardData: React.FC<TableDashboardData> = ({
const check: number = chaosEngineNamesAndNamespacesMap.filter(
(data, index) => {
if (
data.engineName === parsedEmbeddedYaml.metadata.name &&
data.engineName.includes(
parsedEmbeddedYaml.metadata.name
) &&
data.engineNamespace === engineNamespace
) {
matchIndex = index;
@ -160,7 +162,7 @@ const TableDashboardData: React.FC<TableDashboardData> = ({
).length;
if (check === 0) {
chaosEngineNamesAndNamespacesMap.push({
engineName: parsedEmbeddedYaml.metadata.name,
engineName: `${parsedEmbeddedYaml.metadata.name}-${parsedEmbeddedYaml.spec.experiments[0].name}`,
engineNamespace,
workflowName: workflowYaml.metadata.name,
});
@ -185,7 +187,7 @@ const TableDashboardData: React.FC<TableDashboardData> = ({
(existingPromQuery: PromQuery) => {
if (
existingPromQuery.prom_query_name.startsWith(
'heptio_eventrouter_normal_total{reason="ChaosInject"'
'litmuschaos_awaited_experiments'
)
) {
const chaosDetails: ChaosEngineNamesAndNamespacesMap = getEngineNameAndNamespace(
@ -197,8 +199,9 @@ const TableDashboardData: React.FC<TableDashboardData> = ({
index: number
) => {
if (
chaosDetailsFomSchedule.engineName ===
chaosDetails.engineName &&
chaosDetailsFomSchedule.engineName.includes(
chaosDetails.engineName
) &&
chaosDetailsFomSchedule.engineNamespace ===
chaosDetails.engineNamespace
) {
@ -222,9 +225,7 @@ const TableDashboardData: React.FC<TableDashboardData> = ({
panel.prom_queries.forEach((query: PromQuery) => {
let updatedLegend: string = query.legend;
if (
query.prom_query_name.startsWith(
'heptio_eventrouter_normal_total{reason="ChaosInject"'
)
query.prom_query_name.startsWith('litmuschaos_awaited_experiments')
) {
const chaosDetails: ChaosEngineNamesAndNamespacesMap = getEngineNameAndNamespace(
query.prom_query_name
@ -232,8 +233,9 @@ const TableDashboardData: React.FC<TableDashboardData> = ({
chaosEngineNamesAndNamespacesMap.forEach(
(chaosDetailsFomSchedule: ChaosEngineNamesAndNamespacesMap) => {
if (
chaosDetailsFomSchedule.engineName ===
chaosDetails.engineName &&
chaosDetailsFomSchedule.engineName.includes(
chaosDetails.engineName
) &&
chaosDetailsFomSchedule.engineNamespace ===
chaosDetails.engineNamespace &&
!query.legend.includes(chaosDetailsFomSchedule.workflowName)

View File

@ -140,10 +140,10 @@ const useStyles = makeStyles((theme: Theme) => ({
marginLeft: 'auto',
},
avatarBackground: {
backgroundColor: theme.palette.primary.main,
backgroundColor: theme.palette.primary.light,
width: '2.56rem',
height: '2.56rem',
color: theme.palette.text.primary,
color: theme.palette.secondary.contrastText,
alignContent: 'right',
marginRight: theme.spacing(2.5),
[theme.breakpoints.down('sm')]: {