Skip to content

Commit

Permalink
[SLOs] Unified Search (elastic#174054)
Browse files Browse the repository at this point in the history
## Summary

Fixes elastic#173601

Implement Unified Search in SLO List view 

1. SLO title has been removed to make it more consistent with other
kibana apps
2. Feedback button is moved up 
3. Auto refresh is removed

<img width="1720" alt="image"
src="https://github.com/elastic/kibana/assets/3505601/0ff6fd83-98ac-4737-bf4f-aa087739f110">


<img width="1728" alt="image"
src="https://github.com/elastic/kibana/assets/3505601/aa71e2e7-3bc8-4be7-afb3-f4b7efffc953">

Filters

<img width="1727" alt="image"
src="https://github.com/elastic/kibana/assets/3505601/d3bbf3d3-d2b3-4574-ae7f-bb8258016930">

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
shahzad31 and kibanamachine authored Jan 23, 2024
1 parent 615c16e commit f1057ca
Show file tree
Hide file tree
Showing 32 changed files with 479 additions and 379 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { I18nProvider } from '@kbn/i18n-react';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/public';
import { buildExistsFilter } from '@kbn/es-query';
import { EuiComboBox } from '@elastic/eui';
import { EuiButton, EuiComboBox } from '@elastic/eui';
import { SearchBar, SearchBarProps } from '../search_bar';
import { setIndexPatterns } from '../services';

Expand Down Expand Up @@ -695,4 +695,20 @@ storiesOf('SearchBar', module)
},
submitButtonStyle: 'full',
})
)

.add('with renderQueryInputAppend prop', () =>
wrapSearchBarInContext({
dataViewPickerComponentProps: {
currentDataViewId: '1234',
trigger: {
'data-test-subj': 'dataView-switch-link',
label: 'logstash-*',
title: 'logstash-*',
},
onChangeDataView: action('onChangeDataView'),
},
submitButtonStyle: 'full',
renderQueryInputAppend: () => <EuiButton onClick={() => {}}>Append</EuiButton>,
})
);
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export interface QueryBarMenuProps extends WithCloseFilterEditorConfirmModalProp
buttonProps?: Partial<EuiButtonIconProps>;
isDisabled?: boolean;
suggestionsAbstraction?: SuggestionsAbstraction;
renderQueryInputAppend?: () => React.ReactNode;
}

