Skip to content

Commit

Permalink
[APM][Infrastructure UI] Enables log flyouts on APM logs tables (#132617
Browse files Browse the repository at this point in the history
)

* provides a way for LogStream component to show log flyouts

* move open flyout logic to a hook; fix flyout remaining open after moving to another page

* rename flyoutEnabled property

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
crespocarlos and kibanamachine authored May 25, 2022
1 parent cb403a6 commit a7e2bb1
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export function ServiceLogs() {
startTimestamp={moment(start).valueOf()}
endTimestamp={moment(end).valueOf()}
query={getInfrastructureKQLFilter(data, serviceName)}
showFlyoutAction
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ function LogsTabContent({ transaction }: { transaction: Transaction }) {
},
{ type: 'message' },
]}
showFlyoutAction
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ This will show a list of log entries between the specified timestamps.

## Query log entries

You might want to show specific log entries in your plugin. Maybe you want to show log lines from a specific host, or for an AMP trace. The LogStream component supports both `query` and `filters`, and these are the standard `es-query` types.
You might want to show specific log entries in your plugin. Maybe you want to show log lines from a specific host, or for an AMP trace. The LogStream component supports both `query` and `filters`, and these are the standard `es-query` types.

### Query

The component has a `query` prop that accepts a valid es-query `query`. You can either supply this with a `language` and `query` property, or you can just supply a string which is a shortcut for KQL expressions.
The component has a `query` prop that accepts a valid es-query `query`. You can either supply this with a `language` and `query` property, or you can just supply a string which is a shortcut for KQL expressions.

```tsx
<LogStream
Expand Down Expand Up @@ -73,8 +73,8 @@ The component also has a `filters` prop that accepts valid es-query `filters`. T
disabled: false,
negate: false,
},
}]
}
},
]}
/>
```

Expand Down Expand Up @@ -248,4 +248,18 @@ class MyPlugin {
### Setting component height
It's possible to pass a `height` prop, e.g. `60vh` or `300px`, to specify how much vertical space the component should consume.
It's possible to pass a `height` prop, e.g. `60vh` or `300px`, to specify how much vertical space the component should consume.
### With a `showFlyoutAction` prop
The component can render a button on the row that opens a flyout, via the `showFlyoutAction` prop. The flyout will display the log details for that each entry
```tsx
<LogStream
sourceId="my_source"
startTimestamp={...}
endTimestamp={...}
showFlyoutAction />
```
<Story id="infra-logstream--flyout" />
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,8 @@ CustomColumnRendering.args = {
{ type: 'message' },
],
};

export const Flyout = LogStreamStoryTemplate.bind({});
Flyout.args = {
showFlyoutAction: true,
};
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,12 @@ export const decorateWithKibanaContext = <StoryFnReactReturnType extends React.R
get$: () => new Subject(),
};

const overlays = {
openFlyout: () => {},
};

