Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Logs+] Refactor state and URL persistence of Log Explorer #170200

Merged
merged 77 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
b1d2c35
Extract state between separate layers
Kerry350 Oct 25, 2023
f4d0bc2
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Oct 31, 2023
8d4834c
Merge remote-tracking branch 'upstream/main' into pr/Kerry350/170200
weltenwort Nov 3, 2023
af82afc
Merge branch 'main' into 165255-extract-URL-state-persistence
kibanamachine Nov 6, 2023
6a7580a
Improve log explorer state machine layout
weltenwort Nov 7, 2023
d5b35bc
Add value sanitation to xstate dev tools options
weltenwort Nov 9, 2023
493ab7b
WIP
weltenwort Nov 9, 2023
be0ac2f
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Nov 9, 2023
a711671
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Nov 9, 2023
00e5ae6
Wire up grid display changes to controller
weltenwort Nov 9, 2023
e2a70e8
Wire up chart breakdown from Discover app state
weltenwort Nov 9, 2023
f8dcf03
Prevent window.location from leaking through
weltenwort Nov 10, 2023
e97a9da
Initialize Discover app state
weltenwort Nov 10, 2023
6d16fdd
Move service creation into the controller
weltenwort Nov 10, 2023
a5c3042
Fix imports
weltenwort Nov 10, 2023
53395e6
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Nov 10, 2023
e107567
WIP
weltenwort Nov 10, 2023
dd0b8a0
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Nov 10, 2023
dbf1a42
WIP: Clean up obs log explorer main route
weltenwort Nov 13, 2023
135d1e3
Crudely wire up the query state
weltenwort Nov 13, 2023
07de7c4
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Nov 13, 2023
cd730a0
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Nov 13, 2023
2881814
WIP
weltenwort Nov 14, 2023
9bad9c5
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Nov 14, 2023
a01d7c4
WIP
weltenwort Nov 14, 2023
699f99a
Inject appropriately customized search bar
weltenwort Nov 15, 2023
888fa39
Fix erroneous semicolon in content
weltenwort Nov 15, 2023
bc49dd5
More extensively mock the discover services
weltenwort Nov 15, 2023
9b0209e
Propagate query state in log explorer state
weltenwort Nov 15, 2023
9a1aac4
Fix URL parsing
weltenwort Nov 16, 2023
b086888
Allow for no breakdown
weltenwort Nov 16, 2023
c76dff3
Fix query, filter and time initialization
weltenwort Nov 16, 2023
2a53af8
Merge remote-tracking branch 'upstream/main' into pr/Kerry350/170200
weltenwort Nov 20, 2023
890982f
Also export types
weltenwort Nov 20, 2023
59405a6
Fix merge mistakes
weltenwort Nov 20, 2023
b3fb365
Persist dataset selection and row options
weltenwort Nov 20, 2023
f2ae644
Partly fix discover link
weltenwort Nov 20, 2023
e678d95
Fix Discover link
weltenwort Nov 20, 2023
a0e9dde
Remove obsolete dataset encoding tricks
weltenwort Nov 23, 2023
9d8bb72
Persist control groups in URL
weltenwort Nov 24, 2023
202eb8b
Merge remote-tracking branch 'upstream/main' into pr/Kerry350/170200
weltenwort Nov 24, 2023
79f236d
Fix the locators
weltenwort Nov 24, 2023
14e3968
Make filter controls more intuitive in locator
weltenwort Nov 27, 2023
9f4a096
Fix the controller lifecycle
weltenwort Nov 27, 2023
5414beb
Merge remote-tracking branch 'upstream/main' into pr/Kerry350/170200
weltenwort Nov 27, 2023
331f558
Move customization into controller
weltenwort Nov 28, 2023
c7b4422
Fix dataset quality route props
weltenwort Nov 28, 2023
75872ac
Fix flyout customization
weltenwort Nov 28, 2023
57f9ca7
Fix locators tests
weltenwort Nov 28, 2023
eb1dee7
Add missing exports
weltenwort Nov 28, 2023
696afea
Add time range mode to url schema
weltenwort Nov 28, 2023
e4f6bf3
Attempt to fix navigation in functional tests
weltenwort Nov 28, 2023
29bb8f2
Apply more test fixes
weltenwort Nov 28, 2023
c1a7ef9
Merge remote-tracking branch 'upstream/main' into pr/Kerry350/170200
weltenwort Nov 28, 2023
fc2f12c
Apply more test fixes
weltenwort Nov 28, 2023
9189af8
Fix navigation in functional tests
weltenwort Nov 29, 2023
8c12b89
Merge remote-tracking branch 'upstream/main' into pr/Kerry350/170200
weltenwort Nov 29, 2023
3954a3c
Fix functional test navigation helper
weltenwort Nov 29, 2023
c40cb35
Clean up Discover modifications
weltenwort Nov 29, 2023
8fb2968
Fix mocks in slo unit tests
weltenwort Nov 29, 2023
0436f57
Add helper to navigate to invalid page states
weltenwort Nov 29, 2023
ed4a04c
Merge remote-tracking branch 'upstream/main' into pr/Kerry350/170200
weltenwort Nov 29, 2023
29e269a
Improve entry bundle sizes
weltenwort Dec 1, 2023
e964f63
Merge remote-tracking branch 'upstream/main' into pr/Kerry350/170200
weltenwort Dec 1, 2023
a693196
Fix the discover header link
weltenwort Dec 1, 2023
9b47545
Improve state matching
weltenwort Dec 1, 2023
7105256
Fix loss of columns when switching data views
weltenwort Dec 4, 2023
f5488c8
Merge remote-tracking branch 'upstream/main' into pr/Kerry350/170200
weltenwort Dec 4, 2023
e4fc5a0
Restore dataview workaround
weltenwort Dec 4, 2023
6a82d2a
Fix unintended import
weltenwort Dec 4, 2023
ec242e6
Fix typo
weltenwort Dec 4, 2023
3b46cba
Merge remote-tracking branch 'upstream/main' into pr/Kerry350/170200
weltenwort Dec 5, 2023
2436642
Merge remote-tracking branch 'upstream/main' into pr/Kerry350/170200
weltenwort Dec 8, 2023
daf302e
Fix merge mistakes
weltenwort Dec 8, 2023
26b23b6
Merge remote-tracking branch 'upstream/main' into pr/Kerry350/170200
weltenwort Dec 8, 2023
aeee2d4
Merge remote-tracking branch 'upstream/main' into pr/Kerry350/170200
weltenwort Dec 11, 2023
82e9b6e
Add unit test for the custom state storage
weltenwort Dec 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/deeplinks/observability/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

