Skip to content

Commit

Permalink
Top n queries configuration page (#8)
Browse files Browse the repository at this point in the history
* Add 2 tabs to home screen

Signed-off-by: Emily Guo <[email protected]>

* two tabs for query insights and configuration

Signed-off-by: Emily Guo <[email protected]>

* Breadcrumbs + restructuring

Signed-off-by: Emily Guo <[email protected]>

* Top n queries table + search

Signed-off-by: Emily Guo <[email protected]>

* search in general

Signed-off-by: Emily Guo <[email protected]>

* Search includes indices and time selection fully works

Signed-off-by: Emily Guo <[email protected]>

* Fix tabs display

Signed-off-by: Emily Guo <[email protected]>

* Basic functionalities of configuration page

Signed-off-by: Emily Guo <[email protected]>

* Save button + cancel button working

Signed-off-by: Emily Guo <[email protected]>

* Fixing lint and including relevant files

Signed-off-by: Emily Guo <[email protected]>

* Typo

Signed-off-by: Emily Guo <[email protected]>

* ignore lintcache

Signed-off-by: Emily Guo <[email protected]>

* Delete .eslintcache

Signed-off-by: Emily Guo <[email protected]>

* remove commented out lines

Signed-off-by: Emily Guo <[email protected]>

* Update based on comments on overview page

Signed-off-by: Emily Guo <[email protected]>

* Rerun security check?

Signed-off-by: Emily Guo <[email protected]>

* Added updates to all configurations

Signed-off-by: Emily Guo <[email protected]>

* Updated unit test

Signed-off-by: Emily Guo <[email protected]>

* Fix based on comments

Signed-off-by: Emily Guo <[email protected]>

* Fixed lint issues

Signed-off-by: Emily Guo <[email protected]>

* Update TopNQueries.tsx

Signed-off-by: Emily Guo <[email protected]>

---------

Signed-off-by: Emily Guo <[email protected]>
Signed-off-by: Emily Guo <[email protected]>
Signed-off-by: Emily Guo <[email protected]>
  • Loading branch information
LilyCaroline17 authored Sep 4, 2024
1 parent 4987001 commit afe9a0c
Show file tree
Hide file tree
Showing 3 changed files with 7,113 additions and 0 deletions.
345 changes: 345 additions & 0 deletions public/pages/Configuration/Configuration.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,345 @@
import React, { useMemo, useCallback, useState, useEffect } from 'react';
import {
EuiBottomBar,
EuiButton,
EuiButtonEmpty,
EuiFieldNumber,
EuiFlexGrid,
EuiFlexGroup,
EuiFlexItem,
EuiForm,
EuiFormRow,
EuiHealth,
EuiPanel,
EuiSelect,
EuiSpacer,
EuiSwitch,
EuiText,
EuiTitle,
} from '@elastic/eui';
import { useHistory, useLocation } from 'react-router-dom';
import { CoreStart } from '../../../../../src/core/public';
import { QUERY_INSIGHTS, MetricSettings } from '../TopNQueries/TopNQueries';

const Configuration = ({
latencySettings,
cpuSettings,
memorySettings,
configInfo,
core,
}: {
latencySettings: MetricSettings;
cpuSettings: MetricSettings;
memorySettings: MetricSettings;
configInfo: any;
core: CoreStart;
}) => {
const metricTypes = [
{ value: 'latency', text: 'Latency' },
{ value: 'cpu', text: 'CPU' },
{ value: 'memory', text: 'Memory' },
];

const timeUnits = [
{ value: 'MINUTES', text: 'Minute(s)' },
{ value: 'HOURS', text: 'Hour(s)' },
];

const minutesOptions = [
{ value: '1', text: '1' },
{ value: '5', text: '5' },
{ value: '10', text: '10' },
{ value: '30', text: '30' },
];

const history = useHistory();
const location = useLocation();

const [metric, setMetric] = useState<'latency' | 'cpu' | 'memory'>('latency');
const [isEnabled, setIsEnabled] = useState<boolean>(false);
const [topNSize, setTopNSize] = useState(latencySettings.currTopN);
const [windowSize, setWindowSize] = useState(latencySettings.currWindowSize);
const [time, setTime] = useState(latencySettings.currTimeUnit);

const metricSettingsMap = useMemo(
() => ({
latency: latencySettings,
cpu: cpuSettings,
memory: memorySettings,
}),
[latencySettings, cpuSettings, memorySettings]
);

const newOrReset = useCallback(() => {
const currMetric = metricSettingsMap[metric];
setTopNSize(currMetric.currTopN);
setWindowSize(currMetric.currWindowSize);
setTime(currMetric.currTimeUnit);
setIsEnabled(currMetric.isEnabled);
}, [metric, metricSettingsMap]);

useEffect(() => {
newOrReset();
}, [newOrReset]);

useEffect(() => {
core.chrome.setBreadcrumbs([
{
text: 'Query insights',
href: QUERY_INSIGHTS,
onClick: (e) => {
e.preventDefault();
history.push(QUERY_INSIGHTS);
},
},
]);
}, [core.chrome, history, location]);

const onMetricChange = (e: any) => {
setMetric(e.target.value);
};

const onEnabledChange = (e: any) => {
setIsEnabled(e.target.checked);
};

const onTopNSizeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setTopNSize(e.target.value);
};

const onWindowSizeChange = (
e: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLSelectElement>
) => {
setWindowSize(e.target.value);
};

const onTimeChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setTime(e.target.value);
};