return (
<KibanaContextProvider services={{ data, http, uiSettings }}>
<KibanaContextProvider services={{ data, http, uiSettings, overlays }}>
{wrappedStory()}
</KibanaContextProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { LogColumnRenderConfiguration } from '../../utils/log_column_render_conf
import { useKibanaQuerySettings } from '../../utils/use_kibana_query_settings';
import { ScrollableLogTextStreamView } from '../logging/log_text_stream';
import { LogStreamErrorBoundary } from './log_stream_error_boundary';
import { useLogEntryFlyout } from '../logging/log_entry_flyout';

interface LogStreamPluginDeps {
data: DataPublicPluginStart;
Expand Down Expand Up @@ -72,6 +73,7 @@ interface LogStreamContentProps {
center?: LogEntryCursor;
highlight?: string;
columns?: LogColumnDefinition[];
showFlyoutAction?: boolean;
}

export const LogStream: React.FC<LogStreamProps> = ({ height = 400, ...contentProps }) => {
Expand All @@ -93,6 +95,7 @@ export const LogStreamContent: React.FC<LogStreamContentProps> = ({
center,
highlight,
columns,
showFlyoutAction = false,
}) => {
const customColumns = useMemo(
() => (columns ? convertLogColumnDefinitionToLogSourceColumnDefinition(columns) : undefined),
Expand All @@ -112,6 +115,8 @@ Read more at https://github.com/elastic/kibana/blob/main/src/plugins/kibana_reac
);
}

const { openLogEntryFlyout } = useLogEntryFlyout(sourceId);

const kibanaQuerySettings = useKibanaQuerySettings();

const logViews = useMemo(
Expand Down Expand Up @@ -223,6 +228,7 @@ Read more at https://github.com/elastic/kibana/blob/main/src/plugins/kibana_reac
jumpToTarget={noop}
reportVisibleInterval={handlePagination}
reloadItems={fetchEntries}
onOpenLogEntryFlyout={showFlyoutAction ? openLogEntryFlyout : undefined}
highlightedItem={highlight ?? null}
currentHighlightKey={null}
startDateExpression={''}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ import { LogEntry } from '../../../../common/search_strategies/log_entries/log_e

const UPTIME_FIELDS = ['container.id', 'host.ip', 'kubernetes.pod.uid'];

export const LogEntryActionsMenu: React.FunctionComponent<{
export interface LogEntryActionsMenuProps {
logEntry: LogEntry;
}> = ({ logEntry }) => {
const { hide, isVisible, show } = useVisibilityState(false);
}

export const LogEntryActionsMenu = ({ logEntry }: LogEntryActionsMenuProps) => {
const { hide, isVisible, toggle } = useVisibilityState(false);

const apmLinkDescriptor = useMemo(() => getAPMLink(logEntry), [logEntry]);
const uptimeLinkDescriptor = useMemo(() => getUptimeLink(logEntry), [logEntry]);
Expand Down Expand Up @@ -73,7 +75,7 @@ export const LogEntryActionsMenu: React.FunctionComponent<{
disabled={!hasMenuItems}
iconSide="right"
iconType="arrowDown"
onClick={show}
onClick={toggle}
>
<FormattedMessage
id="xpack.infra.logEntryActionsMenu.buttonLabel"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import React, { useEffect } from 'react';
import type { Query } from '@kbn/es-query';
import React, { useCallback, useEffect, useRef } from 'react';
import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public';
import { OverlayRef } from '@kbn/core/public';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
import { TimeKey } from '../../../../common/time';
import { useLogEntry } from '../../../containers/logs/log_entry';
import { CenteredEuiFlyoutBody } from '../../centered_flyout_body';
Expand All @@ -34,6 +38,51 @@ export interface LogEntryFlyoutProps {
sourceId: string | null | undefined;
}

export const useLogEntryFlyout = (sourceId: string) => {
const flyoutRef = useRef<OverlayRef>();
const {
services: { http, data, uiSettings, application },
overlays: { openFlyout },
} = useKibana<{ data: DataPublicPluginStart }>();

const closeLogEntryFlyout = useCallback(() => {
flyoutRef.current?.close();
}, []);

const openLogEntryFlyout = useCallback(
(logEntryId) => {
const { Provider: KibanaReactContextProvider } = createKibanaReactContext({
http,
data,
uiSettings,
application,
});

flyoutRef.current = openFlyout(
<KibanaReactContextProvider>
<LogEntryFlyout
logEntryId={logEntryId}
onCloseFlyout={closeLogEntryFlyout}
sourceId={sourceId}
/>
</KibanaReactContextProvider>
);
},
[http, data, uiSettings, application, openFlyout, sourceId, closeLogEntryFlyout]
);

useEffect(() => {
return () => {
closeLogEntryFlyout();
};
}, [closeLogEntryFlyout]);

return {
openLogEntryFlyout,
closeLogEntryFlyout,
};
};

export const LogEntryFlyout = ({
logEntryId,
onCloseFlyout,
Expand Down

0 comments on commit a7e2bb1

Please sign in to comment.