mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Infrastructure UI] add copilot to hosts process (#159413)
## Summary
Add [Copilot
Prompt](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/co_pilot_prompt)
to Hosts processes
I removed the Autosizer component that wrapped this row component which
set a fixed height in the CSS. It was causing problems with how the
prompt renders a response and is constantly changing the height with
each new sentence. I'm not sure why we needed to have a fixed height, so
I removed it. Ideally we could use [EUI expanding
rows](https://elastic.github.io/eui/#/tabular-content/tables#expanding-rows)
style and functionality if possible.
<img width="2306" alt="Screenshot 2023-06-08 at 4 52 33 PM"
src="c3e67b9c
-c542-4844-8c58-90a241c9bb6c">
### How to Test
To test you will need to enable copilot
- Prompt should only show up in Hosts flyout
- Prompt will not be visible unless Copilot is enabled
Ref: https://github.com/elastic/kibana/pull/158678
---------
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
02fab4dece
commit
4d794f5a7b
6 changed files with 206 additions and 93 deletions
|
@ -9,6 +9,8 @@ import { AppMountParameters, CoreStart } from '@kbn/core/public';
|
|||
import React from 'react';
|
||||
import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common';
|
||||
import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { CoPilotContextProvider } from '@kbn/observability-plugin/public';
|
||||
import { CoPilotService } from '@kbn/observability-plugin/public/typings/co_pilot';
|
||||
import { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import { NavigationWarningPromptProvider } from '@kbn/observability-shared-plugin/public';
|
||||
import { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
|
@ -22,18 +24,29 @@ export const CommonInfraProviders: React.FC<{
|
|||
appName: string;
|
||||
storage: Storage;
|
||||
triggersActionsUI: TriggersAndActionsUIPublicPluginStart;
|
||||
observabilityCopilot: CoPilotService;
|
||||
setHeaderActionMenu: AppMountParameters['setHeaderActionMenu'];
|
||||
theme$: AppMountParameters['theme$'];
|
||||
}> = ({ children, triggersActionsUI, setHeaderActionMenu, appName, storage, theme$ }) => {
|
||||
}> = ({
|
||||
children,
|
||||
triggersActionsUI,
|
||||
observabilityCopilot,
|
||||
setHeaderActionMenu,
|
||||
appName,
|
||||
storage,
|
||||
theme$,
|
||||
}) => {
|
||||
const darkMode = useIsDarkMode();
|
||||
|
||||
return (
|
||||
<TriggersActionsProvider triggersActionsUI={triggersActionsUI}>
|
||||
<EuiThemeProvider darkMode={darkMode}>
|
||||
<DataUIProviders appName={appName} storage={storage}>
|
||||
<HeaderActionMenuProvider setHeaderActionMenu={setHeaderActionMenu} theme$={theme$}>
|
||||
<NavigationWarningPromptProvider>{children}</NavigationWarningPromptProvider>
|
||||
</HeaderActionMenuProvider>
|
||||
<CoPilotContextProvider value={observabilityCopilot}>
|
||||
<HeaderActionMenuProvider setHeaderActionMenu={setHeaderActionMenu} theme$={theme$}>
|
||||
<NavigationWarningPromptProvider>{children}</NavigationWarningPromptProvider>
|
||||
</HeaderActionMenuProvider>
|
||||
</CoPilotContextProvider>
|
||||
</DataUIProviders>
|
||||
</EuiThemeProvider>
|
||||
</TriggersActionsProvider>
|
||||
|
|
|
@ -14,7 +14,6 @@ import { Route } from '@kbn/shared-ux-router';
|
|||
import { AppMountParameters } from '@kbn/core/public';
|
||||
import { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import '../index.scss';
|
||||
import { CoPilotContextProvider } from '@kbn/observability-plugin/public';
|
||||
import { LinkToLogsPage } from '../pages/link_to/link_to_logs';
|
||||
import { LogsPage } from '../pages/logs';
|
||||
import { InfraClientStartDeps, InfraClientStartExports } from '../types';
|
||||
|
@ -69,20 +68,19 @@ const LogsApp: React.FC<{
|
|||
storage={storage}
|
||||
theme$={theme$}
|
||||
triggersActionsUI={plugins.triggersActionsUi}
|
||||
observabilityCopilot={plugins.observability.getCoPilotService()}
|
||||
>
|
||||
<CoPilotContextProvider value={plugins.observability.getCoPilotService()}>
|
||||
<Router history={history}>
|
||||
<KbnUrlStateStorageFromRouterProvider
|
||||
history={history}
|
||||
toastsService={core.notifications.toasts}
|
||||
>
|
||||
<Switch>
|
||||
<Route path="/link-to" component={LinkToLogsPage} />
|
||||
{uiCapabilities?.logs?.show && <Route path="/" component={LogsPage} />}
|
||||
</Switch>
|
||||
</KbnUrlStateStorageFromRouterProvider>
|
||||
</Router>
|
||||
</CoPilotContextProvider>
|
||||
<Router history={history}>
|
||||
<KbnUrlStateStorageFromRouterProvider
|
||||
history={history}
|
||||
toastsService={core.notifications.toasts}
|
||||
>
|
||||
<Switch>
|
||||
<Route path="/link-to" component={LinkToLogsPage} />
|
||||
{uiCapabilities?.logs?.show && <Route path="/" component={LogsPage} />}
|
||||
</Switch>
|
||||
</KbnUrlStateStorageFromRouterProvider>
|
||||
</Router>
|
||||
</CommonInfraProviders>
|
||||
</CoreProviders>
|
||||
);
|
||||
|
|
|
@ -72,6 +72,7 @@ const MetricsApp: React.FC<{
|
|||
storage={storage}
|
||||
theme$={theme$}
|
||||
triggersActionsUI={plugins.triggersActionsUi}
|
||||
observabilityCopilot={plugins.observability.getCoPilotService()}
|
||||
>
|
||||
<SourceProvider sourceId="default">
|
||||
<Router history={history}>
|
||||
|
|
|
@ -213,7 +213,7 @@ const ProcessesTableBody = ({ items, currentTime }: TableBodyProps) => (
|
|||
{column.render ? column.render(item[column.field], currentTime) : item[column.field]}
|
||||
</EuiTableRowCell>
|
||||
));
|
||||
return <ProcessRow cells={cells} item={item} key={`row-${i}`} />;
|
||||
return <ProcessRow cells={cells} item={item} key={`row-${i}`} supportCopilot={true} />;
|
||||
})}
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
EuiTableRow,
|
||||
|
@ -22,17 +22,43 @@ import {
|
|||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
import { euiStyled } from '@kbn/kibana-react-plugin/common';
|
||||
import { useCoPilot, CoPilotPrompt } from '@kbn/observability-plugin/public';
|
||||
import { CoPilotPromptId } from '@kbn/observability-plugin/common';
|
||||
import useToggle from 'react-use/lib/useToggle';
|
||||
import { AutoSizer } from '../../../../../../../components/auto_sizer';
|
||||
import { Process } from './types';
|
||||
import { ProcessRowCharts } from './process_row_charts';
|
||||
|
||||
interface Props {
|
||||
cells: React.ReactNode[];
|
||||
item: Process;
|
||||
supportCopilot?: boolean;
|
||||
}
|
||||
export const CopilotProcessRow = ({ command }: { command: string }) => {
|
||||
const coPilotService = useCoPilot();
|
||||
const explainProcessParams = useMemo(() => {
|
||||
return command ? { command } : undefined;
|
||||
}, [command]);
|
||||
return (
|
||||
<>
|
||||
{coPilotService?.isEnabled() && explainProcessParams ? (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<CoPilotPrompt
|
||||
coPilot={coPilotService}
|
||||
title={explainProcessMessageTitle}
|
||||
params={explainProcessParams}
|
||||
promptId={CoPilotPromptId.InfraExplainProcess}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const ProcessRow = ({ cells, item }: Props) => {
|
||||
export const ProcessRow = ({ cells, item, supportCopilot = false }: Props) => {
|
||||
const [isExpanded, toggle] = useToggle(false);
|
||||
|
||||
return (
|
||||
|
@ -50,79 +76,80 @@ export const ProcessRow = ({ cells, item }: Props) => {
|
|||
</EuiTableRow>
|
||||
<EuiTableRow isExpandable isExpandedRow={isExpanded}>
|
||||
{isExpanded && (
|
||||
<AutoSizer bounds>
|
||||
{({ measureRef, bounds: { height = 0 } }) => (
|
||||
<ExpandedRowCell commandHeight={height}>
|
||||
<EuiSpacer size="s" />
|
||||
<ExpandedRowDescriptionList>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<div ref={measureRef}>
|
||||
<EuiDescriptionListTitle>
|
||||
{i18n.translate(
|
||||
'xpack.infra.metrics.nodeDetails.processes.expandedRowLabelCommand',
|
||||
{
|
||||
defaultMessage: 'Command',
|
||||
}
|
||||
)}
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
<ExpandedCommandLine>{item.command}</ExpandedCommandLine>
|
||||
</EuiDescriptionListDescription>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
{item.apmTrace && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton data-test-subj="infraProcessRowViewTraceInApmButton">
|
||||
{i18n.translate(
|
||||
'xpack.infra.metrics.nodeDetails.processes.viewTraceInAPM',
|
||||
{
|
||||
defaultMessage: 'View trace in APM',
|
||||
}
|
||||
)}
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
<ExpandedRowCell>
|
||||
<EuiSpacer size="s" />
|
||||
<ExpandedRowDescriptionList>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<div>
|
||||
<EuiDescriptionListTitle>
|
||||
{i18n.translate(
|
||||
'xpack.infra.metrics.nodeDetails.processes.expandedRowLabelCommand',
|
||||
{
|
||||
defaultMessage: 'Command',
|
||||
}
|
||||
)}
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
<ExpandedCommandLine>{item.command}</ExpandedCommandLine>
|
||||
</EuiDescriptionListDescription>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
{item.apmTrace && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton data-test-subj="infraProcessRowViewTraceInApmButton">
|
||||
{i18n.translate('xpack.infra.metrics.nodeDetails.processes.viewTraceInAPM', {
|
||||
defaultMessage: 'View trace in APM',
|
||||
})}
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
<EuiFlexGrid columns={2} gutterSize="s" responsive={false}>
|
||||
<EuiFlexItem>
|
||||
<EuiDescriptionListTitle>
|
||||
{i18n.translate(
|
||||
'xpack.infra.metrics.nodeDetails.processes.expandedRowLabelPID',
|
||||
{
|
||||
defaultMessage: 'PID',
|
||||
}
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
<EuiFlexGrid columns={2} gutterSize="s" responsive={false}>
|
||||
<EuiFlexItem>
|
||||
<EuiDescriptionListTitle>
|
||||
{i18n.translate(
|
||||
'xpack.infra.metrics.nodeDetails.processes.expandedRowLabelPID',
|
||||
{
|
||||
defaultMessage: 'PID',
|
||||
}
|
||||
)}
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
<CodeListItem>{item.pid}</CodeListItem>
|
||||
</EuiDescriptionListDescription>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiDescriptionListTitle>
|
||||
{i18n.translate(
|
||||
'xpack.infra.metrics.nodeDetails.processes.expandedRowLabelUser',
|
||||
{
|
||||
defaultMessage: 'User',
|
||||
}
|
||||
)}
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
<CodeListItem>{item.user}</CodeListItem>
|
||||
</EuiDescriptionListDescription>
|
||||
</EuiFlexItem>
|
||||
<ProcessRowCharts command={item.command} />
|
||||
</EuiFlexGrid>
|
||||
</ExpandedRowDescriptionList>
|
||||
</ExpandedRowCell>
|
||||
)}
|
||||
</AutoSizer>
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
<CodeListItem>{item.pid}</CodeListItem>
|
||||
</EuiDescriptionListDescription>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiDescriptionListTitle>
|
||||
{i18n.translate(
|
||||
'xpack.infra.metrics.nodeDetails.processes.expandedRowLabelUser',
|
||||
{
|
||||
defaultMessage: 'User',
|
||||
}
|
||||
)}
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
<CodeListItem>{item.user}</CodeListItem>
|
||||
</EuiDescriptionListDescription>
|
||||
</EuiFlexItem>
|
||||
<ProcessRowCharts command={item.command} />
|
||||
</EuiFlexGrid>
|
||||
{supportCopilot && <CopilotProcessRow command={item.command} />}
|
||||
</ExpandedRowDescriptionList>
|
||||
</ExpandedRowCell>
|
||||
)}
|
||||
</EuiTableRow>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const explainProcessMessageTitle = i18n.translate(
|
||||
'xpack.infra.hostFlyout.explainProcessMessageTitle',
|
||||
{
|
||||
defaultMessage: "What's this process?",
|
||||
}
|
||||
);
|
||||
|
||||
const ExpandedRowDescriptionList = euiStyled(EuiDescriptionList).attrs({
|
||||
compressed: true,
|
||||
})`
|
||||
|
@ -149,8 +176,8 @@ const ExpandedCommandLine = euiStyled(EuiCode).attrs({
|
|||
const ExpandedRowCell = euiStyled(EuiTableRowCell).attrs({
|
||||
textOnly: false,
|
||||
colSpan: 6,
|
||||
})<{ commandHeight: number }>`
|
||||
height: ${(props) => props.commandHeight + 240}px;
|
||||
padding: 0 ${(props) => props.theme.eui.euiSizeM};
|
||||
})`
|
||||
padding-top: ${(props) => props.theme.eui.euiSizeM} !important;
|
||||
padding-bottom: ${(props) => props.theme.eui.euiSizeM} !important;
|
||||
background-color: ${(props) => props.theme.eui.euiColorLightestShade};
|
||||
`;
|
||||
|
|
|
@ -22,6 +22,7 @@ export enum CoPilotPromptId {
|
|||
ApmExplainError = 'apmExplainError',
|
||||
LogsExplainMessage = 'logsExplainMessage',
|
||||
LogsFindSimilar = 'logsFindSimilar',
|
||||
InfraExplainProcess = 'infraExplainProcess',
|
||||
ExplainLogSpike = 'explainLogSpike',
|
||||
}
|
||||
|
||||
|
@ -38,7 +39,13 @@ const APM_GPT_SYSTEM_MESSAGE = {
|
|||
};
|
||||
|
||||
const LOGS_SYSTEM_MESSAGE = {
|
||||
content: `You logsapm-gpt, a helpful assistant for logs-based observability. Answer as
|
||||
content: `You are logs-gpt, a helpful assistant for logs-based observability. Answer as
|
||||
concisely as possible.`,
|
||||
role: 'system' as const,
|
||||
};
|
||||
|
||||
const INFRA_SYSTEM_MESSAGE = {
|
||||
content: `You are infra-gpt, a helpful assistant for metrics-based infrastructure observability. Answer as
|
||||
concisely as possible.`,
|
||||
role: 'system' as const,
|
||||
};
|
||||
|
@ -133,7 +140,7 @@ export const coPilotPrompts = {
|
|||
The library is: ${library}
|
||||
The function is: ${functionName}
|
||||
|
||||
Your task is to desribe what the library is and what its use cases are, and to describe what the function
|
||||
Your task is to describe what the library is and what its use cases are, and to describe what the function
|
||||
does. The output format should look as follows:
|
||||
|
||||
Library description: Provide a concise description of the library
|
||||
|
@ -231,6 +238,73 @@ export const coPilotPrompts = {
|
|||
];
|
||||
},
|
||||
}),
|
||||
[CoPilotPromptId.InfraExplainProcess]: prompt({
|
||||
params: t.type({
|
||||
command: t.string,
|
||||
}),
|
||||
messages: ({ command }) => {
|
||||
return [
|
||||
INFRA_SYSTEM_MESSAGE,
|
||||
{
|
||||
content: `I am a software engineer. I am trying to understand what a process running on my
|
||||
machine does.
|
||||
|
||||
Your task is to first describe what the process is and what its general use cases are. If I also provide you
|
||||
with the arguments to the process you should then explain its arguments and how they influence the behaviour
|
||||
of the process. If I do not provide any arguments then explain the behaviour of the process when no arguments are
|
||||
provided.
|
||||
|
||||
If you do not recognise the process say "No information available for this process". If I provide an argument
|
||||
to the process that you do not recognise then say "No information available for this argument" when explaining
|
||||
that argument.
|
||||
|
||||
Here is an example with arguments.
|
||||
Process: metricbeat -c /etc/metricbeat.yml -d autodiscover,kafka -e -system.hostfs=/hostfs
|
||||
Explaination: Metricbeat is part of the Elastic Stack. It is a lightweight shipper that you can install on your
|
||||
servers to periodically collect metrics from the operating system and from services running on the server.
|
||||
Use cases for Metricbeat generally revolve around infrastructure monitoring. You would typically install
|
||||
Metricbeat on your servers to collect metrics from your systems and services. These metrics are then
|
||||
used for performance monitoring, anomaly detection, system status checks, etc.
|
||||
|
||||
Here is a breakdown of the arguments used:
|
||||
|
||||
* -c /etc/metricbeat.yml: The -c option is used to specify the configuration file for Metricbeat. In
|
||||
this case, /etc/metricbeat.yml is the configuration file. This file contains configurations for what
|
||||
metrics to collect and where to send them (e.g., to Elasticsearch or Logstash).
|
||||
|
||||
* -d autodiscover,kafka: The -d option is used to enable debug output for selected components. In
|
||||
this case, debug output is enabled for autodiscover and kafka components. The autodiscover feature
|
||||
allows Metricbeat to automatically discover services as they get started and stopped in your environment,
|
||||
and kafka is presumably a monitored service from which Metricbeat collects metrics.
|
||||
|
||||
* -e: The -e option is used to log to stderr and disable syslog/file output. This is useful for debugging.
|
||||
|
||||
* -system.hostfs=/hostfs: The -system.hostfs option is used to set the mount point of the host’s
|
||||
filesystem for use in monitoring a host from within a container. In this case, /hostfs is the mount
|
||||
point. When running Metricbeat inside a container, filesystem metrics would be for the container by
|
||||
default, but with this option, Metricbeat can get metrics for the host system.
|
||||
|
||||
Here is an example without arguments.
|
||||
Process: metricbeat
|
||||
Explanation: Metricbeat is part of the Elastic Stack. It is a lightweight shipper that you can install on your
|
||||
servers to periodically collect metrics from the operating system and from services running on the server.
|
||||
Use cases for Metricbeat generally revolve around infrastructure monitoring. You would typically install
|
||||
Metricbeat on your servers to collect metrics from your systems and services. These metrics are then
|
||||
used for performance monitoring, anomaly detection, system status checks, etc.
|
||||
|
||||
Running it without any arguments will start the process with the default configuration file, typically
|
||||
located at /etc/metricbeat/metricbeat.yml. This file specifies the metrics to be collected and where
|
||||
to ship them to.
|
||||
|
||||
Now explain this process to me.
|
||||
Process: ${command}
|
||||
Explanation:
|
||||
`,
|
||||
role: 'user',
|
||||
},
|
||||
];
|
||||
},
|
||||
}),
|
||||
[CoPilotPromptId.ExplainLogSpike]: prompt({
|
||||
params: t.type({
|
||||
significantFieldValues: significantFieldValuesRt,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue