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

[ML] Explain log rate spikes: Move API stream demos to Kibana examples. #132590

Merged
merged 25 commits into from
May 24, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ff5dbf2
[Ml] Example plugin boilerplate.
walterra May 16, 2022
55a7bb0
[ML] Fix tsconfig.base.json.
walterra May 17, 2022
6dd5169
[ML] Move bar chart race page from aiops to examples.
walterra May 17, 2022
42267da
[ML] Add simple string example.
walterra May 18, 2022
600d451
[ML] Improve support for simple string reducer.
walterra May 18, 2022
6c22a7f
[ML] Move shared code to @kbn/aiops-utils package.
walterra May 19, 2022
b9208af
[ML] Move API integration tests.
walterra May 19, 2022
bc8db4f
[Ml] Tweak navigation.
walterra May 19, 2022
7e6173c
[ML] Improve error handling.
walterra May 20, 2022
1d1d30b
[ML] Fix type exports.
walterra May 20, 2022
a8029d9
[ML] Fix tsconfig.
walterra May 20, 2022
b46f2df
[ML] Fix tests.
walterra May 20, 2022
847cf02
[ML] Improve error handling.
walterra May 20, 2022
7d1f596
[ML] Fix updated function usage.
walterra May 20, 2022
7970ea3
[ML] Fix updated function usage.
walterra May 20, 2022
29b34ce
[ML] Improve error handling.
walterra May 23, 2022
d5b8c5c
[ML] Fix types for headers. Improves some docs.
walterra May 23, 2022
eebf7fb
[ML] Fix types.
walterra May 23, 2022
bf70cca
[ML] Extend README.md.
walterra May 24, 2022
39279ba
[ML] Remove translations from example plugin.
walterra May 24, 2022
304e8e3
[ML] Document fetchStream().
walterra May 24, 2022
4136a92
[ML] Improve error handling.
walterra May 24, 2022
fa70297
[ML] Add comment to random timeout.
walterra May 24, 2022
6a4df1e
Merge branch 'main' into ml-aiops-examples
walterra May 24, 2022
e80dffc
[ML] Document stringReducer().
walterra May 24, 2022
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
4 changes: 3 additions & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
/x-pack/test/screenshot_creation/apps/ml_docs @elastic/ml-ui
/x-pack/test/screenshot_creation/services/ml_screenshots.ts @elastic/ml-ui

# Additional plugins maintained by the ML team.
# Additional plugins and packages maintained by the ML team.
/x-pack/plugins/aiops/ @elastic/ml-ui
/x-pack/plugins/data_visualizer/ @elastic/ml-ui
/x-pack/plugins/file_upload/ @elastic/ml-ui
Expand All @@ -198,6 +198,8 @@
/x-pack/test/functional/apps/transform/ @elastic/ml-ui
/x-pack/test/functional/services/transform/ @elastic/ml-ui
/x-pack/test/functional_basic/apps/transform/ @elastic/ml-ui
/packages/kbn-aiops-utils @elastic/ml-ui
/examples/response_stream/ @elastic/ml-ui

# Maps
#CC# /x-pack/plugins/maps/ @elastic/kibana-gis
Expand Down
5 changes: 5 additions & 0 deletions examples/response_stream/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## response stream

This example demonstrates how to stream chunks of data to the client with just a single request.

To run this example, use the command `yarn start --run-examples`.
1 change: 1 addition & 0 deletions examples/response_stream/common/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The `./api` folder contains shared code used to support working with the same type specifications on server and client.
36 changes: 36 additions & 0 deletions examples/response_stream/common/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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 type {
UseFetchStreamCustomReducerParams,
UseFetchStreamParamsDefault,
} from '@kbn/aiops-utils';

import {
reducerStreamReducer,
ReducerStreamRequestBodySchema,
ReducerStreamApiAction,
} from './reducer_stream';
import { SimpleStringStreamRequestBodySchema } from './simple_string_stream';

export const API_ENDPOINT = {
REDUCER_STREAM: '/internal/response_stream/reducer_stream',
SIMPLE_STRING_STREAM: '/internal/response_stream/simple_string_stream',
} as const;

export interface ApiReducerStream extends UseFetchStreamCustomReducerParams {
endpoint: typeof API_ENDPOINT.REDUCER_STREAM;
reducer: typeof reducerStreamReducer;
body: ReducerStreamRequestBodySchema;
actions: ReducerStreamApiAction;
}

