Skip to content

Commit

Permalink
Add configuration section for exporter and delete_after (#53)
Browse files Browse the repository at this point in the history
* Add configuration section for exporter and delete_after

Signed-off-by: Chenyang Ji <[email protected]>

* rebase from main and refactor functions

Signed-off-by: Chenyang Ji <[email protected]>

* exporter configruation pannels

Signed-off-by: Chenyang Ji <[email protected]>

* rebase main to pick up MDS changes

Signed-off-by: Chenyang Ji <[email protected]>

---------

Signed-off-by: Chenyang Ji <[email protected]>
(cherry picked from commit 9f955a0)
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
github-actions[bot] committed Jan 27, 2025
1 parent c58cc2b commit e06e08a
Show file tree
Hide file tree
Showing 13 changed files with 741 additions and 49 deletions.
3 changes: 3 additions & 0 deletions cypress/e2e/2_query_details.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ describe('Top Queries Details Page', () => {
// waiting for the query insights queue to drain
cy.wait(10000);
cy.navigateToOverview();
cy.get('.euiTableRow').first().find('button').first().trigger('mouseover');
cy.wait(1000);
cy.get('.euiTableRow').first().find('button').first().click(); // Navigate to details
cy.wait(1000);
});

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

Check warning on line 37 in cypress/e2e/2_query_details.cy.js

View workflow job for this annotation

GitHub Actions / Run lint

Test has no assertions
Expand Down
3 changes: 2 additions & 1 deletion cypress/e2e/3_configurations.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ describe('Query Insights Configurations Page', () => {
cy.contains('button', 'Top N queries').should('be.visible');
cy.contains('button', 'Configuration').should('have.class', 'euiTab-isSelected');
// Validate the panels
cy.get('.euiPanel').should('have.length', 4); // 4 panels: Settings, Status, Group Settings, Group Status
// 6 panels: Settings, Status, Group Settings, Group Status, Delete After Settings, Delete After Status
cy.get('.euiPanel').should('have.length', 6);
});

/**
Expand Down
3 changes: 3 additions & 0 deletions cypress/e2e/4_group_details.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ describe('Query Group Details Page', () => {
// waiting for the query insights queue to drain
cy.wait(10000);
cy.navigateToOverview();
cy.get('.euiTableRow').first().find('button').first().trigger('mouseover');
cy.wait(1000);
cy.get('.euiTableRow').first().find('button').first().click(); // Navigate to details
cy.wait(1000);
});

it('should display correct details on the group details page', () => {
Expand Down
2 changes: 1 addition & 1 deletion public/components/DataSourcePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { AppMountParameters, CoreStart } from '../../../../src/core/public';
import { QueryInsightsDashboardsPluginStartDependencies } from '../types';

export interface DataSourceMenuProps {
dataSourceManagement: DataSourceManagementPluginSetup;
dataSourceManagement?: DataSourceManagementPluginSetup;
depsStart: QueryInsightsDashboardsPluginStartDependencies;
coreStart: CoreStart;
params: AppMountParameters;
Expand Down
20 changes: 14 additions & 6 deletions public/pages/Configuration/Configuration.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ const groupBySettings = {
groupBy: 'SIMILARITY',
};

const dataRetentionSettings = {
exporterType: 'local_index',
deleteAfterDays: '179',
};

const dataSourceMenuMock = jest.fn(() => <div>Mock DataSourceMenu</div>);

const dataSourceManagementMock = {
Expand All @@ -62,6 +67,7 @@ const renderConfiguration = (overrides = {}) =>
memorySettings={defaultMemorySettings}
groupBySettings={groupBySettings}
configInfo={mockConfigInfo}
dataRetentionSettings={dataRetentionSettings}
core={mockCoreStart}
depsStart={{ navigation: {} }}
params={{} as any}
Expand All @@ -72,7 +78,7 @@ const renderConfiguration = (overrides = {}) =>
);

const getWindowSizeConfigurations = () => screen.getAllByRole('combobox');
const getTopNSizeConfiguration = () => screen.getByRole('spinbutton');
const getTopNSizeConfiguration = () => screen.getAllByRole('spinbutton');
const getEnableToggle = () => screen.getByRole('switch');

describe('Configuration Component', () => {
Expand Down Expand Up @@ -108,15 +114,15 @@ describe('Configuration Component', () => {

it('validates topNSize and windowSize inputs and disables Save button for invalid input', () => {
renderConfiguration();
fireEvent.change(getTopNSizeConfiguration(), { target: { value: '101' } });
fireEvent.change(getTopNSizeConfiguration()[0], { target: { value: '101' } });
expect(screen.queryByText('Save')).not.toBeInTheDocument();
fireEvent.change(getWindowSizeConfigurations()[1], { target: { value: '999' } });
expect(screen.queryByText('Save')).not.toBeInTheDocument();
});

it('calls configInfo and navigates on Save button click', async () => {
renderConfiguration();
fireEvent.change(getTopNSizeConfiguration(), { target: { value: '7' } });
fireEvent.change(getTopNSizeConfiguration()[0], { target: { value: '7' } });
fireEvent.click(screen.getByText('Save'));
await waitFor(() => {
expect(mockConfigInfo).toHaveBeenCalledWith(
Expand All @@ -126,15 +132,17 @@ describe('Configuration Component', () => {
'7',
'10',
'MINUTES',
'SIMILARITY'
'local_index',
'SIMILARITY',
'179'
);
});
});

it('resets state on Cancel button click', async () => {
renderConfiguration();
fireEvent.change(getTopNSizeConfiguration(), { target: { value: '7' } });
fireEvent.change(getTopNSizeConfiguration()[0], { target: { value: '7' } });
fireEvent.click(screen.getByText('Cancel'));
expect(getTopNSizeConfiguration()).toHaveValue(5); // Resets to initial value
expect(getTopNSizeConfiguration()[0]).toHaveValue(5); // Resets to initial value
});
});
138 changes: 132 additions & 6 deletions public/pages/Configuration/Configuration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@ import {
MetricSettings,
GroupBySettings,
DataSourceContext,
DataRetentionSettings,
} from '../TopNQueries/TopNQueries';
import {
METRIC_TYPES_TEXT,
TIME_UNITS_TEXT,
MINUTES_OPTIONS,
GROUP_BY_OPTIONS,
EXPORTER_TYPES_LIST,
EXPORTER_TYPE,
} from '../Utils/Constants';
import { QueryInsightsDataSourceMenu } from '../../components/DataSourcePicker';
import { QueryInsightsDashboardsPluginStartDependencies } from '../../types';
Expand All @@ -45,6 +48,7 @@ const Configuration = ({
cpuSettings,
memorySettings,
groupBySettings,
dataRetentionSettings,
configInfo,
core,
depsStart,
Expand All @@ -55,6 +59,7 @@ const Configuration = ({
cpuSettings: MetricSettings;
memorySettings: MetricSettings;
groupBySettings: GroupBySettings;
dataRetentionSettings: DataRetentionSettings;
configInfo: any;
core: CoreStart;
params: AppMountParameters;
Expand All @@ -71,23 +76,29 @@ const Configuration = ({
const [time, setTime] = useState(latencySettings.currTimeUnit);
const [groupBy, setGroupBy] = useState(groupBySettings.groupBy);
const { dataSource, setDataSource } = useContext(DataSourceContext)!;
const [deleteAfterDays, setDeleteAfterDays] = useState(dataRetentionSettings.deleteAfterDays);
const [exporterType, setExporterTypeType] = useState(dataRetentionSettings.exporterType);

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

const [groupBySettingMap, setGroupBySettingMap] = useState({
groupBy: groupBySettings,
});

const [dataRetentionSettingMap, setDataRetentionSettingMap] = useState({
dataRetention: dataRetentionSettings,
});

useEffect(() => {
setMetricSettingsMap({
latency: latencySettings,
cpu: cpuSettings,
memory: memorySettings,
groupBy: groupBySettings,
});

setGroupBy(groupBySettings.groupBy);
}, [latencySettings, cpuSettings, memorySettings, groupBySettings]);

const newOrReset = useCallback(() => {
Expand All @@ -96,12 +107,28 @@ const Configuration = ({
setWindowSize(currMetric.currWindowSize);
setTime(currMetric.currTimeUnit);
setIsEnabled(currMetric.isEnabled);
// setExporterTypeType(currMetric.exporterType);
}, [metric, metricSettingsMap]);

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

useEffect(() => {
setGroupBySettingMap({
groupBy: groupBySettings,
});
setGroupBy(groupBySettings.groupBy);
}, [groupBySettings]);

useEffect(() => {
setDataRetentionSettingMap({
dataRetention: dataRetentionSettings,
});
setDeleteAfterDays(dataRetentionSettings.deleteAfterDays);
setExporterTypeType(dataRetentionSettings.exporterType);
}, [dataRetentionSettings]);

useEffect(() => {
core.chrome.setBreadcrumbs([
{
Expand Down Expand Up @@ -137,10 +164,18 @@ const Configuration = ({
setTime(e.target.value);
};

const onGroupByChange = (e: any) => {
const onExporterTypeChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setExporterTypeType(e.target.value);
};

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

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

const MinutesBox = () => (
<EuiSelect
id="minutes"
Expand Down Expand Up @@ -168,7 +203,9 @@ const Configuration = ({
topNSize !== metricSettingsMap[metric].currTopN ||
windowSize !== metricSettingsMap[metric].currWindowSize ||
time !== metricSettingsMap[metric].currTimeUnit ||
groupBy !== metricSettingsMap.groupBy.groupBy;
groupBy !== groupBySettingMap.groupBy.groupBy ||
exporterType !== dataRetentionSettingMap.dataRetention.exporterType ||
deleteAfterDays !== dataRetentionSettingMap.dataRetention.deleteAfterDays;

const isValid = (() => {
const nVal = parseInt(topNSize, 10);
Expand Down Expand Up @@ -415,6 +452,85 @@ const Configuration = ({
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup>
<EuiFlexItem grow={6}>
<EuiPanel paddingSize="m">
<EuiForm>
<EuiFlexItem>
<EuiTitle size="s">
<EuiText size="s">
<h2>Query Insights export and data retention settings</h2>
</EuiText>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGrid columns={2} gutterSize="s" style={{ padding: '15px 0px' }}>
<EuiFlexItem>
<EuiText size="xs">
<h3>Exporter</h3>
</EuiText>
<EuiText size="xs" style={textPadding}>
Configure a sink for exporting Query Insights data.
</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormRow style={formRowPadding}>
<EuiSelect
id="exporterType"
required={true}
options={EXPORTER_TYPES_LIST}
value={exporterType}
onChange={onExporterTypeChange}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem>
<EuiText size="xs">
<h3>Delete After (days)</h3>
</EuiText>
<EuiText size="xs" style={textPadding}>
Number of days to retain Query Insights data.
</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormRow style={formRowPadding}>
<EuiFieldNumber
disabled={exporterType !== EXPORTER_TYPE.localIndex}
min={1}
max={180}
value={exporterType !== EXPORTER_TYPE.localIndex ? '' : deleteAfterDays}
onChange={onDeleteAfterDaysChange}
/>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGrid>
</EuiFlexItem>
</EuiForm>
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem grow={2}>
<EuiPanel paddingSize="m" grow={false}>
<EuiFlexItem>
<EuiTitle size="s">
<EuiText size="s">
<h2>Statuses for data retention</h2>
</EuiText>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGroup>
<EuiFlexItem>
<EuiText size="m">Exporter</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiSpacer size="xs" />
{exporterType === EXPORTER_TYPE.localIndex ? enabledSymb : disabledSymb}
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
{isChanged && isValid ? (
<EuiBottomBar>
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd">
Expand All @@ -431,7 +547,17 @@ const Configuration = ({
size="s"
iconType="check"
onClick={() => {
configInfo(false, isEnabled, metric, topNSize, windowSize, time, groupBy);
configInfo(
false,
isEnabled,
metric,
topNSize,
windowSize,
time,
exporterType,
groupBy,
deleteAfterDays
);
return history.push(QUERY_INSIGHTS);
}}
>
Expand Down
Loading

0 comments on commit e06e08a

Please sign in to comment.