function QueryBarMenuComponent({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ export interface QueryBarTopRowProps<QT extends Query | AggregateQuery = Query>
onTextLangQuerySubmit: (query?: Query | AggregateQuery) => void;
onTextLangQueryChange: (query: AggregateQuery) => void;
submitOnBlur?: boolean;
renderQueryInputAppend?: () => React.ReactNode;
}

export const SharingMetaFields = React.memo(function SharingMetaFields({
Expand Down Expand Up @@ -702,6 +703,7 @@ export const QueryBarTopRow = React.memo(
? renderTextLangEditor()
: null}
</EuiFlexItem>
{props.renderQueryInputAppend?.()}
{shouldShowDatePickerAsBadge() && props.filterBar}
{renderUpdateButton()}
</EuiFlexGroup>
Expand Down
4 changes: 4 additions & 0 deletions src/plugins/unified_search/public/search_bar/search_bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ export interface SearchBarOwnProps<QT extends AggregateQuery | Query = Query> {
isDisabled?: boolean;

submitOnBlur?: boolean;

renderQueryInputAppend?: () => React.ReactNode;
}

export type SearchBarProps<QT extends Query | AggregateQuery = Query> = SearchBarOwnProps<QT> &
Expand Down Expand Up @@ -524,6 +526,7 @@ class SearchBarUI<QT extends (Query | AggregateQuery) | Query = Query> extends C
: undefined
}
suggestionsAbstraction={this.props.suggestionsAbstraction}
renderQueryInputAppend={this.props.renderQueryInputAppend}
/>
) : undefined;

Expand Down Expand Up @@ -610,6 +613,7 @@ class SearchBarUI<QT extends (Query | AggregateQuery) | Query = Query> extends C
onTextLangQueryChange={this.onTextLangQueryChange}
submitOnBlur={this.props.submitOnBlur}
suggestionsAbstraction={this.props.suggestionsAbstraction}
renderQueryInputAppend={this.props.renderQueryInputAppend}
/>
</div>
);
Expand Down
1 change: 1 addition & 0 deletions x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ const sortBySchema = t.union([

const findSLOParamsSchema = t.partial({
query: t.partial({
filters: t.string,
kqlQuery: t.string,
page: t.string,
perPage: t.string,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { EuiButton, EuiCallOut } from '@elastic/eui';
import { EuiButton, EuiCallOut, EuiSpacer } from '@elastic/eui';
import React from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
Expand All @@ -25,37 +25,40 @@ export function SloOutdatedCallout() {
const { isLoading, data } = useFetchSloDefinitions({ includeOutdatedOnly: true });
if (!isLoading && data && data.total > 0) {
return (
<EuiCallOut
color="warning"
iconType="warning"
title={i18n.translate('xpack.observability.slo.outdatedSloCallout.title', {
defaultMessage: '{total} Outdated SLOs Detected',
values: {
total: data.total,
},
})}
>
<p>
<FormattedMessage
id="xpack.observability.slo.outdatedSloCallout.message"
defaultMessage="We've noticed that you have {total} outdated SLO definitions, these SLOs will not be running or alerting until you've reset them. Please click the button below to review the SLO definitions; you can choose to either reset the SLO definition or remove it."
values={{ total: data.total }}
/>
</p>
<p>
<EuiButton
color="warning"
data-test-subj="o11ySloOutdatedCalloutViewOutdatedSloDefinitionsButton"
fill
onClick={handleClick}
>
<>
<EuiCallOut
color="warning"
iconType="warning"
title={i18n.translate('xpack.observability.slo.outdatedSloCallout.title', {
defaultMessage: '{total} Outdated SLOs Detected',
values: {
total: data.total,
},
})}
>
<p>
<FormattedMessage
id="xpack.observability.outdatedSloCallout.buttonLabel"
defaultMessage="Review Outdated SLO Definitions"
id="xpack.observability.slo.outdatedSloCallout.message"
defaultMessage="We've noticed that you have {total} outdated SLO definitions, these SLOs will not be running or alerting until you've reset them. Please click the button below to review the SLO definitions; you can choose to either reset the SLO definition or remove it."
values={{ total: data.total }}
/>
</EuiButton>
</p>
</EuiCallOut>
</p>
<p>
<EuiButton
color="warning"
data-test-subj="o11ySloOutdatedCalloutViewOutdatedSloDefinitionsButton"
fill
onClick={handleClick}
>
<FormattedMessage
id="xpack.observability.outdatedSloCallout.buttonLabel"
defaultMessage="Review Outdated SLO Definitions"
/>
</EuiButton>
</p>
</EuiCallOut>
<EuiSpacer size="m" />
</>
);
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ interface SloListFilter {
perPage: number;
sortBy: string;
sortDirection: string;
filters: string;
lastRefresh?: number;
}

export const sloKeys = {
Expand Down
61 changes: 38 additions & 23 deletions x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
import { i18n } from '@kbn/i18n';
import { FindSLOResponse } from '@kbn/slo-schema';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useState } from 'react';
import { DEFAULT_SLO_PAGE_SIZE } from '../../../common/slo/constants';
import { SLO_LONG_REFETCH_INTERVAL, SLO_SHORT_REFETCH_INTERVAL } from '../../constants';
import { useMemo } from 'react';
import { buildQueryFromFilters, Filter } from '@kbn/es-query';
import { useCreateDataView } from '../use_create_data_view';
import {
DEFAULT_SLO_PAGE_SIZE,
SLO_SUMMARY_DESTINATION_INDEX_NAME,
} from '../../../common/slo/constants';

import { useKibana } from '../../utils/kibana_react';
import { sloKeys } from './query_key_factory';
Expand All @@ -20,8 +24,9 @@ interface SLOListParams {
page?: number;
sortBy?: string;
sortDirection?: 'asc' | 'desc';
shouldRefetch?: boolean;
perPage?: number;
filters?: Filter[];
lastRefresh?: number;
}

export interface UseFetchSloListResponse {
Expand All @@ -38,37 +43,57 @@ export function useFetchSloList({
page = 1,
sortBy = 'status',
sortDirection = 'desc',
shouldRefetch,
perPage = DEFAULT_SLO_PAGE_SIZE,
filters: filterDSL = [],
lastRefresh,
}: SLOListParams = {}): UseFetchSloListResponse {
const {
http,
notifications: { toasts },
} = useKibana().services;
const queryClient = useQueryClient();
const [stateRefetchInterval, setStateRefetchInterval] = useState<number>(
SLO_SHORT_REFETCH_INTERVAL
);

const { dataView } = useCreateDataView({
indexPatternString: SLO_SUMMARY_DESTINATION_INDEX_NAME,
});

const filters = useMemo(() => {
try {
return JSON.stringify(
buildQueryFromFilters(filterDSL, dataView, {
ignoreFilterIfFieldNotInIndex: true,
})
);
} catch (e) {
return '';
}
}, [filterDSL, dataView]);

const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data } = useQuery({
queryKey: sloKeys.list({ kqlQuery, page, perPage, sortBy, sortDirection }),
queryKey: sloKeys.list({
kqlQuery,
page,
perPage,
sortBy,
sortDirection,
filters,
lastRefresh,
}),
queryFn: async ({ signal }) => {
const response = await http.get<FindSLOResponse>(`/api/observability/slos`, {
return await http.get<FindSLOResponse>(`/api/observability/slos`, {
query: {
...(kqlQuery && { kqlQuery }),
...(sortBy && { sortBy }),
...(sortDirection && { sortDirection }),
...(page && { page }),
...(perPage && { perPage }),
...(filters && { filters }),
},
signal,
});

return response;
},
cacheTime: 0,
refetchOnWindowFocus: false,
refetchInterval: shouldRefetch ? stateRefetchInterval : undefined,
retry: (failureCount, error) => {
if (String(error) === 'Error: Forbidden') {
return false;
Expand All @@ -79,16 +104,6 @@ export function useFetchSloList({
queryClient.invalidateQueries({ queryKey: sloKeys.historicalSummaries(), exact: false });
queryClient.invalidateQueries({ queryKey: sloKeys.activeAlerts(), exact: false });
queryClient.invalidateQueries({ queryKey: sloKeys.rules(), exact: false });

if (!shouldRefetch) {
return;
}

if (results.find((slo) => slo.summary.status === 'NO_DATA' || !slo.summary)) {
setStateRefetchInterval(SLO_SHORT_REFETCH_INTERVAL);
} else {
setStateRefetchInterval(SLO_LONG_REFETCH_INTERVAL);
}
},
onError: (error: Error) => {
toasts.addError(error, {
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/observability/public/locators/slo_list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('SloListLocator', () => {
const location = await locator.getLocation({});
expect(location.app).toEqual('observability');
expect(location.path).toMatchInlineSnapshot(
`"/slos?search=(compact:!t,kqlQuery:'',page:0,perPage:25,sort:(by:status,direction:desc),view:cardView)"`
`"/slos?search=(compact:!t,filters:!(),kqlQuery:'',lastRefresh:0,page:0,perPage:25,sort:(by:status,direction:desc),view:cardView)"`
);
});

Expand All @@ -24,7 +24,7 @@ describe('SloListLocator', () => {
});
expect(location.app).toEqual('observability');
expect(location.path).toMatchInlineSnapshot(
`"/slos?search=(compact:!t,kqlQuery:'slo.name:%20%22Service%20Availability%22%20and%20slo.indicator.type%20:%20%22sli.kql.custom%22',page:0,perPage:25,sort:(by:status,direction:desc),view:cardView)"`
`"/slos?search=(compact:!t,filters:!(),kqlQuery:'slo.name:%20%22Service%20Availability%22%20and%20slo.indicator.type%20:%20%22sli.kql.custom%22',lastRefresh:0,page:0,perPage:25,sort:(by:status,direction:desc),view:cardView)"`
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import React from 'react';
import { useKibana } from '../../../../utils/kibana_react';
import { usePluginContext } from '../../../../hooks/use_plugin_context';
import HeaderMenuPortal from './header_menu_portal';
const SLO_FEEDBACK_LINK = 'https://ela.st/slo-feedback';

export function HeaderMenu(): React.ReactElement | null {
const {
Expand All @@ -27,6 +28,16 @@ export function HeaderMenu(): React.ReactElement | null {
return (
<HeaderMenuPortal setHeaderActionMenu={setHeaderActionMenu} theme$={theme.theme$}>
<EuiHeaderLinks>
<EuiHeaderLink
data-test-subj="sloFeedbackButton"
color="warning"
href={SLO_FEEDBACK_LINK}
iconType="popout"
>
{i18n.translate('xpack.observability.slo.giveFeedback', {
defaultMessage: 'Give feedback',
})}
</EuiHeaderLink>
<EuiHeaderLink
color="primary"
href={http.basePath.prepend('/app/integrations/browse')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import { HeaderControl } from './components/header_control';
import { paths } from '../../../common/locators/paths';
import type { SloDetailsPathParams } from './types';
import { AutoRefreshButton } from '../../components/slo/auto_refresh_button';
import { FeedbackButton } from '../../components/slo/feedback_button/feedback_button';
import { useGetInstanceIdQueryParam } from './hooks/use_get_instance_id_query_param';
import { useAutoRefreshStorage } from '../../components/slo/auto_refresh_button/hooks/use_auto_refresh_storage';
import { HeaderMenu } from '../overview/components/header_menu/header_menu';
Expand Down Expand Up @@ -81,7 +80,6 @@ export function SloDetailsPage() {
isAutoRefreshing={isAutoRefreshing}
onClick={handleToggleAutoRefresh}
/>,
<FeedbackButton disabled={isPerformingAction} />,
],
bottomBorder: false,
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import { i18n } from '@kbn/i18n';
import { useBreadcrumbs } from '@kbn/observability-shared-plugin/public';

import { createHtmlPortalNode, OutPortal } from 'react-reverse-portal';
import { FeedbackButton } from '../alert_details/components/feedback_button';
import { paths } from '../../../common/locators/paths';
import { useKibana } from '../../utils/kibana_react';
import { usePluginContext } from '../../hooks/use_plugin_context';
import { useFetchSloDetails } from '../../hooks/slo/use_fetch_slo_details';
import { useLicense } from '../../hooks/use_license';
import { useCapabilities } from '../../hooks/slo/use_capabilities';
import { useFetchSloGlobalDiagnosis } from '../../hooks/slo/use_fetch_global_diagnosis';
import { FeedbackButton } from '../../components/slo/feedback_button/feedback_button';
import { SloEditForm } from './components/slo_edit_form';
import { HeaderMenu } from '../overview/components/header_menu/header_menu';

Expand Down
Loading

0 comments on commit f1057ca

Please sign in to comment.