Skip to content

Commit

Permalink
[Streams] App plugin (elastic#200060)
Browse files Browse the repository at this point in the history
Creates the Streams app plugin, which renders UI for managing streams
(see elastic#198713).

Additional changes in this PR:

- The menus were updated to conditionally add a link to the Streams app.
The Streams plugin itself returns a status$ observable which signals if
Streams have been enabled. This value is used to conditionally render
the link in the various flavors of menus.
- There's a small change in the ES types to allow for ordered params in
ES|QL (vs named params)
- `@kbn/server-route-repository` was updated to be able to override
`access` (instead of only inferring it from the endpoint name).
Additionally, we now allow all route options by default.
- `@kbn/typed-react-router-config` now also exports a `useBreadcrumbs`.
This was copied over from the APM implementation.
- the signature of the `esql` method in
`ObservabilityElasticsearchClient` was updated to separate processing
options from options that are sent over to the _query endpoint.

---------

Co-authored-by: Chris Cowan <[email protected]>
Co-authored-by: Joe Reuter <[email protected]>
Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
4 people authored Nov 25, 2024
1 parent 197e606 commit 63da770
Show file tree
Hide file tree
Showing 156 changed files with 4,098 additions and 1,159 deletions.
5 changes: 4 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -952,14 +952,15 @@ module.exports = {
{
files: [
'x-pack/plugins/observability_solution/**/*.{ts,tsx}',
'x-pack/plugins/{streams,streams_app}/**/*.{ts,tsx}',
'x-pack/packages/observability/**/*.{ts,tsx}',
],
rules: {
'react-hooks/exhaustive-deps': [
'error',
{
additionalHooks:
'^(useAbortableAsync|useMemoWithAbortSignal|useFetcher|useProgressiveFetcher|useBreadcrumb|useAsync|useTimeRangeAsync|useAutoAbortedHttpClient)$',
'^(useAbortableAsync|useMemoWithAbortSignal|useFetcher|useProgressiveFetcher|useBreadcrumb|useAsync|useTimeRangeAsync|useAutoAbortedHttpClient|use.*Fetch)$',
},
],
},
Expand All @@ -968,6 +969,7 @@ module.exports = {
files: [
'x-pack/plugins/aiops/**/*.tsx',
'x-pack/plugins/observability_solution/**/*.tsx',
'x-pack/plugins/{streams,streams_app}/**/*.{ts,tsx}',
'src/plugins/ai_assistant_management/**/*.tsx',
'x-pack/packages/observability/**/*.{ts,tsx}',
],
Expand All @@ -984,6 +986,7 @@ module.exports = {
{
files: [
'x-pack/plugins/observability_solution/**/!(*.stories.tsx|*.test.tsx|*.storybook_decorator.tsx|*.mock.tsx)',
'x-pack/plugins/{streams,streams_app}/**/!(*.stories.tsx|*.test.tsx|*.storybook_decorator.tsx|*.mock.tsx)',
'src/plugins/ai_assistant_management/**/!(*.stories.tsx|*.test.tsx|*.storybook_decorator.tsx|*.mock.tsx)',
'x-pack/packages/observability/logs_overview/**/!(*.stories.tsx|*.test.tsx|*.storybook_decorator.tsx|*.mock.tsx)',
],
Expand Down
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,7 @@ x-pack/plugins/spaces @elastic/kibana-security
x-pack/plugins/stack_alerts @elastic/response-ops
x-pack/plugins/stack_connectors @elastic/response-ops
x-pack/plugins/streams @simianhacker @flash1293 @dgieselaar
x-pack/plugins/streams_app @simianhacker @flash1293 @dgieselaar
x-pack/plugins/task_manager @elastic/response-ops
x-pack/plugins/telemetry_collection_xpack @elastic/kibana-core
x-pack/plugins/threat_intelligence @elastic/security-threat-hunting-investigations
Expand Down
4 changes: 4 additions & 0 deletions docs/developer/plugin-list.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,10 @@ routes, etc.
|This plugin provides an interface to manage streams
|{kib-repo}blob/{branch}/x-pack/plugins/streams_app/README.md[streamsApp]
|Home of the Streams app plugin, which allows users to manage Streams via the UI.
|{kib-repo}blob/{branch}/x-pack/plugins/observability_solution/synthetics/README.md[synthetics]
|The purpose of this plugin is to provide users of Heartbeat more visibility of what's happening
in their infrastructure.
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,7 @@
"@kbn/status-plugin-a-plugin": "link:test/server_integration/plugins/status_plugin_a",
"@kbn/status-plugin-b-plugin": "link:test/server_integration/plugins/status_plugin_b",
"@kbn/std": "link:packages/kbn-std",
"@kbn/streams-app-plugin": "link:x-pack/plugins/streams_app",
"@kbn/streams-plugin": "link:x-pack/plugins/streams",
"@kbn/synthetics-plugin": "link:x-pack/plugins/observability_solution/synthetics",
"@kbn/synthetics-private-location": "link:x-pack/packages/kbn-synthetics-private-location",
Expand Down
2 changes: 2 additions & 0 deletions packages/deeplinks/observability/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ export const OBLT_UX_APP_ID = 'ux';
export const OBLT_PROFILING_APP_ID = 'profiling';

export const INVENTORY_APP_ID = 'inventory';

export const STREAMS_APP_ID = 'streams';
13 changes: 10 additions & 3 deletions packages/deeplinks/observability/deep_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
OBLT_UX_APP_ID,
OBLT_PROFILING_APP_ID,
INVENTORY_APP_ID,
STREAMS_APP_ID,
} from './constants';

type LogsApp = typeof LOGS_APP_ID;
Expand All @@ -36,6 +37,7 @@ type AiAssistantApp = typeof AI_ASSISTANT_APP_ID;
type ObltUxApp = typeof OBLT_UX_APP_ID;
type ObltProfilingApp = typeof OBLT_PROFILING_APP_ID;
type InventoryApp = typeof INVENTORY_APP_ID;
type StreamsApp = typeof STREAMS_APP_ID;

export type AppId =
| LogsApp
Expand All @@ -50,7 +52,8 @@ export type AppId =
| AiAssistantApp
| ObltUxApp
| ObltProfilingApp
| InventoryApp;
| InventoryApp
| StreamsApp;

export type LogsLinkId = 'log-categories' | 'settings' | 'anomalies' | 'stream';

Expand Down Expand Up @@ -83,13 +86,16 @@ export type SyntheticsLinkId = 'certificates' | 'overview';

export type ProfilingLinkId = 'stacktraces' | 'flamegraphs' | 'functions';

export type StreamsLinkId = 'overview';

export type LinkId =
| LogsLinkId
| ObservabilityOverviewLinkId
| MetricsLinkId
| ApmLinkId
| SyntheticsLinkId
| ProfilingLinkId;
| ProfilingLinkId
| StreamsLinkId;

export type DeepLinkId =
| AppId
Expand All @@ -99,4 +105,5 @@ export type DeepLinkId =
| `${ApmApp}:${ApmLinkId}`
| `${SyntheticsApp}:${SyntheticsLinkId}`
| `${ObltProfilingApp}:${ProfilingLinkId}`
| `${InventoryApp}:${InventoryLinkId}`;
| `${InventoryApp}:${InventoryLinkId}`
| `${StreamsApp}:${StreamsLinkId}`;
2 changes: 1 addition & 1 deletion packages/kbn-es-types/src/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -695,5 +695,5 @@ export interface ESQLSearchParams {
locale?: string;
include_ccs_metadata?: boolean;
dropNullColumns?: boolean;
params?: Array<Record<string, string | undefined>>;
params?: estypesWithoutBodyKey.ScalarValue[] | Array<Record<string, string | undefined>>;
}
1 change: 1 addition & 0 deletions packages/kbn-optimizer/limits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ pageLoadAssetSize:
stackAlerts: 58316
stackConnectors: 67227
streams: 16742
streamsApp: 20537
synthetics: 55971
telemetry: 51957
telemetryManagementSection: 38586
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import {
} from '@kbn/server-route-repository-utils';
import { httpResponseIntoObservable } from '@kbn/sse-utils-client';
import { from } from 'rxjs';
import { HttpFetchOptions, HttpFetchQuery, HttpResponse } from '@kbn/core-http-browser';
import { HttpFetchQuery, HttpResponse } from '@kbn/core-http-browser';
import { omit } from 'lodash';

export function createRepositoryClient<
TRepository extends ServerRouteRepository,
TClientOptions extends HttpFetchOptions = {}
TClientOptions extends Record<string, any> = {}
>(core: CoreStart | CoreSetup): RouteRepositoryClient<TRepository, TClientOptions> {
const fetch = (
endpoint: string,
Expand Down
1 change: 0 additions & 1 deletion packages/kbn-server-route-repository-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export type {
EndpointOf,
ReturnOf,
RouteRepositoryClient,
RouteState,
ClientRequestParamsOf,
DecodedRequestParamsOf,
ServerRouteRepository,
Expand Down
12 changes: 5 additions & 7 deletions packages/kbn-server-route-repository-utils/src/parse_endpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,20 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

type Method = 'get' | 'post' | 'put' | 'patch' | 'delete';
import type { RouteMethod } from '@kbn/core-http-server';

const validMethods: RouteMethod[] = ['delete', 'get', 'patch', 'post', 'put'];

export function parseEndpoint(endpoint: string) {
const parts = endpoint.split(' ');

const method = parts[0].trim().toLowerCase() as Method;
const method = parts[0].trim().toLowerCase() as Exclude<RouteMethod, 'options'>;
const pathname = parts[1].trim();
const version = parts[2]?.trim();

if (!['get', 'post', 'put', 'patch', 'delete'].includes(method)) {
if (!validMethods.includes(method)) {
throw new Error(`Endpoint ${endpoint} was not prefixed with a valid HTTP method`);
}

if (!version && pathname.startsWith('/api')) {
throw new Error(`Missing version for public endpoint ${endpoint}`);
}

return { method, pathname, version };
}
95 changes: 54 additions & 41 deletions packages/kbn-server-route-repository-utils/src/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,21 @@
*/

import type { HttpFetchOptions } from '@kbn/core-http-browser';
import type { IKibanaResponse } from '@kbn/core-http-server';
import type { IKibanaResponse, RouteAccess, RouteSecurity } from '@kbn/core-http-server';
import type {
KibanaRequest,
KibanaResponseFactory,
Logger,
RequestHandlerContext,
RouteConfigOptions,
RouteSecurity,
RouteMethod,
} from '@kbn/core/server';
import type { ServerSentEvent } from '@kbn/sse-utils';
import { z } from '@kbn/zod';
import * as t from 'io-ts';
import { Observable } from 'rxjs';
import { Readable } from 'stream';
import { RequiredKeys, ValuesType } from 'utility-types';
import { Required, RequiredKeys, ValuesType } from 'utility-types';

type MaybeOptional<T extends { params?: Record<string, any> }> = RequiredKeys<
T['params']
Expand Down Expand Up @@ -51,24 +50,37 @@ export type ZodParamsObject = z.ZodObject<{
export type IoTsParamsObject = WithoutIncompatibleMethods<t.Type<RouteParams>>;

export type RouteParamsRT = IoTsParamsObject | ZodParamsObject;
export type ServerRouteHandlerResources = Record<string, any>;

export interface RouteState {
[endpoint: string]: ServerRoute<any, any, any, any, any>;
export interface ServerRouteCreateOptions {
[x: string]: any;
}

export type ServerRouteHandlerResources = Record<string, any>;
export type ServerRouteCreateOptions = Record<string, any>;
type RouteMethodOf<TEndpoint extends string> = TEndpoint extends `${infer TRouteMethod} ${string}`
? Lowercase<TRouteMethod> extends RouteMethod
? Lowercase<TRouteMethod>
: never
: never;

type ValidateEndpoint<TEndpoint extends string> = string extends TEndpoint
type IsPublicEndpoint<
TEndpoint extends string,
TRouteAccess extends RouteAccess | undefined
> = TRouteAccess extends 'public'
? true
: TEndpoint extends `${string} ${string} ${string}`
: TRouteAccess extends 'internal'
? false
: TEndpoint extends `${string} /api${string}`
? true
: TEndpoint extends `${string} ${infer TPathname}`
? TPathname extends `/internal/${string}`
? true
: false
: false;

type IsVersionSpecified<TEndpoint extends string> =
TEndpoint extends `${string} ${string} ${string}` ? true : false;

type ValidateEndpoint<
TEndpoint extends string,
TRouteAccess extends RouteAccess | undefined
> = IsPublicEndpoint<TEndpoint, TRouteAccess> extends true ? IsVersionSpecified<TEndpoint> : true;

type IsAny<T> = 1 | 0 extends (T extends never ? 1 : 0) ? true : false;

// this ensures only plain objects can be returned, if it's not one
Expand Down Expand Up @@ -128,17 +140,27 @@ type ServerRouteHandler<

export type CreateServerRouteFactory<
TRouteHandlerResources extends ServerRouteHandlerResources,
TRouteCreateOptions extends ServerRouteCreateOptions
TRouteCreateOptions extends DefaultRouteCreateOptions | undefined
> = <
TEndpoint extends string,
TReturnType extends ServerRouteHandlerReturnType,
TRouteParamsRT extends RouteParamsRT | undefined = undefined
TRouteParamsRT extends RouteParamsRT | undefined = undefined,
TRouteAccess extends RouteAccess | undefined = undefined
>(
options: {
endpoint: ValidateEndpoint<TEndpoint> extends true ? TEndpoint : never;
endpoint: ValidateEndpoint<TEndpoint, TRouteAccess> extends true ? TEndpoint : never;
handler: ServerRouteHandler<TRouteHandlerResources, TRouteParamsRT, TReturnType>;
params?: TRouteParamsRT;
} & TRouteCreateOptions
security?: RouteSecurity;
} & Required<
{
options?: (TRouteCreateOptions extends DefaultRouteCreateOptions ? TRouteCreateOptions : {}) &
RouteConfigOptions<RouteMethodOf<TEndpoint>> & {
access?: TRouteAccess;
};
},
RequiredKeys<TRouteCreateOptions> extends never ? never : 'options'
>
) => Record<
TEndpoint,
ServerRoute<
Expand All @@ -155,16 +177,17 @@ export type ServerRoute<
TRouteParamsRT extends RouteParamsRT | undefined,
TRouteHandlerResources extends ServerRouteHandlerResources,
TReturnType extends ServerRouteHandlerReturnType,
TRouteCreateOptions extends ServerRouteCreateOptions
TRouteCreateOptions extends DefaultRouteCreateOptions | undefined
> = {
endpoint: TEndpoint;
handler: ServerRouteHandler<TRouteHandlerResources, TRouteParamsRT, TReturnType>;
} & TRouteCreateOptions &
(TRouteParamsRT extends RouteParamsRT ? { params: TRouteParamsRT } : {});
security?: RouteSecurity;
} & (TRouteParamsRT extends RouteParamsRT ? { params: TRouteParamsRT } : {}) &
(TRouteCreateOptions extends DefaultRouteCreateOptions ? { options: TRouteCreateOptions } : {});

export type ServerRouteRepository = Record<
string,
ServerRoute<string, RouteParamsRT | undefined, any, any, Record<string, any>>
ServerRoute<string, RouteParamsRT | undefined, any, any, ServerRouteCreateOptions | undefined>
>;

type ClientRequestParamsOfType<TRouteParamsRT extends RouteParamsRT> =
Expand Down Expand Up @@ -195,13 +218,7 @@ export type EndpointOf<TServerRouteRepository extends ServerRouteRepository> =
export type ReturnOf<
TServerRouteRepository extends ServerRouteRepository,
TEndpoint extends keyof TServerRouteRepository
> = TServerRouteRepository[TEndpoint] extends ServerRoute<
any,
any,
any,
infer TReturnType,
ServerRouteCreateOptions
>
> = TServerRouteRepository[TEndpoint] extends ServerRoute<any, any, any, infer TReturnType, any>
? TReturnType extends IKibanaResponse<infer TWrappedResponseType>
? TWrappedResponseType
: TReturnType
Expand All @@ -210,13 +227,7 @@ export type ReturnOf<
export type DecodedRequestParamsOf<
TServerRouteRepository extends ServerRouteRepository,
TEndpoint extends keyof TServerRouteRepository
> = TServerRouteRepository[TEndpoint] extends ServerRoute<
any,
infer TRouteParamsRT,
any,
any,
ServerRouteCreateOptions
>
> = TServerRouteRepository[TEndpoint] extends ServerRoute<any, infer TRouteParamsRT, any, any, any>
? TRouteParamsRT extends RouteParamsRT
? DecodedRequestParamsOfType<TRouteParamsRT>
: {}
Expand All @@ -230,7 +241,7 @@ export type ClientRequestParamsOf<
infer TRouteParamsRT,
any,
any,
ServerRouteCreateOptions
ServerRouteCreateOptions | undefined
>
? TRouteParamsRT extends RouteParamsRT
? ClientRequestParamsOfType<TRouteParamsRT>
Expand All @@ -250,13 +261,17 @@ export interface RouteRepositoryClient<
fetch<TEndpoint extends Extract<keyof TServerRouteRepository, string>>(
endpoint: TEndpoint,
...args: MaybeOptionalArgs<
ClientRequestParamsOf<TServerRouteRepository, TEndpoint> & TAdditionalClientOptions
ClientRequestParamsOf<TServerRouteRepository, TEndpoint> &
TAdditionalClientOptions &
HttpFetchOptions
>
): Promise<ReturnOf<TServerRouteRepository, TEndpoint>>;
stream<TEndpoint extends Extract<keyof TServerRouteRepository, string>>(
endpoint: TEndpoint,
...args: MaybeOptionalArgs<
ClientRequestParamsOf<TServerRouteRepository, TEndpoint> & TAdditionalClientOptions
ClientRequestParamsOf<TServerRouteRepository, TEndpoint> &
TAdditionalClientOptions &
HttpFetchOptions
>
): ReturnOf<TServerRouteRepository, TEndpoint> extends Observable<infer TReturnType>
? TReturnType extends ServerSentEvent
Expand All @@ -277,6 +292,4 @@ export interface DefaultRouteHandlerResources extends CoreRouteHandlerResources
logger: Logger;
}

export interface DefaultRouteCreateOptions {
options?: RouteConfigOptions<RouteMethod> & { security?: RouteSecurity };
}
export type DefaultRouteCreateOptions = RouteConfigOptions<Exclude<RouteMethod, 'options'>>;
1 change: 0 additions & 1 deletion packages/kbn-server-route-repository/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export type {
ServerRouteRepository,
ServerRoute,
RouteParamsRT,
RouteState,
DefaultRouteCreateOptions,
DefaultRouteHandlerResources,
IoTsParamsObject,
Expand Down
Loading

0 comments on commit 63da770

Please sign in to comment.