export const LOGS_APP_ID = 'logs';

export const OBSERVABILITY_LOG_EXPLORER = 'observability-log-explorer';
export const OBSERVABILITY_LOG_EXPLORER_APP_ID = 'observability-log-explorer';

export const OBSERVABILITY_OVERVIEW_APP_ID = 'observability-overview';

Expand Down
8 changes: 4 additions & 4 deletions packages/deeplinks/observability/deep_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
*/

import {
APM_APP_ID,
LOGS_APP_ID,
OBSERVABILITY_LOG_EXPLORER,
OBSERVABILITY_OVERVIEW_APP_ID,
METRICS_APP_ID,
APM_APP_ID,
OBSERVABILITY_LOG_EXPLORER_APP_ID,
OBSERVABILITY_ONBOARDING_APP_ID,
OBSERVABILITY_OVERVIEW_APP_ID,
} from './constants';

type LogsApp = typeof LOGS_APP_ID;
type ObservabilityLogExplorerApp = typeof OBSERVABILITY_LOG_EXPLORER;
type ObservabilityLogExplorerApp = typeof OBSERVABILITY_LOG_EXPLORER_APP_ID;
type ObservabilityOverviewApp = typeof OBSERVABILITY_OVERVIEW_APP_ID;
type MetricsApp = typeof METRICS_APP_ID;
type ApmApp = typeof APM_APP_ID;
Expand Down
6 changes: 2 additions & 4 deletions packages/deeplinks/observability/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@
*/

export {
OBSERVABILITY_ONBOARDING_APP_ID,
LOGS_APP_ID,
OBSERVABILITY_LOG_EXPLORER,
OBSERVABILITY_LOG_EXPLORER_APP_ID,
OBSERVABILITY_ONBOARDING_APP_ID,
OBSERVABILITY_OVERVIEW_APP_ID,
} from './constants';

export type { AppId, DeepLinkId } from './deep_links';

export * from './locators';
19 changes: 15 additions & 4 deletions packages/deeplinks/observability/locators/log_explorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ export type RefreshInterval = {
value: number;
};

// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
export type FilterControls = {
namespace?: ListFilterControl;
};

// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
export type ListFilterControl = {
mode: 'include';
values: string[];
};

export const LOG_EXPLORER_LOCATOR_ID = 'LOG_EXPLORER_LOCATOR';

