Skip to content

Commit

Permalink
[Fleet] Agent logs UI (#83356)
Browse files Browse the repository at this point in the history
* Initial agent log table

* Add data and storage services to Kibana context, rename useCore to useStartServices and replace usage of useStartDeps

* Initial attempt at adding query bar for log stream

* Adjust app layout to allow page content to be full height

* Dataset and log level filters, split into smaller files

* Use data plugin's `QueryStringInput` component for query bar

* Add open in Logs UI link

* Clean up unused storage dependency

* Remove agent activity log and related dead code

* Clean up i18n

* Clean up plugin deps, fix routing

* Add back storage dependency that data plugin components need

* Remove dependency on infra for logs UI link

* Change default date range to last one day

* Adjust panel padding

* Add comment

* Move module declarations to top-level x-pack/typings

* Fix missed renaming

* Remove unused path

* Move building of log stream query into separate service with unit tests

* Adjust test conditions
  • Loading branch information
jen-huang authored Nov 20, 2020
1 parent 6164d04 commit a8913d3
Show file tree
Hide file tree
Showing 60 changed files with 788 additions and 914 deletions.
2 changes: 1 addition & 1 deletion x-pack/plugins/fleet/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"requiredPlugins": ["licensing", "data", "encryptedSavedObjects"],
"optionalPlugins": ["security", "features", "cloud", "usageCollection", "home"],
"extraPublicDirs": ["common"],
"requiredBundles": ["kibanaReact", "esUiShared", "home"]
"requiredBundles": ["kibanaReact", "esUiShared", "home", "infra", "kibanaUtils"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { IFieldType } from 'src/plugins/data/public';
// @ts-ignore
import { EuiSuggest, EuiSuggestItemProps } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useDebounce, useStartDeps } from '../hooks';
import { useDebounce, useStartServices } from '../hooks';
import { INDEX_NAME, AGENT_SAVED_OBJECT_TYPE } from '../constants';

const DEBOUNCE_SEARCH_MS = 150;
Expand Down Expand Up @@ -80,7 +80,7 @@ export const SearchBar: React.FunctionComponent<Props> = ({
);
};

function transformSuggestionType(type: string): { iconType: string; color: string } {
export function transformSuggestionType(type: string): { iconType: string; color: string } {
switch (type) {
case 'field':
return { iconType: 'kqlField', color: 'tint4' };
Expand All @@ -96,7 +96,7 @@ function transformSuggestionType(type: string): { iconType: string; color: strin
}

function useSuggestions(fieldPrefix: string, search: string) {
const { data } = useStartDeps();
const { data } = useStartServices();

const debouncedSearch = useDebounce(search, DEBOUNCE_SEARCH_MS);
const [suggestions, setSuggestions] = useState<Suggestion[]>([]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ import {
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiText } from '@elastic/eui';
import { safeLoad } from 'js-yaml';
import { useComboInput, useCore, useGetSettings, useInput, sendPutSettings } from '../hooks';
import {
useComboInput,
useStartServices,
useGetSettings,
useInput,
sendPutSettings,
} from '../hooks';
import { useGetOutputs, sendPutOutput } from '../hooks/use_request/outputs';
import { isDiffPathProtocol } from '../../../../common/';

Expand All @@ -37,7 +43,7 @@ interface Props {

function useSettingsForm(outputId: string | undefined, onSuccess: () => void) {
const [isLoading, setIsloading] = React.useState(false);
const { notifications } = useCore();
const { notifications } = useStartServices();
const kibanaUrlsInput = useComboInput([], (value) => {
if (value.length === 0) {
return [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ export const PAGE_ROUTING_PATHS = {
fleet: '/fleet',
fleet_agent_list: '/fleet/agents',
fleet_agent_details: '/fleet/agents/:agentId/:tabId?',
fleet_agent_details_events: '/fleet/agents/:agentId',
fleet_agent_details_details: '/fleet/agents/:agentId/details',
fleet_agent_details_logs: '/fleet/agents/:agentId/logs',
fleet_enrollment_tokens: '/fleet/enrollment-tokens',
data_streams: '/data-streams',
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
*/

export { useCapabilities } from './use_capabilities';
export { useCore } from './use_core';
export { useStartServices } from './use_core';
export { useConfig, ConfigContext } from './use_config';
export { useKibanaVersion, KibanaVersionContext } from './use_kibana_version';
export { useSetupDeps, useStartDeps, DepsContext } from './use_deps';
export { licenseService, useLicense } from './use_license';
export { useBreadcrumbs } from './use_breadcrumbs';
export { useLink } from './use_link';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { i18n } from '@kbn/i18n';
import { ChromeBreadcrumb } from 'src/core/public';
import { BASE_PATH, Page, DynamicPagePathValues, pagePathGetters } from '../constants';
import { useCore } from './use_core';
import { useStartServices } from './use_core';

const BASE_BREADCRUMB: ChromeBreadcrumb = {
href: pagePathGetters.overview(),
Expand Down Expand Up @@ -204,7 +204,7 @@ const breadcrumbGetters: {
};

export function useBreadcrumbs(page: Page, values: DynamicPagePathValues = {}) {
const { chrome, http } = useCore();
const { chrome, http } = useStartServices();
const breadcrumbs: ChromeBreadcrumb[] = breadcrumbGetters[page](values).map((breadcrumb) => ({
...breadcrumb,
href: breadcrumb.href ? http.basePath.prepend(`${BASE_PATH}#${breadcrumb.href}`) : undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { useCore } from './';
import { useStartServices } from './';

export function useCapabilities() {
const core = useCore();
const core = useStartServices();
return core.application.capabilities.fleet;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { CoreStart } from 'kibana/public';
import { FleetStartServices } from '../../../plugin';
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';

export function useCore(): CoreStart {
const { services } = useKibana<CoreStart>();
export function useStartServices(): FleetStartServices {
const { services } = useKibana<FleetStartServices>();
if (services === null) {
throw new Error('KibanaContextProvider not initialized');
}
Expand Down
29 changes: 0 additions & 29 deletions x-pack/plugins/fleet/public/applications/fleet/hooks/use_deps.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { useCore } from './';
import { useStartServices } from './';

const KIBANA_BASE_PATH = '/app/kibana';

export function useKibanaLink(path: string = '/') {
const core = useCore();
const core = useStartServices();
return core.http.basePath.prepend(`${KIBANA_BASE_PATH}#${path}`);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import {
DynamicPagePathValues,
pagePathGetters,
} from '../constants';
import { useCore } from './';
import { useStartServices } from './';

const getPath = (page: StaticPage | DynamicPage, values: DynamicPagePathValues = {}): string => {
return values ? pagePathGetters[page](values) : pagePathGetters[page as StaticPage]();
};

export const useLink = () => {
const core = useCore();
const core = useStartServices();
return {
getPath,
getHref: (page: StaticPage | DynamicPage, values?: DynamicPagePathValues) => {
Expand Down
51 changes: 20 additions & 31 deletions x-pack/plugins/fleet/public/applications/fleet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,15 @@ import { EuiErrorBoundary, EuiPanel, EuiEmptyPrompt, EuiCode } from '@elastic/eu
import { CoreStart, AppMountParameters } from 'src/core/public';
import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public';
import { EuiThemeProvider } from '../../../../xpack_legacy/common';
import { FleetSetupDeps, FleetConfigType, FleetStartDeps } from '../../plugin';
import { FleetConfigType, FleetStartServices } from '../../plugin';
import { PAGE_ROUTING_PATHS } from './constants';
import { DefaultLayout, WithoutHeaderLayout } from './layouts';
import { Loading, Error } from './components';
import { IngestManagerOverview, EPMApp, AgentPolicyApp, FleetApp, DataStreamApp } from './sections';
import {
DepsContext,
ConfigContext,
useConfig,
useCore,
useStartServices,
sendSetup,
sendGetPermissionsCheck,
licenseService,
Expand Down Expand Up @@ -67,7 +66,7 @@ const IngestManagerRoutes = memo<{ history: AppMountParameters['history']; basep
useBreadcrumbs('base');
const { agents } = useConfig();

const { notifications } = useCore();
const { notifications } = useStartServices();

const [isPermissionsLoading, setIsPermissionsLoading] = useState<boolean>(false);
const [permissionsError, setPermissionsError] = useState<string>();
Expand Down Expand Up @@ -227,58 +226,48 @@ const IngestManagerRoutes = memo<{ history: AppMountParameters['history']; basep

const IngestManagerApp = ({
basepath,
coreStart,
setupDeps,
startDeps,
startServices,
config,
history,
kibanaVersion,
extensions,
}: {
basepath: string;
coreStart: CoreStart;
setupDeps: FleetSetupDeps;
startDeps: FleetStartDeps;
startServices: FleetStartServices;
config: FleetConfigType;
history: AppMountParameters['history'];
kibanaVersion: string;
extensions: UIExtensionsStorage;
}) => {
const isDarkMode = useObservable<boolean>(coreStart.uiSettings.get$('theme:darkMode'));
const isDarkMode = useObservable<boolean>(startServices.uiSettings.get$('theme:darkMode'));
return (
<coreStart.i18n.Context>
<KibanaContextProvider services={{ ...coreStart }}>
<DepsContext.Provider value={{ setup: setupDeps, start: startDeps }}>
<ConfigContext.Provider value={config}>
<KibanaVersionContext.Provider value={kibanaVersion}>
<EuiThemeProvider darkMode={isDarkMode}>
<UIExtensionsContext.Provider value={extensions}>
<IngestManagerRoutes history={history} basepath={basepath} />
</UIExtensionsContext.Provider>
</EuiThemeProvider>
</KibanaVersionContext.Provider>
</ConfigContext.Provider>
</DepsContext.Provider>
<startServices.i18n.Context>
<KibanaContextProvider services={{ ...startServices }}>
<ConfigContext.Provider value={config}>
<KibanaVersionContext.Provider value={kibanaVersion}>
<EuiThemeProvider darkMode={isDarkMode}>
<UIExtensionsContext.Provider value={extensions}>
<IngestManagerRoutes history={history} basepath={basepath} />
</UIExtensionsContext.Provider>
</EuiThemeProvider>
</KibanaVersionContext.Provider>
</ConfigContext.Provider>
</KibanaContextProvider>
</coreStart.i18n.Context>
</startServices.i18n.Context>
);
};

export function renderApp(
coreStart: CoreStart,
startServices: FleetStartServices,
{ element, appBasePath, history }: AppMountParameters,
setupDeps: FleetSetupDeps,
startDeps: FleetStartDeps,
config: FleetConfigType,
kibanaVersion: string,
extensions: UIExtensionsStorage
) {
ReactDOM.render(
<IngestManagerApp
basepath={appBasePath}
coreStart={coreStart}
setupDeps={setupDeps}
startDeps={startDeps}
startServices={startServices}
config={config}
history={history}
kibanaVersion={kibanaVersion}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ const Container = styled.div`
flex-direction: column;
`;

const Wrapper = styled.div`
display: flex;
flex-direction: column;
flex: 1;
`;

const Nav = styled.nav`
background: ${(props) => props.theme.eui.euiColorEmptyShade};
border-bottom: ${(props) => props.theme.eui.euiBorderThin};
Expand Down Expand Up @@ -56,7 +62,7 @@ export const DefaultLayout: React.FunctionComponent<Props> = ({
/>
)}
<Container>
<div>
<Wrapper>
<Nav>
<EuiFlexGroup gutterSize="l" alignItems="center">
<EuiFlexItem>
Expand Down Expand Up @@ -126,7 +132,7 @@ export const DefaultLayout: React.FunctionComponent<Props> = ({
</EuiFlexGroup>
</Nav>
{children}
</div>
</Wrapper>
<AlphaMessaging />
</Container>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
* you may not use this file except in compliance with the Elastic License.
*/
export { DefaultLayout } from './default';
export { WithHeaderLayout } from './with_header';
export { WithHeaderLayout, WithHeaderLayoutProps } from './with_header';
export { WithoutHeaderLayout } from './without_header';
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React, { Fragment } from 'react';
import styled from 'styled-components';
import { EuiPage, EuiPageBody, EuiSpacer } from '@elastic/eui';
import { EuiPageBody, EuiSpacer } from '@elastic/eui';
import { Header, HeaderProps } from '../components';

const Page = styled(EuiPage)`
background: ${(props) => props.theme.eui.euiColorEmptyShade};
`;
import { Page, ContentWrapper } from './without_header';

export interface WithHeaderLayoutProps extends HeaderProps {
restrictWidth?: number;
Expand All @@ -37,8 +33,10 @@ export const WithHeaderLayout: React.FC<WithHeaderLayoutProps> = ({
data-test-subj={dataTestSubj ? `${dataTestSubj}_page` : undefined}
>
<EuiPageBody>
<EuiSpacer size="m" />
{children}
<ContentWrapper>
<EuiSpacer size="m" />
{children}
</ContentWrapper>
</EuiPageBody>
</Page>
</Fragment>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,17 @@ import React, { Fragment } from 'react';
import styled from 'styled-components';
import { EuiPage, EuiPageBody, EuiSpacer } from '@elastic/eui';

const Page = styled(EuiPage)`
export const Page = styled(EuiPage)`
background: ${(props) => props.theme.eui.euiColorEmptyShade};
width: 100%;
align-self: center;
margin-left: 0;
margin-right: 0;
flex: 1;
`;

export const ContentWrapper = styled.div`
height: 100%;
`;

interface Props {
Expand All @@ -20,8 +29,10 @@ export const WithoutHeaderLayout: React.FC<Props> = ({ restrictWidth, children }
<Fragment>
<Page restrictWidth={restrictWidth || 1200}>
<EuiPageBody>
<EuiSpacer size="m" />
{children}
<ContentWrapper>
<EuiSpacer size="m" />
{children}
</ContentWrapper>
</EuiPageBody>
</Page>
</Fragment>
Expand Down
Loading

0 comments on commit a8913d3

Please sign in to comment.