export interface ApiSimpleStringStream extends UseFetchStreamParamsDefault {
endpoint: typeof API_ENDPOINT.SIMPLE_STRING_STREAM;
body: SimpleStringStreamRequestBodySchema;
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
* 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 { schema, TypeOf } from '@kbn/config-schema';

export const aiopsExampleStreamSchema = schema.object({
/** Boolean flag to enable/disabling simulation of response errors. */
simulateErrors: schema.maybe(schema.boolean()),
/** Maximum timeout between streaming messages. */
timeout: schema.maybe(schema.number()),
});

export type AiopsExampleStreamSchema = TypeOf<typeof aiopsExampleStreamSchema>;
export { reducerStreamReducer } from './reducer';
export { reducerStreamRequestBodySchema } from './request_body_schema';
export type { ReducerStreamRequestBodySchema } from './request_body_schema';

export const API_ACTION_NAME = {
UPDATE_PROGRESS: 'update_progress',
Expand Down Expand Up @@ -65,7 +59,7 @@ export function deleteEntityAction(payload: string): ApiActionDeleteEntity {
};
}

export type AiopsExampleStreamApiAction =
export type ReducerStreamApiAction =
| ApiActionUpdateProgress
| ApiActionAddToEntity
| ApiActionDeleteEntity;
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
* 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 { AiopsExampleStreamApiAction, API_ACTION_NAME } from '../../../common/api/example_stream';
import { ReducerStreamApiAction, API_ACTION_NAME } from '.';

export const UI_ACTION_NAME = {
ERROR: 'error',
RESET: 'reset',
} as const;
export type UiActionName = typeof UI_ACTION_NAME[keyof typeof UI_ACTION_NAME];

export interface StreamState {
errors: string[];
progress: number;
entities: Record<string, number>;
}
export const initialState: StreamState = {
errors: [],
progress: 0,
entities: {},
};

interface UiActionError {
type: typeof UI_ACTION_NAME.ERROR;
payload: string;
}
interface UiActionResetStream {
type: typeof UI_ACTION_NAME.RESET;
}
Expand All @@ -36,14 +30,14 @@ export function resetStream(): UiActionResetStream {
return { type: UI_ACTION_NAME.RESET };
}

type UiAction = UiActionResetStream | UiActionError;
export type ReducerAction = AiopsExampleStreamApiAction | UiAction;
export function streamReducer(
type UiAction = UiActionResetStream;
export type ReducerAction = ReducerStreamApiAction | UiAction;
export function reducerStreamReducer(
state: StreamState,
action: ReducerAction | ReducerAction[]
): StreamState {
if (Array.isArray(action)) {
return action.reduce(streamReducer, state);
return action.reduce(reducerStreamReducer, state);
}

switch (action.type) {
Expand Down Expand Up @@ -72,15 +66,7 @@ export function streamReducer(
};
case UI_ACTION_NAME.RESET:
return initialState;
case UI_ACTION_NAME.ERROR:
return {
...state,
errors: [...state.errors, action.payload],
};
default:
return {
...state,
errors: [...state.errors, 'UNKNOWN_ACTION_ERROR'],
};
return state;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* 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 { schema, TypeOf } from '@kbn/config-schema';

export const reducerStreamRequestBodySchema = schema.object({
/** Boolean flag to enable/disabling simulation of response errors. */
simulateErrors: schema.maybe(schema.boolean()),
/** Maximum timeout between streaming messages. */
timeout: schema.maybe(schema.number()),
});
export type ReducerStreamRequestBodySchema = TypeOf<typeof reducerStreamRequestBodySchema>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* 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.
*/

export { simpleStringStreamRequestBodySchema } from './request_body_schema';
export type { SimpleStringStreamRequestBodySchema } from './request_body_schema';
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* 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 { schema, TypeOf } from '@kbn/config-schema';

export const simpleStringStreamRequestBodySchema = schema.object({
/** Maximum timeout between streaming messages. */
timeout: schema.number(),
});
export type SimpleStringStreamRequestBodySchema = TypeOf<
typeof simpleStringStreamRequestBodySchema
>;
14 changes: 14 additions & 0 deletions examples/response_stream/kibana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"id": "responseStream",
"kibanaVersion": "kibana",
"version": "0.0.1",
"server": true,
"ui": true,
"owner": {
"name": "ML UI",
"githubTeam": "ml-ui"
},
"requiredPlugins": ["developerExamples"],
"optionalPlugins": [],
"requiredBundles": ["kibanaReact"]
}
41 changes: 41 additions & 0 deletions examples/response_stream/public/components/page.tsx
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 * as React from 'react';

import {
EuiPageBody,
EuiPageContent,
EuiPageContentBody,
EuiPageHeader,
EuiPageHeaderSection,
EuiTitle,
} from '@elastic/eui';

export interface PageProps {
title?: React.ReactNode;
}

export const Page: React.FC<PageProps> = ({ title = 'Untitled', children }) => {
return (
<EuiPageBody>
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>{title}</h1>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiPageContent>
<EuiPageContentBody style={{ maxWidth: 800, margin: '0 auto' }}>
{children}
</EuiPageContentBody>
</EuiPageContent>
</EuiPageBody>
);
};
37 changes: 37 additions & 0 deletions examples/response_stream/public/containers/app/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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 React from 'react';
import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom';
import { EuiPage } from '@elastic/eui';
import { useDeps } from '../../hooks/use_deps';
import { Sidebar } from './sidebar';
import { routes } from '../../routes';

export const App: React.FC = () => {
const { appBasePath } = useDeps();

const routeElements: React.ReactElement[] = [];
for (const { items } of routes) {
for (const { id, component } of items) {
routeElements.push(<Route key={id} path={`/${id}`} render={(props) => component} />);
}
}

return (
<Router basename={appBasePath}>
<EuiPage>
<Sidebar />
<Switch>
{routeElements}
<Redirect to="/simple-string-stream" />
</Switch>
</EuiPage>
</Router>
);
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
* 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.
*/

export function getStatusMessage(isRunning: boolean, isCancelled: boolean, progress: number) {
Expand All @@ -13,7 +14,7 @@ export function getStatusMessage(isRunning: boolean, isCancelled: boolean, progr
} else if (!isRunning && isCancelled) {
return 'Oh no, development got cancelled!';
} else if (!isRunning && progress === 100) {
return 'Development clompeted, the release got out the door!';
return 'Development completed, the release got out the door!';
}

// When the process stops but wasn't cancelled by the user and progress is not yet at 100%,
Expand Down
Loading