[Logs UI] <LogStream /> as a kibana embeddable (#88618)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
fb19aab307
commit
53637d0158
|
@ -34,7 +34,7 @@ pageLoadAssetSize:
|
||||||
indexLifecycleManagement: 107090
|
indexLifecycleManagement: 107090
|
||||||
indexManagement: 140608
|
indexManagement: 140608
|
||||||
indexPatternManagement: 154222
|
indexPatternManagement: 154222
|
||||||
infra: 197873
|
infra: 204800
|
||||||
fleet: 415829
|
fleet: 415829
|
||||||
ingestPipelines: 58003
|
ingestPipelines: 58003
|
||||||
inputControlVis: 172675
|
inputControlVis: 172675
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
"features",
|
"features",
|
||||||
"usageCollection",
|
"usageCollection",
|
||||||
"spaces",
|
"spaces",
|
||||||
|
"embeddable",
|
||||||
"data",
|
"data",
|
||||||
"dataEnhanced",
|
"dataEnhanced",
|
||||||
"visTypeTimeseries",
|
"visTypeTimeseries",
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './log_stream';
|
|
@ -5,9 +5,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { LogStreamProps } from './';
|
import type { LogStreamProps } from './log_stream';
|
||||||
|
|
||||||
const LazyLogStream = React.lazy(() => import('./'));
|
const LazyLogStream = React.lazy(() => import('./log_stream'));
|
||||||
|
|
||||||
export const LazyLogStreamWrapper: React.FC<LogStreamProps> = (props) => (
|
export const LazyLogStreamWrapper: React.FC<LogStreamProps> = (props) => (
|
||||||
<React.Suspense fallback={<div />}>
|
<React.Suspense fallback={<div />}>
|
||||||
|
|
|
@ -17,6 +17,7 @@ import { useLogStream } from '../../containers/logs/log_stream';
|
||||||
import { ScrollableLogTextStreamView } from '../logging/log_text_stream';
|
import { ScrollableLogTextStreamView } from '../logging/log_text_stream';
|
||||||
import { LogColumnRenderConfiguration } from '../../utils/log_column_render_configuration';
|
import { LogColumnRenderConfiguration } from '../../utils/log_column_render_configuration';
|
||||||
import { JsonValue } from '../../../../../../src/plugins/kibana_utils/common';
|
import { JsonValue } from '../../../../../../src/plugins/kibana_utils/common';
|
||||||
|
import { Query } from '../../../../../../src/plugins/data/common';
|
||||||
|
|
||||||
const PAGE_THRESHOLD = 2;
|
const PAGE_THRESHOLD = 2;
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ export interface LogStreamProps {
|
||||||
sourceId?: string;
|
sourceId?: string;
|
||||||
startTimestamp: number;
|
startTimestamp: number;
|
||||||
endTimestamp: number;
|
endTimestamp: number;
|
||||||
query?: string;
|
query?: string | Query;
|
||||||
center?: LogEntryCursor;
|
center?: LogEntryCursor;
|
||||||
highlight?: string;
|
highlight?: string;
|
||||||
height?: string | number;
|
height?: string | number;
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* 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 React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import { CoreStart } from 'kibana/public';
|
||||||
|
|
||||||
|
import { I18nProvider } from '@kbn/i18n/react';
|
||||||
|
import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public';
|
||||||
|
import { EuiThemeProvider } from '../../../../../../src/plugins/kibana_react/common';
|
||||||
|
import { Query, TimeRange } from '../../../../../../src/plugins/data/public';
|
||||||
|
import {
|
||||||
|
Embeddable,
|
||||||
|
EmbeddableInput,
|
||||||
|
IContainer,
|
||||||
|
} from '../../../../../../src/plugins/embeddable/public';
|
||||||
|
import { datemathToEpochMillis } from '../../utils/datemath';
|
||||||
|
import { LazyLogStreamWrapper } from './lazy_log_stream_wrapper';
|
||||||
|
|
||||||
|
export const LOG_STREAM_EMBEDDABLE = 'LOG_STREAM_EMBEDDABLE';
|
||||||
|
|
||||||
|
export interface LogStreamEmbeddableInput extends EmbeddableInput {
|
||||||
|
timeRange: TimeRange;
|
||||||
|
query: Query;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LogStreamEmbeddable extends Embeddable<LogStreamEmbeddableInput> {
|
||||||
|
public readonly type = LOG_STREAM_EMBEDDABLE;
|
||||||
|
private node?: HTMLElement;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private services: CoreStart,
|
||||||
|
initialInput: LogStreamEmbeddableInput,
|
||||||
|
parent?: IContainer
|
||||||
|
) {
|
||||||
|
super(initialInput, {}, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(node: HTMLElement) {
|
||||||
|
if (this.node) {
|
||||||
|
ReactDOM.unmountComponentAtNode(this.node);
|
||||||
|
}
|
||||||
|
this.node = node;
|
||||||
|
|
||||||
|
this.renderComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public reload() {
|
||||||
|
this.renderComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public destroy() {
|
||||||
|
super.destroy();
|
||||||
|
if (this.node) {
|
||||||
|
ReactDOM.unmountComponentAtNode(this.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderComponent() {
|
||||||
|
if (!this.node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const startTimestamp = datemathToEpochMillis(this.input.timeRange.from);
|
||||||
|
const endTimestamp = datemathToEpochMillis(this.input.timeRange.to);
|
||||||
|
|
||||||
|
if (!startTimestamp || !endTimestamp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<I18nProvider>
|
||||||
|
<EuiThemeProvider>
|
||||||
|
<KibanaContextProvider services={this.services}>
|
||||||
|
<div style={{ width: '100%' }}>
|
||||||
|
<LazyLogStreamWrapper
|
||||||
|
startTimestamp={startTimestamp}
|
||||||
|
endTimestamp={endTimestamp}
|
||||||
|
height="100%"
|
||||||
|
query={this.input.query}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</KibanaContextProvider>
|
||||||
|
</EuiThemeProvider>
|
||||||
|
</I18nProvider>,
|
||||||
|
this.node
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { CoreStart } from 'kibana/public';
|
||||||
|
import {
|
||||||
|
EmbeddableFactoryDefinition,
|
||||||
|
IContainer,
|
||||||
|
} from '../../../../../../src/plugins/embeddable/public';
|
||||||
|
import {
|
||||||
|
LogStreamEmbeddable,
|
||||||
|
LOG_STREAM_EMBEDDABLE,
|
||||||
|
LogStreamEmbeddableInput,
|
||||||
|
} from './log_stream_embeddable';
|
||||||
|
|
||||||
|
export class LogStreamEmbeddableFactoryDefinition
|
||||||
|
implements EmbeddableFactoryDefinition<LogStreamEmbeddableInput> {
|
||||||
|
public readonly type = LOG_STREAM_EMBEDDABLE;
|
||||||
|
|
||||||
|
constructor(private getCoreServices: () => Promise<CoreStart>) {}
|
||||||
|
|
||||||
|
public async isEditable() {
|
||||||
|
const { application } = await this.getCoreServices();
|
||||||
|
return application.capabilities.logs.save as boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async create(initialInput: LogStreamEmbeddableInput, parent?: IContainer) {
|
||||||
|
const services = await this.getCoreServices();
|
||||||
|
return new LogStreamEmbeddable(services, initialInput, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDisplayName() {
|
||||||
|
return 'Log stream';
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@
|
||||||
import { useMemo, useEffect } from 'react';
|
import { useMemo, useEffect } from 'react';
|
||||||
import useSetState from 'react-use/lib/useSetState';
|
import useSetState from 'react-use/lib/useSetState';
|
||||||
import usePrevious from 'react-use/lib/usePrevious';
|
import usePrevious from 'react-use/lib/usePrevious';
|
||||||
import { esKuery } from '../../../../../../../src/plugins/data/public';
|
import { esKuery, esQuery, Query } from '../../../../../../../src/plugins/data/public';
|
||||||
import { fetchLogEntries } from '../log_entries/api/fetch_log_entries';
|
import { fetchLogEntries } from '../log_entries/api/fetch_log_entries';
|
||||||
import { useTrackedPromise } from '../../../utils/use_tracked_promise';
|
import { useTrackedPromise } from '../../../utils/use_tracked_promise';
|
||||||
import { LogEntryCursor, LogEntry } from '../../../../common/log_entry';
|
import { LogEntryCursor, LogEntry } from '../../../../common/log_entry';
|
||||||
|
@ -18,7 +18,7 @@ interface LogStreamProps {
|
||||||
sourceId: string;
|
sourceId: string;
|
||||||
startTimestamp: number;
|
startTimestamp: number;
|
||||||
endTimestamp: number;
|
endTimestamp: number;
|
||||||
query?: string;
|
query?: string | Query;
|
||||||
center?: LogEntryCursor;
|
center?: LogEntryCursor;
|
||||||
columns?: LogSourceConfigurationProperties['logColumns'];
|
columns?: LogSourceConfigurationProperties['logColumns'];
|
||||||
}
|
}
|
||||||
|
@ -84,9 +84,21 @@ export function useLogStream({
|
||||||
}, [prevEndTimestamp, endTimestamp, setState]);
|
}, [prevEndTimestamp, endTimestamp, setState]);
|
||||||
|
|
||||||
const parsedQuery = useMemo(() => {
|
const parsedQuery = useMemo(() => {
|
||||||
return query
|
if (!query) {
|
||||||
? JSON.stringify(esKuery.toElasticsearchQuery(esKuery.fromKueryExpression(query)))
|
return null;
|
||||||
: null;
|
}
|
||||||
|
|
||||||
|
let q;
|
||||||
|
|
||||||
|
if (typeof query === 'string') {
|
||||||
|
q = esKuery.toElasticsearchQuery(esKuery.fromKueryExpression(query));
|
||||||
|
} else if (query.language === 'kuery') {
|
||||||
|
q = esKuery.toElasticsearchQuery(esKuery.fromKueryExpression(query.query as string));
|
||||||
|
} else if (query.language === 'lucene') {
|
||||||
|
q = esQuery.luceneStringToDsl(query.query as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.stringify(q);
|
||||||
}, [query]);
|
}, [query]);
|
||||||
|
|
||||||
// Callbacks
|
// Callbacks
|
||||||
|
|
|
@ -19,6 +19,8 @@ import {
|
||||||
} from './types';
|
} from './types';
|
||||||
import { getLogsHasDataFetcher, getLogsOverviewDataFetcher } from './utils/logs_overview_fetchers';
|
import { getLogsHasDataFetcher, getLogsOverviewDataFetcher } from './utils/logs_overview_fetchers';
|
||||||
import { createMetricsHasData, createMetricsFetchData } from './metrics_overview_fetchers';
|
import { createMetricsHasData, createMetricsFetchData } from './metrics_overview_fetchers';
|
||||||
|
import { LOG_STREAM_EMBEDDABLE } from './components/log_stream/log_stream_embeddable';
|
||||||
|
import { LogStreamEmbeddableFactoryDefinition } from './components/log_stream/log_stream_embeddable_factory';
|
||||||
|
|
||||||
export class Plugin implements InfraClientPluginClass {
|
export class Plugin implements InfraClientPluginClass {
|
||||||
constructor(_context: PluginInitializerContext) {}
|
constructor(_context: PluginInitializerContext) {}
|
||||||
|
@ -46,6 +48,13 @@ export class Plugin implements InfraClientPluginClass {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getCoreServices = async () => (await core.getStartServices())[0];
|
||||||
|
|
||||||
|
pluginsSetup.embeddable.registerEmbeddableFactory(
|
||||||
|
LOG_STREAM_EMBEDDABLE,
|
||||||
|
new LogStreamEmbeddableFactoryDefinition(getCoreServices)
|
||||||
|
);
|
||||||
|
|
||||||
core.application.register({
|
core.application.register({
|
||||||
id: 'logs',
|
id: 'logs',
|
||||||
title: i18n.translate('xpack.infra.logs.pluginTitle', {
|
title: i18n.translate('xpack.infra.logs.pluginTitle', {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import type { CoreSetup, CoreStart, Plugin as PluginClass } from 'kibana/public';
|
import type { CoreSetup, CoreStart, Plugin as PluginClass } from 'kibana/public';
|
||||||
import type { DataPublicPluginStart } from '../../../../src/plugins/data/public';
|
import type { DataPublicPluginStart } from '../../../../src/plugins/data/public';
|
||||||
import type { HomePublicPluginSetup } from '../../../../src/plugins/home/public';
|
import type { HomePublicPluginSetup } from '../../../../src/plugins/home/public';
|
||||||
|
import type { EmbeddableSetup } from '../../../../src/plugins/embeddable/public';
|
||||||
import type {
|
import type {
|
||||||
UsageCollectionSetup,
|
UsageCollectionSetup,
|
||||||
UsageCollectionStart,
|
UsageCollectionStart,
|
||||||
|
@ -33,6 +34,7 @@ export interface InfraClientSetupDeps {
|
||||||
observability: ObservabilityPluginSetup;
|
observability: ObservabilityPluginSetup;
|
||||||
triggersActionsUi: TriggersAndActionsUIPublicPluginSetup;
|
triggersActionsUi: TriggersAndActionsUIPublicPluginSetup;
|
||||||
usageCollection: UsageCollectionSetup;
|
usageCollection: UsageCollectionSetup;
|
||||||
|
embeddable: EmbeddableSetup;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InfraClientStartDeps {
|
export interface InfraClientStartDeps {
|
||||||
|
|
Loading…
Reference in a new issue