Skip to content

Commit

Permalink
[Logs and Metrics UI] Initial setup for registering observability ove…
Browse files Browse the repository at this point in the history
…rview data fetchers (#69999)

* Switches mount callbacks to only use start deps

Fixes #58014

* Sets up skeleton logs data fetchers for overview

* Fixes type hacks for logs fetcher

* Prevent kibana from crashing on initial load

* Fixes types and linting errors

* Fixes some linting import/export issues

Co-authored-by: Alejandro Fernández Gómez <alejandro.fernandez@elastic.co>
  • Loading branch information
jasonrhodes and Alejandro Fernández Gómez committed Jun 30, 2020
1 parent 2118439 commit bb7bc78
Show file tree
Hide file tree
Showing 16 changed files with 201 additions and 90 deletions.
2 changes: 1 addition & 1 deletion src/plugins/usage_collection/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { PluginInitializerContext } from '../../../core/public';
import { UsageCollectionPlugin } from './plugin';

export { METRIC_TYPE } from '@kbn/analytics';
export { UsageCollectionSetup } from './plugin';
export { UsageCollectionSetup, UsageCollectionStart } from './plugin';

export function plugin(initializerContext: PluginInitializerContext) {
return new UsageCollectionPlugin(initializerContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@

import { i18n } from '@kbn/i18n';
import { sum } from 'lodash';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { FetchDataParams } from '../../../../observability/public/data_handler';
import { ApmFetchDataResponse } from '../../../../observability/public/typings/fetch_data_response';
import {
ApmFetchDataResponse,
FetchDataParams,
} from '../../../../observability/public';
import { callApmApi } from './createCallApmApi';
import { Theme } from '../../utils/get_theme';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { rangeFilter } from '../../../common/utils/range_filter';
import { Coordinates } from '../../../../observability/public/typings/fetch_data_response';
import { Coordinates } from '../../../../observability/public';
import { PROCESSOR_EVENT } from '../../../common/elasticsearch_fieldnames';
import { Setup, SetupTimeRange } from '../helpers/setup_request';
import { ProcessorEvent } from '../../../common/processor_event';
Expand Down
4 changes: 1 addition & 3 deletions x-pack/plugins/infra/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
"alerts",
"triggers_actions_ui"
],
"optionalPlugins": [
"ml"
],
"optionalPlugins": ["ml", "observability"],
"server": true,
"ui": true,
"configPath": ["xpack", "infra"]
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/infra/public/apps/common_providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
KibanaContextProvider,
} from '../../../../../src/plugins/kibana_react/public';
import { TriggersActionsProvider } from '../utils/triggers_actions_context';
import { ClientPluginDeps } from '../types';
import { InfraClientStartDeps } from '../types';
import { TriggersAndActionsUIPublicPluginStart } from '../../../triggers_actions_ui/public';
import { ApolloClientContext } from '../utils/apollo_context';
import { EuiThemeProvider } from '../../../observability/public';
Expand All @@ -37,7 +37,7 @@ export const CommonInfraProviders: React.FC<{

export const CoreProviders: React.FC<{
core: CoreStart;
plugins: ClientPluginDeps;
plugins: InfraClientStartDeps;
}> = ({ children, core, plugins }) => {
return (
<KibanaContextProvider services={{ ...core, ...plugins }}>
Expand Down
6 changes: 3 additions & 3 deletions x-pack/plugins/infra/public/apps/logs_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ import '../index.scss';
import { NotFoundPage } from '../pages/404';
import { LinkToLogsPage } from '../pages/link_to/link_to_logs';
import { LogsPage } from '../pages/logs';
import { ClientPluginDeps } from '../types';
import { InfraClientStartDeps } from '../types';
import { createApolloClient } from '../utils/apollo_client';
import { CommonInfraProviders, CoreProviders } from './common_providers';
import { prepareMountElement } from './common_styles';

export const renderApp = (
core: CoreStart,
plugins: ClientPluginDeps,
plugins: InfraClientStartDeps,
{ element, history }: AppMountParameters
) => {
const apolloClient = createApolloClient(core.http.fetch);
Expand All @@ -43,7 +43,7 @@ const LogsApp: React.FC<{
apolloClient: ApolloClient<{}>;
core: CoreStart;
history: History<unknown>;
plugins: ClientPluginDeps;
plugins: InfraClientStartDeps;
}> = ({ apolloClient, core, history, plugins }) => {
const uiCapabilities = core.application.capabilities;

Expand Down
6 changes: 3 additions & 3 deletions x-pack/plugins/infra/public/apps/metrics_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ import { NotFoundPage } from '../pages/404';
import { LinkToMetricsPage } from '../pages/link_to/link_to_metrics';
import { InfrastructurePage } from '../pages/metrics';
import { MetricDetail } from '../pages/metrics/metric_detail';
import { ClientPluginDeps } from '../types';
import { InfraClientStartDeps } from '../types';
import { createApolloClient } from '../utils/apollo_client';
import { RedirectWithQueryParams } from '../utils/redirect_with_query_params';
import { CommonInfraProviders, CoreProviders } from './common_providers';
import { prepareMountElement } from './common_styles';

export const renderApp = (
core: CoreStart,
plugins: ClientPluginDeps,
plugins: InfraClientStartDeps,
{ element, history }: AppMountParameters
) => {
const apolloClient = createApolloClient(core.http.fetch);
Expand All @@ -45,7 +45,7 @@ const MetricsApp: React.FC<{
apolloClient: ApolloClient<{}>;
core: CoreStart;
history: History<unknown>;
plugins: ClientPluginDeps;
plugins: InfraClientStartDeps;
}> = ({ apolloClient, core, history, plugins }) => {
const uiCapabilities = core.application.capabilities;

Expand Down
17 changes: 11 additions & 6 deletions x-pack/plugins/infra/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@
*/

import { PluginInitializer, PluginInitializerContext } from 'kibana/public';
import { ClientSetup, ClientStart, Plugin } from './plugin';
import { ClientPluginsSetup, ClientPluginsStart } from './types';
import { Plugin } from './plugin';
import {
InfraClientSetupExports,
InfraClientStartExports,
InfraClientSetupDeps,
InfraClientStartDeps,
} from './types';

export const plugin: PluginInitializer<
ClientSetup,
ClientStart,
ClientPluginsSetup,
ClientPluginsStart
InfraClientSetupExports,
InfraClientStartExports,
InfraClientSetupDeps,
InfraClientStartDeps
> = (context: PluginInitializerContext) => {
return new Plugin(context);
};
Expand Down
63 changes: 26 additions & 37 deletions x-pack/plugins/infra/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,40 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
import {
AppMountParameters,
CoreSetup,
CoreStart,
Plugin as PluginClass,
PluginInitializerContext,
} from 'kibana/public';
import { AppMountParameters, PluginInitializerContext } from 'kibana/public';
import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public';
import { createMetricThresholdAlertType } from './alerting/metric_threshold';
import { createInventoryMetricAlertType } from './alerting/inventory';
import { getAlertType as getLogsAlertType } from './components/alerting/logs/log_threshold_alert_type';
import { registerStartSingleton } from './legacy_singletons';
import { registerFeatures } from './register_feature';
import { ClientPluginsSetup, ClientPluginsStart } from './types';

export type ClientSetup = void;
export type ClientStart = void;
import {
InfraClientSetupDeps,
InfraClientStartDeps,
InfraClientCoreSetup,
InfraClientCoreStart,
InfraClientPluginClass,
} from './types';
import { getLogsHasDataFetcher, getLogsOverviewDataFetcher } from './utils/logs_overview_fetchers';

export class Plugin
implements PluginClass<ClientSetup, ClientStart, ClientPluginsSetup, ClientPluginsStart> {
export class Plugin implements InfraClientPluginClass {
constructor(_context: PluginInitializerContext) {}

setup(core: CoreSetup<ClientPluginsStart, ClientStart>, pluginsSetup: ClientPluginsSetup) {
setup(core: InfraClientCoreSetup, pluginsSetup: InfraClientSetupDeps) {
registerFeatures(pluginsSetup.home);

pluginsSetup.triggers_actions_ui.alertTypeRegistry.register(createInventoryMetricAlertType());
pluginsSetup.triggers_actions_ui.alertTypeRegistry.register(getLogsAlertType());
pluginsSetup.triggers_actions_ui.alertTypeRegistry.register(createMetricThresholdAlertType());

if (pluginsSetup.observability) {
pluginsSetup.observability.dashboard.register({
appName: 'infra_logs',
hasData: getLogsHasDataFetcher(core.getStartServices),
fetchData: getLogsOverviewDataFetcher(core.getStartServices),
});
}

core.application.register({
id: 'logs',
title: i18n.translate('xpack.infra.logs.pluginTitle', {
Expand All @@ -43,20 +48,11 @@ export class Plugin
appRoute: '/app/logs',
category: DEFAULT_APP_CATEGORIES.observability,
mount: async (params: AppMountParameters) => {
// mount callback should not use setup dependencies, get start dependencies instead
const [coreStart, pluginsStart] = await core.getStartServices();
const { renderApp } = await import('./apps/logs_app');

return renderApp(
coreStart,
{
data: pluginsStart.data,
dataEnhanced: pluginsSetup.dataEnhanced,
home: pluginsSetup.home,
triggers_actions_ui: pluginsStart.triggers_actions_ui,
usageCollection: pluginsSetup.usageCollection,
},
params
);
return renderApp(coreStart, pluginsStart, params);
},
});

Expand All @@ -70,20 +66,11 @@ export class Plugin
appRoute: '/app/metrics',
category: DEFAULT_APP_CATEGORIES.observability,
mount: async (params: AppMountParameters) => {
// mount callback should not use setup dependencies, get start dependencies instead
const [coreStart, pluginsStart] = await core.getStartServices();
const { renderApp } = await import('./apps/metrics_app');

return renderApp(
coreStart,
{
data: pluginsStart.data,
dataEnhanced: pluginsSetup.dataEnhanced,
home: pluginsSetup.home,
triggers_actions_ui: pluginsStart.triggers_actions_ui,
usageCollection: pluginsSetup.usageCollection,
},
params
);
return renderApp(coreStart, pluginsStart, params);
},
});

Expand All @@ -102,7 +89,9 @@ export class Plugin
});
}

start(core: CoreStart, _plugins: ClientPluginsStart) {
start(core: InfraClientCoreStart, _plugins: InfraClientStartDeps) {
registerStartSingleton(core);
}

stop() {}
}
30 changes: 25 additions & 5 deletions x-pack/plugins/infra/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,42 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { CoreSetup, CoreStart, Plugin as PluginClass } from 'kibana/public';
import { DataPublicPluginStart } from '../../../../src/plugins/data/public';
import { HomePublicPluginSetup } from '../../../../src/plugins/home/public';
import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/public';
import {
UsageCollectionSetup,
UsageCollectionStart,
} from '../../../../src/plugins/usage_collection/public';
import { TriggersAndActionsUIPublicPluginSetup } from '../../../plugins/triggers_actions_ui/public';
import { DataEnhancedSetup } from '../../data_enhanced/public';
import { DataEnhancedSetup, DataEnhancedStart } from '../../data_enhanced/public';
import { ObservabilityPluginSetup, ObservabilityPluginStart } from '../../observability/public';

export interface ClientPluginsSetup {
// Our own setup and start contract values
export type InfraClientSetupExports = void;
export type InfraClientStartExports = void;

export interface InfraClientSetupDeps {
dataEnhanced: DataEnhancedSetup;
home: HomePublicPluginSetup;
observability: ObservabilityPluginSetup;
triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup;
usageCollection: UsageCollectionSetup;
}

export interface ClientPluginsStart {
export interface InfraClientStartDeps {
data: DataPublicPluginStart;
dataEnhanced: DataEnhancedStart;
observability: ObservabilityPluginStart;
triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup;
usageCollection: UsageCollectionStart;
}

export type ClientPluginDeps = ClientPluginsSetup & ClientPluginsStart;
export type InfraClientCoreSetup = CoreSetup<InfraClientStartDeps, InfraClientStartExports>;
export type InfraClientCoreStart = CoreStart;
export type InfraClientPluginClass = PluginClass<
InfraClientSetupExports,
InfraClientStartExports,
InfraClientSetupDeps,
InfraClientStartDeps
>;
93 changes: 93 additions & 0 deletions x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { InfraClientCoreSetup } from '../types';
import { LogsFetchDataResponse } from '../../../observability/public';

export function getLogsHasDataFetcher(getStartServices: InfraClientCoreSetup['getStartServices']) {
return async () => {
// if you need the data plugin, this is how you get it
// const [, startPlugins] = await getStartServices();
// const { data } = startPlugins;

// if you need a core dep, we need to pass in more than just getStartServices

// perform query
return true;
};
}

export function getLogsOverviewDataFetcher(
getStartServices: InfraClientCoreSetup['getStartServices']
) {
return async (): Promise<LogsFetchDataResponse> => {
// if you need the data plugin, this is how you get it
// const [, startPlugins] = await getStartServices();
// const { data } = startPlugins;

// if you need a core dep, we need to pass in more than just getStartServices

// perform query
return {
title: 'Log rate',
appLink: 'TBD', // TODO: what format should this be in, relative I assume?
stats: {
nginx: {
type: 'number',
label: 'nginx',
value: 345341,
},
'elasticsearch.audit': {
type: 'number',
label: 'elasticsearch.audit',
value: 164929,
},
'haproxy.log': {
type: 'number',
label: 'haproxy.log',
value: 51101,
},
},
// Note: My understanding is that these series coordinates will be
// combined into objects that look like:
// { x: timestamp, y: value, g: label (e.g. nginx) }
// so they fit the stacked bar chart API
// https://elastic.github.io/elastic-charts/?path=/story/bar-chart--stacked-with-axis-and-legend
series: {
nginx: {
label: 'nginx',
coordinates: [
{ x: 1593000000000, y: 10014 },
{ x: 1593000900000, y: 12827 },
{ x: 1593001800000, y: 2946 },
{ x: 1593002700000, y: 14298 },
{ x: 1593003600000, y: 4096 },
],
},
'elasticsearch.audit': {
label: 'elasticsearch.audit',
coordinates: [
{ x: 1593000000000, y: 5676 },
{ x: 1593000900000, y: 6783 },
{ x: 1593001800000, y: 2394 },
{ x: 1593002700000, y: 4554 },
{ x: 1593003600000, y: 5659 },
],
},
'haproxy.log': {
label: 'haproxy.log',
coordinates: [
{ x: 1593000000000, y: 9085 },
{ x: 1593000900000, y: 9002 },
{ x: 1593001800000, y: 3940 },
{ x: 1593002700000, y: 5451 },
{ x: 1593003600000, y: 9133 },
],
},
},
};
};
}
Loading

0 comments on commit bb7bc78

Please sign in to comment.