const MinutesBox = () => (
<EuiSelect
id="minutes"
required={true}
options={minutesOptions}
value={windowSize}
onChange={onWindowSizeChange}
/>
);

const HoursBox = () => (
<EuiFieldNumber
min={1}
max={24}
required={true}
value={windowSize}
onChange={onWindowSizeChange}
/>
);

const WindowChoice = time === timeUnits[0].value ? MinutesBox : HoursBox;

const isChanged =
isEnabled !== metricSettingsMap[metric].isEnabled ||
topNSize !== metricSettingsMap[metric].currTopN ||
windowSize !== metricSettingsMap[metric].currWindowSize ||
time !== metricSettingsMap[metric].currTimeUnit;

const isValid = (() => {
const nVal = parseInt(topNSize, 10);
if (nVal < 1 || nVal > 100) return false;
if (time === timeUnits[0].value) return true;
const windowVal = parseInt(windowSize, 10);
return windowVal >= 1 && windowVal <= 24;
})();

const textPadding = { lineHeight: '22px', padding: '5px 0px' };
const formRowPadding = { padding: '0px 0px 20px' };
const enabledSymb = <EuiHealth color="primary">Enabled</EuiHealth>;
const disabledSymb = <EuiHealth color="default">Disabled</EuiHealth>;

return (
<div>
<EuiFlexGroup>
<EuiFlexItem grow={6}>
<EuiPanel paddingSize="m">
<EuiForm>
<EuiFlexItem>
<EuiTitle size="s">
<EuiText size="s">
<h2>Top n queries monitoring configuration settings</h2>
</EuiText>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGrid columns={2} gutterSize="s" style={{ padding: '15px 0px' }}>
<EuiFlexItem>
<EuiText size="xs">
<h3>Metric Type</h3>
</EuiText>
<EuiText size="xs" style={textPadding}>
Specify the metric type to set settings for.
</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormRow style={formRowPadding}>
<EuiSelect
id="metricType"
required={true}
options={metricTypes}
value={metric}
onChange={onMetricChange}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem>
<EuiText size="xs">
<h3>Enabled</h3>
</EuiText>
<EuiText size="xs" style={textPadding}>
{`Enable/disable top N query monitoring by ${metric}.`}
</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormRow style={formRowPadding}>
<EuiFlexItem>
<EuiSpacer size="s" />
<EuiSwitch label="" checked={isEnabled} onChange={onEnabledChange} />
</EuiFlexItem>
</EuiFormRow>
</EuiFlexItem>
{isEnabled ? (
<>
<EuiFlexItem>
<EuiText size="xs">
<h3>Value of N (count)</h3>
</EuiText>
<EuiText size="xs" style={textPadding}>
Specify the value of N. N is the number of queries to be collected within
the window size.
</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormRow
label={`${metric}.top_n_size`}
helpText="Max allowed limit 100."
style={formRowPadding}
>
<EuiFieldNumber
min={1}
max={100}
required={isEnabled}
value={topNSize}
onChange={onTopNSizeChange}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem>
<EuiText size="xs">
<h3>Window size</h3>
</EuiText>
<EuiText size="xs" style={textPadding}>
The duration during which the Top N queries are collected.
</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormRow
label={`${metric}.window_size`}
helpText="Max allowed limit 24 hours."
style={{ padding: '15px 0px 5px' }}
>
<EuiFlexGroup>
<EuiFlexItem style={{ flexDirection: 'row' }}>
<WindowChoice />
</EuiFlexItem>
<EuiFlexItem>
<EuiSelect
id="timeUnit"
required={isEnabled}
options={timeUnits}
value={time}
onChange={onTimeChange}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFormRow>
</EuiFlexItem>
</>
) : null}
</EuiFlexGrid>
</EuiFlexItem>
</EuiForm>
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem grow={2}>
<EuiPanel paddingSize="m" grow={false}>
<EuiFlexItem>
<EuiTitle size="s">
<EuiText size="s">
<h2>Statuses for configuration metrics</h2>
</EuiText>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGroup>
<EuiFlexItem>
<EuiText size="m">Latency</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiSpacer size="xs" />
{latencySettings.isEnabled ? enabledSymb : disabledSymb}
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup>
<EuiFlexItem>
<EuiText size="m">CPU Usage</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiSpacer size="xs" />
{cpuSettings.isEnabled ? enabledSymb : disabledSymb}
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup>
<EuiFlexItem>
<EuiText size="m">Memory</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiSpacer size="xs" />
{memorySettings.isEnabled ? enabledSymb : disabledSymb}
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
{isChanged && isValid ? (
<EuiBottomBar>
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd">
<EuiFlexItem grow={false}>
<EuiButtonEmpty color="ghost" size="s" iconType="cross" onClick={newOrReset}>
Cancel
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
color="primary"
fill
size="s"
iconType="check"
onClick={() => {
configInfo(false, isEnabled, metric, topNSize, windowSize, time);
return history.push(QUERY_INSIGHTS);
}}
>
Save
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiBottomBar>
) : null}
</div>
);
};

// eslint-disable-next-line import/no-default-export
export default Configuration;
Loading

0 comments on commit afe9a0c

Please sign in to comment.