Skip to content

Commit

Permalink
Add a custom and specific InvalidNode Error so that more helpful info…
Browse files Browse the repository at this point in the history
…rmation can be displayed on the Metrics page

Add a custom error for an invalid node check

Add a component for displaying help when using an invalid node

Throw the specific error from kibana_metrics_adapter

Add an enum for specific error codes

Look for and handle invalid node error in metrics/index

Amend container to pass Error instance

Add source configuration flyout to metrics/index to facilitate change source config button
  • Loading branch information
Kerry350 committed Feb 11, 2019
1 parent 6b376e5 commit 1c13f54
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 5 deletions.
79 changes: 79 additions & 0 deletions x-pack/plugins/infra/public/components/metrics/invalid_node.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* 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 { EuiButton, EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { InjectedIntl, injectI18n } from '@kbn/i18n/react';
import React from 'react';
import styled from 'styled-components';
import { WithSourceConfigurationFlyoutState } from '../../components/source_configuration/source_configuration_flyout_state';
import { WithKibanaChrome } from '../../containers/with_kibana_chrome';

interface InvalidNodeErrorProps {
nodeName: string;
intl: InjectedIntl;
}

const invalidNodeError: React.SFC<InvalidNodeErrorProps> = ({ nodeName, intl }) => (
<WithKibanaChrome>
{({ basePath }) => (
<CenteredEmptyPrompt
title={
<h2>
{intl.formatMessage(
{
id: 'xpack.infra.metrics.invalidNodeErrorTitle',
defaultMessage: "Looks like {nodeName} isn't collecting any metrics data",
},
{ nodeName }
)}
</h2>
}
body={
<p>
{intl.formatMessage({
id: 'xpack.infra.metrics.invalidNodeErrorDescription',
defaultMessage: 'Double check your configuration',
})}
</p>
}
actions={
<EuiFlexGroup>
<EuiFlexItem>
<EuiButton
href={`${basePath}/app/kibana#/home/tutorial_directory/metrics`}
color="primary"
fill
>
{intl.formatMessage({
id: 'xpack.infra.homePage.noMetricsIndicesInstructionsActionLabel',
defaultMessage: 'View setup instructions',
})}
</EuiButton>
</EuiFlexItem>
<EuiFlexItem>
<WithSourceConfigurationFlyoutState>
{({ enable }) => (
<EuiButton color="primary" onClick={enable}>
{intl.formatMessage({
id: 'xpack.infra.configureSourceActionLabel',
defaultMessage: 'Change source configuration',
})}
</EuiButton>
)}
</WithSourceConfigurationFlyoutState>
</EuiFlexItem>
</EuiFlexGroup>
}
/>
)}
</WithKibanaChrome>
);

export const InvalidNodeError = injectI18n(invalidNodeError);

const CenteredEmptyPrompt = styled(EuiEmptyPrompt)`
align-self: center;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { ApolloError } from 'apollo-client';
import React from 'react';
import { Query } from 'react-apollo';
import {
Expand All @@ -18,7 +18,7 @@ import { metricsQuery } from './metrics.gql_query';

interface WithMetricsArgs {
metrics: InfraMetricData[];
error?: string | undefined;
error?: ApolloError | undefined;
loading: boolean;
refetch: () => void;
}
Expand Down Expand Up @@ -63,7 +63,7 @@ export const WithMetrics = ({
{({ data, error, loading, refetch }) => {
return children({
metrics: filterOnlyInfraMetricData(data && data.source && data.source.metrics),
error: error && error.message,
error,
loading,
refetch,
});
Expand Down
16 changes: 15 additions & 1 deletion x-pack/plugins/infra/public/pages/metrics/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ import { InjectedIntl, injectI18n } from '@kbn/i18n/react';
import React from 'react';
import styled, { withTheme } from 'styled-components';

import { InfraMetricsErrorCodes } from '../../../server/lib/adapters/metrics/adapter_types';
import { AutoSizer } from '../../components/auto_sizer';
import { Header } from '../../components/header';
import { Metrics } from '../../components/metrics';
import { InvalidNodeError } from '../../components/metrics/invalid_node';
import { MetricsSideNav } from '../../components/metrics/side_nav';
import { MetricsTimeControls } from '../../components/metrics/time_controls';
import { ColumnarPage, PageContent } from '../../components/page';
import { SourceConfigurationFlyout } from '../../components/source_configuration';
import { WithMetadata } from '../../containers/metadata/with_metadata';
import { WithMetrics } from '../../containers/metrics/with_metrics';
import {
Expand Down Expand Up @@ -113,6 +116,7 @@ export const MetricDetail = withTheme(
return (
<ColumnarPage>
<Header breadcrumbs={breadcrumbs} />
<SourceConfigurationFlyout />
<WithMetricsTimeUrlState />
<DetailPageContent>
<WithMetrics
Expand All @@ -124,7 +128,17 @@ export const MetricDetail = withTheme(
>
{({ metrics, error, loading, refetch }) => {
if (error) {
return <ErrorPageBody message={error} />;
if (error.graphQLErrors) {
const invalidNodeError = error.graphQLErrors.find(
(err: any) => err.code === InfraMetricsErrorCodes.invalid_node
);

if (invalidNodeError) {
return <InvalidNodeError nodeName={name} />;
}
}

return <ErrorPageBody message={error.message} />;
}
return (
<EuiPage style={{ flex: '1 0 auto' }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,7 @@ export type InfraMetricModelCreator = (
indexPattern: string | string[],
interval: string
) => InfraMetricModel;

export enum InfraMetricsErrorCodes {
invalid_node = 'METRICS_INVALID_NODE',
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { InfraMetric, InfraMetricData, InfraNodeType } from '../../../graphql/ty
import { InfraBackendFrameworkAdapter, InfraFrameworkRequest } from '../framework';
import { InfraMetricsAdapter, InfraMetricsRequestOptions } from './adapter_types';
import { checkValidNode } from './lib/check_valid_node';
import { InvalidNodeError } from './lib/errors';
import { metricModels } from './models';

export class KibanaMetricsAdapter implements InfraMetricsAdapter {
Expand Down Expand Up @@ -45,7 +46,7 @@ export class KibanaMetricsAdapter implements InfraMetricsAdapter {

const validNode = await checkValidNode(search, indexPattern, nodeField, options.nodeId);
if (!validNode) {
throw new Error(
throw new InvalidNodeError(
i18n.translate('xpack.infra.kibanaMetrics.nodeDoesNotExistErrorMessage', {
defaultMessage: '{nodeId} does not exist.',
values: {
Expand Down
15 changes: 15 additions & 0 deletions x-pack/plugins/infra/server/lib/adapters/metrics/lib/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* 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 { ApolloError } from 'apollo-server-errors';
import { InfraMetricsErrorCodes } from '../adapter_types';

export class InvalidNodeError extends ApolloError {
constructor(message: string) {
super(message, InfraMetricsErrorCodes.invalid_node);
Object.defineProperty(this, 'name', { value: 'InvalidNodeError' });
}
}

0 comments on commit 1c13f54

Please sign in to comment.