export interface LogExplorerNavigationParams extends SerializableRecord {
Expand All @@ -34,13 +45,13 @@ export interface LogExplorerNavigationParams extends SerializableRecord {
*/
columns?: string[];
/**
* Array of the used sorting [[field,direction],...]
* Optionally apply free-form filters.
*/
sort?: string[][];
filters?: Filter[];
/**
* Optionally apply filters.
* Optionally apply curated filter controls
*/
filters?: Filter[];
filterControls?: FilterControls;
}

export interface LogExplorerLocatorParams extends LogExplorerNavigationParams {
Expand Down
48 changes: 48 additions & 0 deletions packages/kbn-xstate-utils/src/dev_tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,52 @@
* Side Public License, v 1.
*/

import {
isArray,
isBoolean,
isDate,
isNil,
isNumber,
isPlainObject,
isString,
mapValues,
} from 'lodash';

export const isDevMode = () => process.env.NODE_ENV !== 'production';

export const getDevToolsOptions = (): boolean | object =>
isDevMode()
? {
actionSanitizer: sanitizeAction,
stateSanitizer: sanitizeState,
}
: false;

const redactComplexValues = (value: unknown): unknown => {
if (isString(value) || isNumber(value) || isBoolean(value) || isDate(value) || isNil(value)) {
return value;
}

if (isArray(value)) {
if (value.length > 100) {
return '[redacted large array]';
}
return value.map(redactComplexValues);
}

if ((isPlainObject as (v: unknown) => v is object)(value)) {
if (Object.keys(value).length > 100) {
return '[redacted large object]';
}
return mapValues(value, (innerValue: unknown) => redactComplexValues(innerValue));
}

return `[redacted complex value of type ${typeof value}]`;
};

const sanitizeAction = redactComplexValues;

const sanitizeState = (state: Record<string, unknown>) => ({
value: state.value,
context: redactComplexValues(state.context),
});
2 changes: 1 addition & 1 deletion packages/kbn-xstate-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
*/

export * from './actions';
export * from './dev_tools';
export * from './notification_channel';
export * from './types';
export * from './dev_tools';
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
import React, { useEffect, useState, memo, useCallback, useMemo } from 'react';
import { useParams, useHistory } from 'react-router-dom';
import type { DataView } from '@kbn/data-views-plugin/public';
import { redirectWhenMissing, SavedObjectNotFound } from '@kbn/kibana-utils-plugin/public';
import {
type IKbnUrlStateStorage,
redirectWhenMissing,
SavedObjectNotFound,
} from '@kbn/kibana-utils-plugin/public';
import { useExecutionContext } from '@kbn/kibana-react-plugin/public';
import {
AnalyticsNoDataPageKibanaProvider,
Expand Down Expand Up @@ -46,13 +50,15 @@ interface DiscoverLandingParams {

export interface MainRouteProps {
customizationCallbacks: CustomizationCallback[];
stateStorageContainer?: IKbnUrlStateStorage;
isDev: boolean;
customizationContext: DiscoverCustomizationContext;
}

export function DiscoverMainRoute({
customizationCallbacks,
customizationContext,
stateStorageContainer,
}: MainRouteProps) {
const history = useHistory();
const services = useDiscoverServices();
Expand All @@ -70,6 +76,7 @@ export function DiscoverMainRoute({
history,
services,
customizationContext,
stateStorageContainer,
})
);
const { customizationService, isInitialized: isCustomizationServiceInitialized } =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
DiscoverStateContainer,
createSearchSessionRestorationDataProvider,
} from './discover_state';
import { createBrowserHistory, History } from 'history';
import { createBrowserHistory, createMemoryHistory, History } from 'history';
import { dataPluginMock } from '@kbn/data-plugin/public/mocks';
import type { SavedSearch, SortOrder } from '@kbn/saved-search-plugin/public';
import {
Expand All @@ -27,6 +27,7 @@ import { waitFor } from '@testing-library/react';
import { DiscoverCustomizationContext, FetchStatus } from '../../types';
import { dataViewAdHoc, dataViewComplexMock } from '../../../__mocks__/data_view_complex';
import { copySavedSearch } from './discover_saved_search_container';
import { createKbnUrlStateStorage, IKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public';

const startSync = (appState: DiscoverAppStateContainer) => {
const { start, stop } = appState.syncState();
Expand Down Expand Up @@ -151,6 +152,68 @@ describe('Test discover state', () => {
expect(getCurrentUrl()).toBe('/#?_g=(refreshInterval:(pause:!t,value:5000))');
});
});

describe('Test discover state with overridden state storage', () => {
let stopSync = () => {};
let history: History;
let stateStorage: IKbnUrlStateStorage;
let state: DiscoverStateContainer;

beforeEach(async () => {
jest.useFakeTimers();
history = createMemoryHistory({
initialEntries: [
{
pathname: '/',
hash: `?_a=()`,
},
],
});
stateStorage = createKbnUrlStateStorage({
history,
useHash: false,
useHashQuery: true,
});
state = getDiscoverStateContainer({
services: discoverServiceMock,
history,
customizationContext,
stateStorageContainer: stateStorage,
});
state.savedSearchState.set(savedSearchMock);
state.appState.update({}, true);
stopSync = startSync(state.appState);
});

afterEach(() => {
stopSync();
stopSync = () => {};
jest.useRealTimers();
});

test('setting app state and syncing to URL', async () => {
state.appState.update({ index: 'modified' });

await jest.runAllTimersAsync();

expect(history.createHref(history.location)).toMatchInlineSnapshot(
`"/#?_a=(columns:!(default_column),index:modified,interval:auto,sort:!())"`
);
});

test('changing URL to be propagated to appState', async () => {
history.push('/#?_a=(index:modified)');

await jest.runAllTimersAsync();

expect(state.appState.getState()).toMatchInlineSnapshot(`
Object {
"index": "modified",
}
`);
});
});

describe('Test discover initial state sort handling', () => {
test('Non-empty sort in URL should not be overwritten by saved search sort', async () => {
const savedSearch = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ interface DiscoverStateContainerParams {
* Context object for customization related properties
*/
customizationContext: DiscoverCustomizationContext;
/**
* a custom url state storage
*/
stateStorageContainer?: IKbnUrlStateStorage;
}

export interface LoadParams {
Expand Down Expand Up @@ -204,19 +208,22 @@ export function getDiscoverStateContainer({
history,
services,
customizationContext,
stateStorageContainer,
}: DiscoverStateContainerParams): DiscoverStateContainer {
const storeInSessionStorage = services.uiSettings.get('state:storeInSessionStorage');
const toasts = services.core.notifications.toasts;

/**
* state storage for state in the URL
*/
const stateStorage = createKbnUrlStateStorage({
useHash: storeInSessionStorage,
history,
useHashQuery: customizationContext.displayMode !== 'embedded',
...(toasts && withNotifyOnErrors(toasts)),
});
const stateStorage =
stateStorageContainer ??
createKbnUrlStateStorage({
useHash: storeInSessionStorage,
history,
useHashQuery: customizationContext.displayMode !== 'embedded',
...(toasts && withNotifyOnErrors(toasts)),
});
davismcphee marked this conversation as resolved.
Show resolved Hide resolved

/**
* Search session logic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { ScopedHistory } from '@kbn/core/public';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import React, { useEffect, useMemo, useState } from 'react';
import { css } from '@emotion/react';
import type { IKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public';
import { DiscoverMainRoute } from '../../application/main';
import type { DiscoverServices } from '../../build_services';
import type { CustomizationCallback } from '../../customizations';
Expand All @@ -29,6 +30,7 @@ export interface DiscoverContainerInternalProps {
getDiscoverServices: () => Promise<DiscoverServices>;
scopedHistory: ScopedHistory;
customizationCallbacks: CustomizationCallback[];
stateStorageContainer?: IKbnUrlStateStorage;
isDev: boolean;
isLoading?: boolean;
}
Expand All @@ -55,6 +57,7 @@ export const DiscoverContainerInternal = ({
customizationCallbacks,
isDev,
getDiscoverServices,
stateStorageContainer,
isLoading = false,
}: DiscoverContainerInternalProps) => {
const [discoverServices, setDiscoverServices] = useState<DiscoverServices | undefined>();
Expand Down Expand Up @@ -97,6 +100,7 @@ export const DiscoverContainerInternal = ({
<DiscoverMainRoute
customizationCallbacks={customizationCallbacks}
customizationContext={customizationContext}
stateStorageContainer={stateStorageContainer}
isDev={isDev}
/>
</KibanaContextProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ describe('kbn_url_storage', () => {
await Promise.all([pr1, pr2, pr3]);
expect(getCurrentUrl()).toBe('/3');

expect(urlControls.getPendingUrl()).toBeUndefined();
expect(urlControls.getPendingUrl()).toEqual(getCurrentUrl());
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,17 +193,17 @@ export const createKbnUrlControls = (

// runs scheduled url updates
function flush(replace = shouldReplace) {
const nextUrl = getPendingUrl();

if (!nextUrl) return;
if (updateQueue.length === 0) {
return;
}

const nextUrl = getPendingUrl();
cleanUp();
const newUrl = updateUrl(nextUrl, replace);
return newUrl;
}

function getPendingUrl() {
if (updateQueue.length === 0) return undefined;
const resultUrl = updateQueue.reduce(
(url, nextUpdate) => nextUpdate(url) ?? url,
getCurrentUrl(history)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,11 @@ export const createKbnUrlStateStorage = (
unlisten();
};
}).pipe(
map(() => getStateFromKbnUrl<State>(key, undefined, { getFromHashQuery: useHashQuery })),
map(() =>
getStateFromKbnUrl<State>(key, history?.createHref(history.location), {
getFromHashQuery: useHashQuery,
})
),
catchError((error) => {
if (onGetErrorThrottled) onGetErrorThrottled(error);
return of(null);
Expand Down
Loading
Loading