Skip to content

Commit

Permalink
[Discover][Alerting] Use Discover locator for alert results link (#14…
Browse files Browse the repository at this point in the history
…6403)

## Summary

Closes #145815, #134232

- Moves Discover locator to common area
- Builds alerts results link from the server
- Now there are two implementations of `setStateToKbnUrl` which is used
in locator. New one in common are lost `HashedItemStore` support, since
sessions storage are actual only for browser
- Toasts `Alert rule has changed`, `Data View has changed` removed
- link generated per each alert will be unique representation of those
`rule params` and `data view state` which were at the time of invocation
- Restuls link will live even after data view and rule removal




### How to create rule

- Create an output index and data view `test` 
<details>
  <summary>Query to use</summary>
  
```
PUT test
{
    "settings" : {
        "number_of_shards" : 1
    },
    "mappings" : {
        "properties" : {
            "rule_id" : { "type" : "text" },
            "rule_name" : { "type" : "text" },
            "alert_id" : { "type" : "text" },
            "context_message": { "type" : "text" }
        }
    }
}
```
</details>

- Create alerts connector using `test` index
- Open `Elasticsearch query` alert in `KQL or Lucene` mode or just using
Discover `Alerts` button
- Specify the following params: `IS ABOVE: 1`, `FOR THE LAST: 30 min`
- Try execute it by clicking `Test query`. It should match some results
- When choosing connector, use the following config
```
{
    "rule_id": "{{rule.id}}",
    "rule_name": "{{rule.name}}",
    "alert_id": "{{alert.id}}",
    "context_message": "{{context.message}}"
}
```
- Create the alert

### How to test

- Create `Elasticsearch query` rule in `KQL or Lucene` mode like
described above
- Wait for some seconds and find the triggered alert document by
browsing `test` data view in Discover. There should be a link to results
in `context_message` field. Save the link somewhere
- Change rule params by adding/removing filters / changing query /
changing data view
- Follow saved link, you should see previous filters, query and data
view state
- Open rule in management and click `View in app`, you should see actual
state of rule
- Try to remove used data view and then follow saved link, you should
still see the results
- Try to remove rule and then follow saved link, you should still see
the results.

### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [x] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)

Co-authored-by: Davis McPhee <[email protected]>
  • Loading branch information
