Skip to content

Commit 5bfd2bc

Browse files
Add configuration section for exporter and delete_after (#53) (#73)
* Add configuration section for exporter and delete_after * rebase from main and refactor functions * exporter configruation pannels * rebase main to pick up MDS changes --------- (cherry picked from commit 9f955a0) Signed-off-by: Chenyang Ji <[email protected]> Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent c58cc2b commit 5bfd2bc

13 files changed

+741
-49
lines changed

cypress/e2e/2_query_details.cy.js

+3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ describe('Top Queries Details Page', () => {
2828
// waiting for the query insights queue to drain
2929
cy.wait(10000);
3030
cy.navigateToOverview();
31+
cy.get('.euiTableRow').first().find('button').first().trigger('mouseover');
32+
cy.wait(1000);
3133
cy.get('.euiTableRow').first().find('button').first().click(); // Navigate to details
34+
cy.wait(1000);
3235
});
3336

3437
it('should display correct details on the query details page', () => {

cypress/e2e/3_configurations.cy.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ describe('Query Insights Configurations Page', () => {
3636
cy.contains('button', 'Top N queries').should('be.visible');
3737
cy.contains('button', 'Configuration').should('have.class', 'euiTab-isSelected');
3838
// Validate the panels
39-
cy.get('.euiPanel').should('have.length', 4); // 4 panels: Settings, Status, Group Settings, Group Status
39+
// 6 panels: Settings, Status, Group Settings, Group Status, Delete After Settings, Delete After Status
40+
cy.get('.euiPanel').should('have.length', 6);
4041
});
4142

4243
/**

cypress/e2e/4_group_details.cy.js

+3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ describe('Query Group Details Page', () => {
2323
// waiting for the query insights queue to drain
2424
cy.wait(10000);
2525
cy.navigateToOverview();
26+
cy.get('.euiTableRow').first().find('button').first().trigger('mouseover');
27+
cy.wait(1000);
2628
cy.get('.euiTableRow').first().find('button').first().click(); // Navigate to details
29+
cy.wait(1000);
2730
});
2831

2932
it('should display correct details on the group details page', () => {

public/components/DataSourcePicker.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { AppMountParameters, CoreStart } from '../../../../src/core/public';
1313
import { QueryInsightsDashboardsPluginStartDependencies } from '../types';
1414

1515
export interface DataSourceMenuProps {
16-
dataSourceManagement: DataSourceManagementPluginSetup;
16+
dataSourceManagement?: DataSourceManagementPluginSetup;
1717
depsStart: QueryInsightsDashboardsPluginStartDependencies;
1818
coreStart: CoreStart;
1919
params: AppMountParameters;

public/pages/Configuration/Configuration.test.tsx

+14-6
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ const groupBySettings = {
4040
groupBy: 'SIMILARITY',
4141
};
4242

43+
const dataRetentionSettings = {
44+
exporterType: 'local_index',
45+
deleteAfterDays: '179',
46+
};
47+
4348
const dataSourceMenuMock = jest.fn(() => <div>Mock DataSourceMenu</div>);
4449

4550
const dataSourceManagementMock = {
@@ -62,6 +67,7 @@ const renderConfiguration = (overrides = {}) =>
6267
memorySettings={defaultMemorySettings}
6368
groupBySettings={groupBySettings}
6469
configInfo={mockConfigInfo}
70+
dataRetentionSettings={dataRetentionSettings}
6571
core={mockCoreStart}
6672
depsStart={{ navigation: {} }}
6773
params={{} as any}
@@ -72,7 +78,7 @@ const renderConfiguration = (overrides = {}) =>
7278
);
7379

7480
const getWindowSizeConfigurations = () => screen.getAllByRole('combobox');
75-
const getTopNSizeConfiguration = () => screen.getByRole('spinbutton');
81+
const getTopNSizeConfiguration = () => screen.getAllByRole('spinbutton');
7682
const getEnableToggle = () => screen.getByRole('switch');
7783

7884
describe('Configuration Component', () => {
@@ -108,15 +114,15 @@ describe('Configuration Component', () => {
108114

109115
it('validates topNSize and windowSize inputs and disables Save button for invalid input', () => {
110116
renderConfiguration();
111-
fireEvent.change(getTopNSizeConfiguration(), { target: { value: '101' } });
117+
fireEvent.change(getTopNSizeConfiguration()[0], { target: { value: '101' } });
112118
expect(screen.queryByText('Save')).not.toBeInTheDocument();
113119
fireEvent.change(getWindowSizeConfigurations()[1], { target: { value: '999' } });
114120
expect(screen.queryByText('Save')).not.toBeInTheDocument();
115121
});
116122

117123
it('calls configInfo and navigates on Save button click', async () => {
118124
renderConfiguration();
119-
fireEvent.change(getTopNSizeConfiguration(), { target: { value: '7' } });
125+
fireEvent.change(getTopNSizeConfiguration()[0], { target: { value: '7' } });
120126
fireEvent.click(screen.getByText('Save'));
121127
await waitFor(() => {
122128
expect(mockConfigInfo).toHaveBeenCalledWith(
@@ -126,15 +132,17 @@ describe('Configuration Component', () => {
126132
'7',
127133
'10',
128134
'MINUTES',
129-
'SIMILARITY'
135+
'local_index',
136+
'SIMILARITY',
137+
'179'
130138
);
131139
});
132140
});
133141

134142
it('resets state on Cancel button click', async () => {
135143
renderConfiguration();
136-
fireEvent.change(getTopNSizeConfiguration(), { target: { value: '7' } });
144+
fireEvent.change(getTopNSizeConfiguration()[0], { target: { value: '7' } });
137145
fireEvent.click(screen.getByText('Cancel'));
138-
expect(getTopNSizeConfiguration()).toHaveValue(5); // Resets to initial value
146+
expect(getTopNSizeConfiguration()[0]).toHaveValue(5); // Resets to initial value
139147
});
140148
});

public/pages/Configuration/Configuration.tsx

+132-6
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,15 @@ import {
3030
MetricSettings,
3131
GroupBySettings,
3232
DataSourceContext,
33+
DataRetentionSettings,
3334
} from '../TopNQueries/TopNQueries';
3435
import {
3536
METRIC_TYPES_TEXT,
3637
TIME_UNITS_TEXT,
3738
MINUTES_OPTIONS,
3839
GROUP_BY_OPTIONS,
40+
EXPORTER_TYPES_LIST,
41+
EXPORTER_TYPE,
3942
} from '../Utils/Constants';
4043
import { QueryInsightsDataSourceMenu } from '../../components/DataSourcePicker';
4144
import { QueryInsightsDashboardsPluginStartDependencies } from '../../types';
@@ -45,6 +48,7 @@ const Configuration = ({
4548
cpuSettings,
4649
memorySettings,
4750
groupBySettings,
51+
dataRetentionSettings,
4852
configInfo,
4953
core,
5054
depsStart,
@@ -55,6 +59,7 @@ const Configuration = ({
5559
cpuSettings: MetricSettings;
5660
memorySettings: MetricSettings;
5761
groupBySettings: GroupBySettings;
62+
dataRetentionSettings: DataRetentionSettings;
5863
configInfo: any;
5964
core: CoreStart;
6065
params: AppMountParameters;
@@ -71,23 +76,29 @@ const Configuration = ({
7176
const [time, setTime] = useState(latencySettings.currTimeUnit);
7277
const [groupBy, setGroupBy] = useState(groupBySettings.groupBy);
7378
const { dataSource, setDataSource } = useContext(DataSourceContext)!;
79+
const [deleteAfterDays, setDeleteAfterDays] = useState(dataRetentionSettings.deleteAfterDays);
80+
const [exporterType, setExporterTypeType] = useState(dataRetentionSettings.exporterType);
7481

7582
const [metricSettingsMap, setMetricSettingsMap] = useState({
7683
latency: latencySettings,
7784
cpu: cpuSettings,
7885
memory: memorySettings,
86+
});
87+
88+
const [groupBySettingMap, setGroupBySettingMap] = useState({
7989
groupBy: groupBySettings,
8090
});
8191

92+
const [dataRetentionSettingMap, setDataRetentionSettingMap] = useState({
93+
dataRetention: dataRetentionSettings,
94+
});
95+
8296
useEffect(() => {
8397
setMetricSettingsMap({
8498
latency: latencySettings,
8599
cpu: cpuSettings,
86100
memory: memorySettings,
87-
groupBy: groupBySettings,
88101
});
89-
90-
setGroupBy(groupBySettings.groupBy);
91102
}, [latencySettings, cpuSettings, memorySettings, groupBySettings]);
92103

93104
const newOrReset = useCallback(() => {
@@ -96,12 +107,28 @@ const Configuration = ({
96107
setWindowSize(currMetric.currWindowSize);
97108
setTime(currMetric.currTimeUnit);
98109
setIsEnabled(currMetric.isEnabled);
110+
// setExporterTypeType(currMetric.exporterType);
99111
}, [metric, metricSettingsMap]);
100112

101113
useEffect(() => {
102114
newOrReset();
103115
}, [newOrReset, metricSettingsMap]);
104116

117+
useEffect(() => {
118+
setGroupBySettingMap({
119+
groupBy: groupBySettings,
120+
});
121+
setGroupBy(groupBySettings.groupBy);
122+
}, [groupBySettings]);
123+
124+
useEffect(() => {
125+
setDataRetentionSettingMap({
126+
dataRetention: dataRetentionSettings,
127+
});
128+
setDeleteAfterDays(dataRetentionSettings.deleteAfterDays);
129+
setExporterTypeType(dataRetentionSettings.exporterType);
130+
}, [dataRetentionSettings]);
131+
105132
useEffect(() => {
106133
core.chrome.setBreadcrumbs([
107134
{
@@ -137,10 +164,18 @@ const Configuration = ({
137164
setTime(e.target.value);
138165
};
139166

140-
const onGroupByChange = (e: any) => {
167+
const onExporterTypeChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
168+
setExporterTypeType(e.target.value);
169+
};
170+
171+
const onGroupByChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
141172
setGroupBy(e.target.value);
142173
};
143174

175+
const onDeleteAfterDaysChange = (e: React.ChangeEvent<HTMLInputElement>) => {
176+
setDeleteAfterDays(e.target.value);
177+
};
178+
144179
const MinutesBox = () => (
145180
<EuiSelect
146181
id="minutes"
@@ -168,7 +203,9 @@ const Configuration = ({
168203
topNSize !== metricSettingsMap[metric].currTopN ||
169204
windowSize !== metricSettingsMap[metric].currWindowSize ||
170205
time !== metricSettingsMap[metric].currTimeUnit ||
171-
groupBy !== metricSettingsMap.groupBy.groupBy;
206+
groupBy !== groupBySettingMap.groupBy.groupBy ||
207+
exporterType !== dataRetentionSettingMap.dataRetention.exporterType ||
208+
deleteAfterDays !== dataRetentionSettingMap.dataRetention.deleteAfterDays;
172209

173210
const isValid = (() => {
174211
const nVal = parseInt(topNSize, 10);
@@ -415,6 +452,85 @@ const Configuration = ({
415452
</EuiPanel>
416453
</EuiFlexItem>
417454
</EuiFlexGroup>
455+
<EuiFlexGroup>
456+
<EuiFlexItem grow={6}>
457+
<EuiPanel paddingSize="m">
458+
<EuiForm>
459+
<EuiFlexItem>
460+
<EuiTitle size="s">
461+
<EuiText size="s">
462+
<h2>Query Insights export and data retention settings</h2>
463+
</EuiText>
464+
</EuiTitle>
465+
</EuiFlexItem>
466+
<EuiFlexItem>
467+
<EuiFlexGrid columns={2} gutterSize="s" style={{ padding: '15px 0px' }}>
468+
<EuiFlexItem>
469+
<EuiText size="xs">
470+
<h3>Exporter</h3>
471+
</EuiText>
472+
<EuiText size="xs" style={textPadding}>
473+
Configure a sink for exporting Query Insights data.
474+
</EuiText>
475+
</EuiFlexItem>
476+
<EuiFlexItem>
477+
<EuiFormRow style={formRowPadding}>
478+
<EuiSelect
479+
id="exporterType"
480+
required={true}
481+
options={EXPORTER_TYPES_LIST}
482+
value={exporterType}
483+
onChange={onExporterTypeChange}
484+
/>
485+
</EuiFormRow>
486+
</EuiFlexItem>
487+
<EuiFlexItem>
488+
<EuiText size="xs">
489+
<h3>Delete After (days)</h3>
490+
</EuiText>
491+
<EuiText size="xs" style={textPadding}>
492+
Number of days to retain Query Insights data.
493+
</EuiText>
494+
</EuiFlexItem>
495+
<EuiFlexItem>
496+
<EuiFormRow style={formRowPadding}>
497+
<EuiFieldNumber
498+
disabled={exporterType !== EXPORTER_TYPE.localIndex}
499+
min={1}
500+
max={180}
501+
value={exporterType !== EXPORTER_TYPE.localIndex ? '' : deleteAfterDays}
502+
onChange={onDeleteAfterDaysChange}
503+
/>
504+
</EuiFormRow>
505+
</EuiFlexItem>
506+
</EuiFlexGrid>
507+
</EuiFlexItem>
508+
</EuiForm>
509+
</EuiPanel>
510+
</EuiFlexItem>
511+
<EuiFlexItem grow={2}>
512+
<EuiPanel paddingSize="m" grow={false}>
513+
<EuiFlexItem>
514+
<EuiTitle size="s">
515+
<EuiText size="s">
516+
<h2>Statuses for data retention</h2>
517+
</EuiText>
518+
</EuiTitle>
519+
</EuiFlexItem>
520+
<EuiFlexItem>
521+
<EuiFlexGroup>
522+
<EuiFlexItem>
523+
<EuiText size="m">Exporter</EuiText>
524+
</EuiFlexItem>
525+
<EuiFlexItem>
526+
<EuiSpacer size="xs" />
527+
{exporterType === EXPORTER_TYPE.localIndex ? enabledSymb : disabledSymb}
528+
</EuiFlexItem>
529+
</EuiFlexGroup>
530+
</EuiFlexItem>
531+
</EuiPanel>
532+
</EuiFlexItem>
533+
</EuiFlexGroup>
418534
{isChanged && isValid ? (
419535
<EuiBottomBar>
420536
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd">
@@ -431,7 +547,17 @@ const Configuration = ({
431547
size="s"
432548
iconType="check"
433549
onClick={() => {
434-
configInfo(false, isEnabled, metric, topNSize, windowSize, time, groupBy);
550+
configInfo(
551+
false,
552+
isEnabled,
553+
metric,
554+
topNSize,
555+
windowSize,
556+
time,
557+
exporterType,
558+
groupBy,
559+
deleteAfterDays
560+
);
435561
return history.push(QUERY_INSIGHTS);
436562
}}
437563
>

0 commit comments

Comments
 (0)