[Monitoring] Add log message for error scenario around missing licensing (#40660) (#41030)

* Add log message

* PR feedback

* Add test

* Fix/add tests

* Use cluster name if possible

* Fix loc id

* Fix messaging
This commit is contained in:
Chris Roberson 2019-07-12 15:29:59 -04:00 committed by GitHub
parent bb0792bae2
commit 30bac95075
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 99 additions and 6 deletions

View file

@ -7,16 +7,35 @@
import clusters from './fixtures/clusters';
import { getClustersSummary } from '../get_clusters_summary';
const mockLog = jest.fn();
const mockServer = {
log: mockLog
};
describe('getClustersSummary', () => {
it('should summarize cluster data with a primary cluster', () => {
const kibanaUuid = '46205c28-9d41-447a-a438-c8b86fb5d1ce';
const result = getClustersSummary(clusters, kibanaUuid);
const result = getClustersSummary(mockServer, clusters, kibanaUuid);
expect(result).toMatchSnapshot();
});
it('should summarize cluster data with no primary cluster', () => {
const kibanaUuid = null;
const result = getClustersSummary(clusters, kibanaUuid);
const result = getClustersSummary(mockServer, clusters, kibanaUuid);
expect(result).toMatchSnapshot();
});
it('should log and throw an exception if a cluster does not have a license', () => {
const fakeClusters = clusters.map(cluster => ({
...cluster,
license: undefined
}));
expect(() => getClustersSummary(mockServer, fakeClusters)).toThrow('Monitoring License Error');
expect(mockLog).toHaveBeenCalledWith(
['error', 'monitoring'],
'Could not find license information for cluster = \'Custom name\'. ' +
'Please check the cluster\'s master node server logs for errors or warnings.'
);
});
});

View file

@ -160,5 +160,6 @@ export async function getClustersFromRequest(req, indexPatterns, { clusterUuid,
const config = req.server.config();
const kibanaUuid = config.get('server.uuid');
return getClustersSummary(clusters, kibanaUuid, isCcrEnabled);
return getClustersSummary(req.server, clusters, kibanaUuid, isCcrEnabled);
}

View file

@ -6,8 +6,10 @@
import { pick, omit, get } from 'lodash';
import { calculateOverallStatus } from '../calculate_overall_status';
import { LOGGING_TAG } from '../../../common/constants';
import { MonitoringLicenseError } from '../errors/custom_errors';
export function getClustersSummary(clusters, kibanaUuid, isCcrEnabled) {
export function getClustersSummary(server, clusters, kibanaUuid, isCcrEnabled) {
return clusters.map(cluster => {
const {
isSupported,
@ -28,6 +30,17 @@ export function getClustersSummary(clusters, kibanaUuid, isCcrEnabled) {
const clusterName = get(clusterSettings, 'cluster.metadata.display_name', cluster.cluster_name);
// check for any missing licenses
if (!license) {
const clusterId = cluster.name || clusterName || clusterUuid;
server.log(
['error', LOGGING_TAG],
'Could not find license information for cluster = \'' + clusterId + '\'. ' +
'Please check the cluster\'s master node server logs for errors or warnings.'
);
throw new MonitoringLicenseError(clusterId);
}
const {
status: licenseStatus,
type: licenseType,

View file

@ -7,6 +7,7 @@
import expect from '@kbn/expect';
import { errors } from 'elasticsearch';
import { isKnownError, handleKnownError } from '../known_errors';
import { MonitoringLicenseError } from '../custom_errors';
describe('Error handling for 503 errors', () => {
it('ignores an unknown type', () => {
@ -87,4 +88,29 @@ describe('Error handling for 503 errors', () => {
headers: {}
});
});
it('handles the custom MonitoringLicenseError error', () => {
const clusterName = 'main';
const err = new MonitoringLicenseError(clusterName);
expect(isKnownError(err)).to.be(true);
const wrappedErr = handleKnownError(err);
expect(wrappedErr.message).to.be(
'Monitoring License Error: ' +
`Could not find license information for cluster = '${clusterName}'. ` +
`Please check the cluster's master node server logs for errors or warnings.`);
expect(wrappedErr.isBoom).to.be(true);
expect(wrappedErr.isServer).to.be(true);
expect(wrappedErr.data).to.be(null);
expect(wrappedErr.output).to.eql({
statusCode: 503,
payload: {
statusCode: 503,
error: 'Service Unavailable',
message: `Monitoring License Error: Could not find license information for cluster = '${clusterName}'. `
+ `Please check the cluster's master node server logs for errors or warnings.`
},
headers: {}
});
});
});

View file

@ -0,0 +1,23 @@
/*
* 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 { i18n } from '@kbn/i18n';
export class MonitoringLicenseError extends Error {
constructor(clusterId) {
super();
this.message = i18n.translate('xpack.monitoring.errors.monitoringLicenseErrorTitle', {
defaultMessage: 'Monitoring License Error',
});
this.description = i18n.translate('xpack.monitoring.errors.monitoringLicenseErrorDescription', {
defaultMessage: 'Could not find license information for cluster = \'{clusterId}\'. ' +
'Please check the cluster\'s master node server logs for errors or warnings.',
values: {
clusterId
}
});
}
}

View file

@ -6,6 +6,8 @@
import { boomify } from 'boom';
import { i18n } from '@kbn/i18n';
import { MonitoringLicenseError } from './custom_errors';
/*
* Check if the given error message is a known "safe" type of error
* in which case we want to give the status as 503 and show the error message.
@ -22,15 +24,24 @@ const mapTypeMessage = {
NoConnections: i18n.translate('xpack.monitoring.errors.noConnectionsErrorMessage', {
defaultMessage: 'Check the Elasticsearch Monitoring cluster network connection and refer to the Kibana logs for more information.' }),
StatusCodeError: i18n.translate('xpack.monitoring.errors.statusCodeErrorMessage', {
defaultMessage: 'Check the Elasticsearch Monitoring cluster network connection or the load level of the nodes.' })
defaultMessage: 'Check the Elasticsearch Monitoring cluster network connection or the load level of the nodes.' }),
};
const customErrors = [
MonitoringLicenseError
];
export function isKnownError(err) {
for (const customError of customErrors) {
if (err instanceof customError) {
return true;
}
}
const knownTypes = Object.keys(mapTypeMessage);
return knownTypes.includes(err.constructor.name);
}
export function handleKnownError(err) {
err.message = err.message + ': ' + mapTypeMessage[err.constructor.name];
err.message = err.message + ': ' + (err.description || mapTypeMessage[err.constructor.name]);
return boomify(err, { statusCode: KNOWN_ERROR_STATUS_CODE });
}