dimaanj and davismcphee authored Jan 4, 2023
1 parent 4e11ef1 commit 503b466
Show file tree
Hide file tree
Showing 90 changed files with 924 additions and 451 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export function ShowShareModal({
if (_g?.filters && _g.filters.length === 0) {
_g = omit(_g, 'filters');
}
const baseUrl = setStateToKbnUrl('_g', _g);
const baseUrl = setStateToKbnUrl('_g', _g, undefined, window.location.href);

const shareableUrl = setStateToKbnUrl(
'_a',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import { History } from 'history';

import {
getQueryParams,
replaceUrlHashQuery,
IKbnUrlStateStorage,
createQueryParamObservable,
} from '@kbn/kibana-utils-plugin/public';
import { replaceUrlHashQuery } from '@kbn/kibana-utils-plugin/common';
import type { Query } from '@kbn/es-query';
import { SearchSessionInfoProvider } from '@kbn/data-plugin/public';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import _ from 'lodash';
import { debounceTime } from 'rxjs/operators';
import semverSatisfies from 'semver/functions/satisfies';

import { IKbnUrlStateStorage, replaceUrlHashQuery } from '@kbn/kibana-utils-plugin/public';
import { IKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public';
import { replaceUrlHashQuery } from '@kbn/kibana-utils-plugin/common';

import {
DashboardPanelMap,
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/dashboard/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ import type {
import { APP_WRAPPER_CLASS } from '@kbn/core/public';
import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
import type { HomePublicPluginSetup } from '@kbn/home-plugin/public';
import { replaceUrlHashQuery } from '@kbn/kibana-utils-plugin/common';
import { createKbnUrlTracker } from '@kbn/kibana-utils-plugin/public';
import { replaceUrlHashQuery } from '@kbn/kibana-utils-plugin/public';
import type { SavedObjectsStart } from '@kbn/saved-objects-plugin/public';
import type { VisualizationsStart } from '@kbn/visualizations-plugin/public';
import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,19 @@ export const EditIndexPattern = withRouter(
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize="none" alignItems="center">
<EuiText size="s">{indexPatternHeading}</EuiText>
<EuiCode style={codeStyle}>{indexPattern.title}</EuiCode>
<EuiCode data-test-subj="currentIndexPatternTitle" style={codeStyle}>
{indexPattern.title}
</EuiCode>
</EuiFlexGroup>
</EuiFlexItem>
)}
{Boolean(indexPattern.timeFieldName) && (
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize="none" alignItems="center">
<EuiText size="s">{timeFilterHeading}</EuiText>
<EuiCode style={codeStyle}>{indexPattern.timeFieldName}</EuiCode>
<EuiCode data-test-subj="currentIndexPatternTimeField" style={codeStyle}>
{indexPattern.timeFieldName}
</EuiCode>
</EuiFlexGroup>
</EuiFlexItem>
)}
Expand Down
1 change: 1 addition & 0 deletions src/plugins/data_views/public/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const createStartContract = (): Start => {
getCanSaveSync: jest.fn(),
getIdsWithTitle: jest.fn(),
getFieldsForIndexPattern: jest.fn(),
create: jest.fn().mockReturnValue(Promise.resolve({})),
} as unknown as jest.Mocked<DataViewsContract>;
};

Expand Down
4 changes: 4 additions & 0 deletions src/plugins/discover/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@

export const DEFAULT_ROWS_PER_PAGE = 100;
export const ROWS_PER_PAGE_OPTIONS = [10, 25, 50, DEFAULT_ROWS_PER_PAGE, 250, 500];
export enum VIEW_MODE {
DOCUMENT_LEVEL = 'documents',
AGGREGATED_LEVEL = 'aggregated',
}
3 changes: 3 additions & 0 deletions src/plugins/discover/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ export const SEARCH_EMBEDDABLE_TYPE = 'search';
export const HIDE_ANNOUNCEMENTS = 'hideAnnouncements';
export const SHOW_LEGACY_FIELD_TOP_VALUES = 'discover:showLegacyFieldTopValues';
export const ENABLE_SQL = 'discover:enableSql';

export { DISCOVER_APP_LOCATOR, DiscoverAppLocatorDefinition } from './locator';
export type { DiscoverAppLocator, DiscoverAppLocatorParams } from './locator';
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
* Side Public License, v 1.
*/

import { hashedItemStore, getStatesFromKbnUrl } from '@kbn/kibana-utils-plugin/public';
import {
hashedItemStore,
getStatesFromKbnUrl,
setStateToKbnUrl,
} from '@kbn/kibana-utils-plugin/public';
import { mockStorage } from '@kbn/kibana-utils-plugin/public/storage/hashed_item_store/mock';
import { FilterStateStore } from '@kbn/es-query';
import { DiscoverAppLocatorDefinition } from './locator';
Expand All @@ -20,7 +24,7 @@ interface SetupParams {
}

const setup = async ({ useHash = false }: SetupParams = {}) => {
const locator = new DiscoverAppLocatorDefinition({ useHash });
const locator = new DiscoverAppLocatorDefinition({ useHash, setStateToKbnUrl });

return {
locator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import type { SerializableRecord } from '@kbn/utility-types';
import type { Filter, TimeRange, Query, AggregateQuery } from '@kbn/es-query';
import type { GlobalQueryStateFromUrl, RefreshInterval } from '@kbn/data-plugin/public';
import type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/public';
import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/public';
import { DataViewSpec } from '@kbn/data-views-plugin/public';
import type { VIEW_MODE } from './components/view_mode_toggle';
import { DataViewSpec } from '@kbn/data-views-plugin/common';
import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/common';
import { VIEW_MODE } from './constants';

export const DISCOVER_APP_LOCATOR = 'DISCOVER_APP_LOCATOR';

Expand Down Expand Up @@ -95,19 +95,25 @@ export interface DiscoverAppLocatorParams extends SerializableRecord {
* Breakdown field
*/
breakdownField?: string;
/**
* Used when navigating to particular alert results
*/
isAlertResults?: boolean;
}

export type DiscoverAppLocator = LocatorPublic<DiscoverAppLocatorParams>;

export interface DiscoverAppLocatorDependencies {
useHash: boolean;
setStateToKbnUrl: typeof setStateToKbnUrl;
}

/**
* Location state of scoped history (history instance of Kibana Platform application service)
*/
export interface MainHistoryLocationState {
dataViewSpec?: DataViewSpec;
isAlertResults?: boolean;
}

export class DiscoverAppLocatorDefinition implements LocatorDefinition<DiscoverAppLocatorParams> {
Expand All @@ -134,6 +140,7 @@ export class DiscoverAppLocatorDefinition implements LocatorDefinition<DiscoverA
viewMode,
hideAggregatedPreview,
breakdownField,
isAlertResults,
} = params;
const savedSearchPath = savedSearchId ? `view/${encodeURIComponent(savedSearchId)}` : '';
const appState: {
Expand Down Expand Up @@ -168,13 +175,12 @@ export class DiscoverAppLocatorDefinition implements LocatorDefinition<DiscoverA
if (breakdownField) appState.breakdownField = breakdownField;

const state: MainHistoryLocationState = {};
if (dataViewSpec) {
state.dataViewSpec = dataViewSpec;
}
if (dataViewSpec) state.dataViewSpec = dataViewSpec;
if (isAlertResults) state.isAlertResults = isAlertResults;

let path = `#/${savedSearchPath}`;
path = setStateToKbnUrl<GlobalQueryStateFromUrl>('_g', queryState, { useHash }, path);
path = setStateToKbnUrl('_a', appState, { useHash }, path);
path = this.deps.setStateToKbnUrl<GlobalQueryStateFromUrl>('_g', queryState, { useHash }, path);
path = this.deps.setStateToKbnUrl('_a', appState, { useHash }, path);

if (searchSessionId) {
path = `${path}&searchSessionId=${searchSessionId}`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { isOfQueryType } from '@kbn/es-query';
import classNames from 'classnames';
import { generateFilters } from '@kbn/data-plugin/public';
import { DataView, DataViewField, DataViewType } from '@kbn/data-views-plugin/public';
import { VIEW_MODE } from '../../../../../common/constants';
import { useInternalStateSelector } from '../../services/discover_internal_state_container';
import { useAppStateSelector } from '../../services/discover_app_state_container';
import { useInspector } from '../../hooks/use_inspector';
Expand All @@ -41,7 +42,6 @@ import { DataMainMsg, RecordRawType } from '../../hooks/use_saved_search';
import { useColumns } from '../../../../hooks/use_data_grid_columns';
import { FetchStatus } from '../../../types';
import { useDataState } from '../../hooks/use_data_state';
import { VIEW_MODE } from '../../../../components/view_mode_toggle';
import { hasActiveFilter } from './utils';
import { getRawRecordType } from '../../utils/get_raw_record_type';
import { SavedSearchURLConflictCallout } from '../../../../components/saved_search_url_conflict_callout/saved_search_url_conflict_callout';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import { SavedSearch } from '@kbn/saved-search-plugin/public';
import React, { useCallback } from 'react';
import { DataView } from '@kbn/data-views-plugin/common';
import { METRIC_TYPE } from '@kbn/analytics';
import { VIEW_MODE } from '../../../../../common/constants';
import { useDiscoverServices } from '../../../../hooks/use_discover_services';
import { DataTableRecord } from '../../../../types';
import { DocumentViewModeToggle, VIEW_MODE } from '../../../../components/view_mode_toggle';
import { DocumentViewModeToggle } from '../../../../components/view_mode_toggle';
import { DocViewFilterFn } from '../../../../services/doc_views/doc_views_types';
import { DataRefetch$, SavedSearchData } from '../../hooks/use_saved_search';
import { DiscoverStateContainer } from '../../services/discover_state';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ import type { AggregateQuery, Query } from '@kbn/es-query';
import { getDefaultFieldFilter } from './lib/field_filter';
import { createDiscoverServicesMock } from '../../../../__mocks__/services';
import { stubLogstashDataView } from '@kbn/data-plugin/common/stubs';
import { VIEW_MODE } from '../../../../components/view_mode_toggle';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { BehaviorSubject } from 'rxjs';
import { FetchStatus } from '../../../types';
import { AvailableFields$, DataDocuments$ } from '../../hooks/use_saved_search';
import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock';
import { VIEW_MODE } from '../../../../../common/constants';
import { DiscoverMainProvider } from '../../services/discover_state_provider';
import * as ExistingFieldsHookApi from '@kbn/unified-field-list-plugin/public/hooks/use_existing_fields';
import { ExistenceFetchStatus } from '@kbn/unified-field-list-plugin/public';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
triggerVisualizeActionsTextBasedLanguages,
useGroupedFields,
} from '@kbn/unified-field-list-plugin/public';
import { VIEW_MODE } from '../../../../../common/constants';
import { useAppStateSelector } from '../../services/discover_app_state_container';
import { useDiscoverServices } from '../../../../hooks/use_discover_services';
import { DiscoverField } from './discover_field';
Expand All @@ -40,7 +41,6 @@ import {
} from './lib/group_fields';
import { doesFieldMatchFilters, FieldFilterState, setFieldFilterProp } from './lib/field_filter';
import { DiscoverSidebarResponsiveProps } from './discover_sidebar_responsive';
import { VIEW_MODE } from '../../../../components/view_mode_toggle';
import { getUiActions } from '../../../../kibana_services';
import { getRawRecordType } from '../../utils/get_raw_record_type';
import { RecordRawType } from '../../hooks/use_saved_search';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ import { DiscoverServices } from '../../../../build_services';
import { FetchStatus } from '../../../types';
import { AvailableFields$, DataDocuments$, RecordRawType } from '../../hooks/use_saved_search';
import { stubLogstashDataView } from '@kbn/data-plugin/common/stubs';
import { VIEW_MODE } from '../../../../components/view_mode_toggle';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock';
import { DiscoverAppStateProvider } from '../../services/discover_app_state_container';
import { VIEW_MODE } from '../../../../../common/constants';
import * as ExistingFieldsServiceApi from '@kbn/unified-field-list-plugin/public/services/field_existing/load_field_existing';
import { resetExistingFieldsCache } from '@kbn/unified-field-list-plugin/public/hooks/use_existing_fields';
import { createDiscoverServicesMock } from '../../../../__mocks__/services';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ import {
useExistingFieldsFetcher,
useQuerySubscriber,
} from '@kbn/unified-field-list-plugin/public';
import { VIEW_MODE } from '../../../../../common/constants';
import { useDiscoverServices } from '../../../../hooks/use_discover_services';
import { getDefaultFieldFilter } from './lib/field_filter';
import { DiscoverSidebar } from './discover_sidebar';
import { AvailableFields$, DataDocuments$, RecordRawType } from '../../hooks/use_saved_search';
import { VIEW_MODE } from '../../../../components/view_mode_toggle';
import { calcFieldCounts } from '../../utils/calc_field_counts';
import { FetchStatus } from '../../../types';
import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../../../../components/discover_tour';
import { getRawRecordType } from '../../utils/get_raw_record_type';
Expand All @@ -43,7 +44,6 @@ import {
DiscoverSidebarReducerActionType,
DiscoverSidebarReducerStatus,
} from './lib/sidebar_reducer';
import { calcFieldCounts } from '../../utils/calc_field_counts';

export interface DiscoverSidebarResponsiveProps {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
getSavedSearch,
getSavedSearchFullPathUrl,
} from '@kbn/saved-search-plugin/public';
import { MainHistoryLocationState } from '../../../common/locator';
import { getDiscoverStateContainer } from './services/discover_state';
import { loadDataView, resolveDataView } from './utils/resolve_data_view';
import { DiscoverMainApp } from './discover_main_app';
Expand All @@ -30,7 +31,7 @@ import { DiscoverError } from '../../components/common/error_alert';
import { useDiscoverServices } from '../../hooks/use_discover_services';
import { getScopedHistory, getUrlTracker } from '../../kibana_services';
import { restoreStateFromSavedSearch } from '../../services/saved_searches/restore_from_saved_search';
import { MainHistoryLocationState } from '../../locator';
import { useAlertResultsToast } from './hooks/use_alert_results_toast';

const DiscoverMainAppMemoized = memo(DiscoverMainApp);

Expand Down Expand Up @@ -72,6 +73,11 @@ export function DiscoverMainRoute(props: Props) {
[]
);

useAlertResultsToast({
isAlertResults: historyLocationState?.isAlertResults,
toastNotifications,
});

useExecutionContext(core.executionContext, {
type: 'application',
page: 'app',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { ToastsStart } from '@kbn/core/public';
import { i18n } from '@kbn/i18n';
import { MarkdownSimple, toMountPoint } from '@kbn/kibana-react-plugin/public';
import React, { useEffect } from 'react';

export const displayPossibleDocsDiffInfoAlert = (toastNotifications: ToastsStart) => {
const infoTitle = i18n.translate('discover.viewAlert.documentsMayVaryInfoTitle', {
defaultMessage: 'Displayed documents may vary',
});
const infoDescription = i18n.translate('discover.viewAlert.documentsMayVaryInfoDescription', {
defaultMessage: `The displayed documents might differ from the documents that triggered the alert.
Some documents might have been added or deleted.`,
});

toastNotifications.addInfo({
title: infoTitle,
text: toMountPoint(<MarkdownSimple>{infoDescription}</MarkdownSimple>),
});
};

export const useAlertResultsToast = ({
isAlertResults,
toastNotifications,
}: {
isAlertResults?: boolean;
toastNotifications: ToastsStart;
}) => {
useEffect(() => {
if (isAlertResults) {
displayPossibleDocsDiffInfoAlert(toastNotifications);
}
}, [isAlertResults, toastNotifications]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {
ReduxLikeStateContainer,
} from '@kbn/kibana-utils-plugin/common';
import { AggregateQuery, Filter, Query } from '@kbn/es-query';
import { VIEW_MODE } from '@kbn/saved-search-plugin/public';
import { DiscoverGridSettings } from '../../../components/discover_grid/types';
import { VIEW_MODE } from '../../../components/view_mode_toggle';

export interface AppState {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
} from '@kbn/data-plugin/public';
import { DataView } from '@kbn/data-views-plugin/public';
import { SavedSearch } from '@kbn/saved-search-plugin/public';
import { DiscoverAppLocatorParams, DISCOVER_APP_LOCATOR } from '../../../../common';
import { AppState } from './discover_app_state_container';
import {
getInternalStateContainer,
Expand All @@ -37,7 +38,6 @@ import {
import { getStateDefaults } from '../utils/get_state_defaults';
import { DiscoverServices } from '../../../build_services';
import { handleSourceColumnState } from '../../../utils/state_helpers';
import { DISCOVER_APP_LOCATOR, DiscoverAppLocatorParams } from '../../../locator';
import { cleanupUrlState } from '../utils/cleanup_url_state';
import { getValidFilters } from '../../../utils/get_valid_filters';

Expand Down
Loading

0 comments on commit 503b466

Please sign in to comment.