mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
Status service: improve overall status summary (#114228)
* improve getSummaryStatus * fix unit tests
This commit is contained in:
parent
25fef38f12
commit
cba91fdaab
4 changed files with 128 additions and 125 deletions
|
@ -81,93 +81,86 @@ describe('getSummaryStatus', () => {
|
|||
});
|
||||
|
||||
describe('summary', () => {
|
||||
describe('when a single service is at highest level', () => {
|
||||
it('returns all information about that single service', () => {
|
||||
expect(
|
||||
getSummaryStatus(
|
||||
Object.entries({
|
||||
s1: degraded,
|
||||
s2: {
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: 'Lorem ipsum',
|
||||
meta: {
|
||||
custom: { data: 'here' },
|
||||
},
|
||||
it('returns correct summary when a single service is affected', () => {
|
||||
expect(
|
||||
getSummaryStatus(
|
||||
Object.entries({
|
||||
s1: degraded,
|
||||
s2: {
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: 'Lorem ipsum',
|
||||
meta: {
|
||||
custom: { data: 'here' },
|
||||
},
|
||||
})
|
||||
)
|
||||
).toEqual({
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: '[s2]: Lorem ipsum',
|
||||
detail: 'See the status page for more information',
|
||||
meta: {
|
||||
affectedServices: ['s2'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('allows the single service to override the detail and documentationUrl fields', () => {
|
||||
expect(
|
||||
getSummaryStatus(
|
||||
Object.entries({
|
||||
s1: degraded,
|
||||
s2: {
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: 'Lorem ipsum',
|
||||
detail: 'Vivamus pulvinar sem ac luctus ultrices.',
|
||||
documentationUrl: 'http://helpmenow.com/problem1',
|
||||
meta: {
|
||||
custom: { data: 'here' },
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
).toEqual({
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: '[s2]: Lorem ipsum',
|
||||
detail: 'Vivamus pulvinar sem ac luctus ultrices.',
|
||||
documentationUrl: 'http://helpmenow.com/problem1',
|
||||
meta: {
|
||||
affectedServices: ['s2'],
|
||||
},
|
||||
});
|
||||
},
|
||||
})
|
||||
)
|
||||
).toEqual({
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: '1 service is unavailable: s2',
|
||||
detail: 'See the status page for more information',
|
||||
meta: {
|
||||
affectedServices: ['s2'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('when multiple services is at highest level', () => {
|
||||
it('returns aggregated information about the affected services', () => {
|
||||
expect(
|
||||
getSummaryStatus(
|
||||
Object.entries({
|
||||
s1: degraded,
|
||||
s2: {
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: 'Lorem ipsum',
|
||||
detail: 'Vivamus pulvinar sem ac luctus ultrices.',
|
||||
documentationUrl: 'http://helpmenow.com/problem1',
|
||||
meta: {
|
||||
custom: { data: 'here' },
|
||||
},
|
||||
it('returns correct summary when multiple services are affected', () => {
|
||||
expect(
|
||||
getSummaryStatus(
|
||||
Object.entries({
|
||||
s1: degraded,
|
||||
s2: {
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: 'Lorem ipsum',
|
||||
detail: 'Vivamus pulvinar sem ac luctus ultrices.',
|
||||
documentationUrl: 'http://helpmenow.com/problem1',
|
||||
meta: {
|
||||
custom: { data: 'here' },
|
||||
},
|
||||
s3: {
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: 'Proin mattis',
|
||||
detail: 'Nunc quis nulla at mi lobortis pretium.',
|
||||
documentationUrl: 'http://helpmenow.com/problem2',
|
||||
meta: {
|
||||
other: { data: 'over there' },
|
||||
},
|
||||
},
|
||||
s3: {
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: 'Proin mattis',
|
||||
detail: 'Nunc quis nulla at mi lobortis pretium.',
|
||||
documentationUrl: 'http://helpmenow.com/problem2',
|
||||
meta: {
|
||||
other: { data: 'over there' },
|
||||
},
|
||||
})
|
||||
)
|
||||
).toEqual({
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: '[2] services are unavailable',
|
||||
detail: 'See the status page for more information',
|
||||
meta: {
|
||||
affectedServices: ['s2', 's3'],
|
||||
},
|
||||
});
|
||||
},
|
||||
})
|
||||
)
|
||||
).toEqual({
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: '2 services are unavailable: s2, s3',
|
||||
detail: 'See the status page for more information',
|
||||
meta: {
|
||||
affectedServices: ['s2', 's3'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('returns correct summary more than `maxServices` services are affected', () => {
|
||||
expect(
|
||||
getSummaryStatus(
|
||||
Object.entries({
|
||||
s1: degraded,
|
||||
s2: available,
|
||||
s3: degraded,
|
||||
s4: degraded,
|
||||
s5: degraded,
|
||||
s6: available,
|
||||
s7: degraded,
|
||||
}),
|
||||
{ maxServices: 3 }
|
||||
)
|
||||
).toEqual({
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '5 services are degraded: s1, s3, s4 and 2 other(s)',
|
||||
detail: 'See the status page for more information',
|
||||
meta: {
|
||||
affectedServices: ['s1', 's3', 's4', 's5', 's7'],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,11 +10,13 @@ import { ServiceStatus, ServiceStatusLevels, ServiceStatusLevel } from './types'
|
|||
|
||||
/**
|
||||
* Returns a single {@link ServiceStatus} that summarizes the most severe status level from a group of statuses.
|
||||
* @param statuses
|
||||
*/
|
||||
export const getSummaryStatus = (
|
||||
statuses: Array<[string, ServiceStatus]>,
|
||||
{ allAvailableSummary = `All services are available` }: { allAvailableSummary?: string } = {}
|
||||
{
|
||||
allAvailableSummary = `All services are available`,
|
||||
maxServices = 3,
|
||||
}: { allAvailableSummary?: string; maxServices?: number } = {}
|
||||
): ServiceStatus => {
|
||||
const { highestLevel, highestStatuses } = highestLevelSummary(statuses);
|
||||
|
||||
|
@ -23,30 +25,38 @@ export const getSummaryStatus = (
|
|||
level: ServiceStatusLevels.available,
|
||||
summary: allAvailableSummary,
|
||||
};
|
||||
} else if (highestStatuses.length === 1) {
|
||||
const [serviceName, status] = highestStatuses[0]! as [string, ServiceStatus];
|
||||
return {
|
||||
...status,
|
||||
summary: `[${serviceName}]: ${status.summary!}`,
|
||||
// TODO: include URL to status page
|
||||
detail: status.detail ?? `See the status page for more information`,
|
||||
meta: {
|
||||
affectedServices: [serviceName],
|
||||
},
|
||||
};
|
||||
} else {
|
||||
const affectedServices = highestStatuses.map(([serviceName]) => serviceName);
|
||||
return {
|
||||
level: highestLevel,
|
||||
summary: `[${highestStatuses.length}] services are ${highestLevel.toString()}`,
|
||||
summary: getSummaryContent(affectedServices, highestLevel, maxServices),
|
||||
// TODO: include URL to status page
|
||||
detail: `See the status page for more information`,
|
||||
meta: {
|
||||
affectedServices: highestStatuses.map(([serviceName]) => serviceName),
|
||||
affectedServices,
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const getSummaryContent = (
|
||||
affectedServices: string[],
|
||||
statusLevel: ServiceStatusLevel,
|
||||
maxServices: number
|
||||
): string => {
|
||||
const serviceCount = affectedServices.length;
|
||||
if (serviceCount === 1) {
|
||||
return `1 service is ${statusLevel.toString()}: ${affectedServices[0]}`;
|
||||
} else if (serviceCount > maxServices) {
|
||||
const exceedingCount = serviceCount - maxServices;
|
||||
return `${serviceCount} services are ${statusLevel.toString()}: ${affectedServices
|
||||
.slice(0, maxServices)
|
||||
.join(', ')} and ${exceedingCount} other(s)`;
|
||||
} else {
|
||||
return `${serviceCount} services are ${statusLevel.toString()}: ${affectedServices.join(', ')}`;
|
||||
}
|
||||
};
|
||||
|
||||
type StatusPair = [string, ServiceStatus];
|
||||
|
||||
const highestLevelSummary = (
|
||||
|
|
|
@ -73,7 +73,7 @@ describe('PluginStatusService', () => {
|
|||
});
|
||||
expect(await serviceDegraded.getDerivedStatus$('a').pipe(first()).toPromise()).toEqual({
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[savedObjects]: savedObjects degraded',
|
||||
summary: '1 service is degraded: savedObjects',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
});
|
||||
|
@ -84,7 +84,7 @@ describe('PluginStatusService', () => {
|
|||
});
|
||||
expect(await serviceCritical.getDerivedStatus$('a').pipe(first()).toPromise()).toEqual({
|
||||
level: ServiceStatusLevels.critical,
|
||||
summary: '[elasticsearch]: elasticsearch critical',
|
||||
summary: '1 service is critical: elasticsearch',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
});
|
||||
|
@ -95,7 +95,7 @@ describe('PluginStatusService', () => {
|
|||
service.set('a', of({ level: ServiceStatusLevels.degraded, summary: 'a is degraded' }));
|
||||
expect(await service.getDerivedStatus$('b').pipe(first()).toPromise()).toEqual({
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[2] services are degraded',
|
||||
summary: '2 services are degraded: savedObjects, a',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
});
|
||||
|
@ -106,7 +106,7 @@ describe('PluginStatusService', () => {
|
|||
service.set('a', of({ level: ServiceStatusLevels.unavailable, summary: 'a is not working' }));
|
||||
expect(await service.getDerivedStatus$('b').pipe(first()).toPromise()).toEqual({
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: '[a]: a is not working',
|
||||
summary: '1 service is unavailable: a',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
});
|
||||
|
@ -120,7 +120,7 @@ describe('PluginStatusService', () => {
|
|||
service.set('a', of({ level: ServiceStatusLevels.unavailable, summary: 'a is not working' }));
|
||||
expect(await service.getDerivedStatus$('b').pipe(first()).toPromise()).toEqual({
|
||||
level: ServiceStatusLevels.critical,
|
||||
summary: '[elasticsearch]: elasticsearch critical',
|
||||
summary: '1 service is critical: elasticsearch',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
});
|
||||
|
@ -132,7 +132,7 @@ describe('PluginStatusService', () => {
|
|||
service.set('b', of({ level: ServiceStatusLevels.unavailable, summary: 'b is not working' }));
|
||||
expect(await service.getDerivedStatus$('c').pipe(first()).toPromise()).toEqual({
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: '[b]: b is not working',
|
||||
summary: '1 service is unavailable: b',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
});
|
||||
|
@ -166,19 +166,19 @@ describe('PluginStatusService', () => {
|
|||
expect(await serviceDegraded.getAll$().pipe(first()).toPromise()).toEqual({
|
||||
a: {
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[savedObjects]: savedObjects degraded',
|
||||
summary: '1 service is degraded: savedObjects',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
},
|
||||
b: {
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[savedObjects]: savedObjects degraded',
|
||||
summary: '1 service is degraded: savedObjects',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
},
|
||||
c: {
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[savedObjects]: savedObjects degraded',
|
||||
summary: '1 service is degraded: savedObjects',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
},
|
||||
|
@ -191,19 +191,19 @@ describe('PluginStatusService', () => {
|
|||
expect(await serviceCritical.getAll$().pipe(first()).toPromise()).toEqual({
|
||||
a: {
|
||||
level: ServiceStatusLevels.critical,
|
||||
summary: '[elasticsearch]: elasticsearch critical',
|
||||
summary: '1 service is critical: elasticsearch',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
},
|
||||
b: {
|
||||
level: ServiceStatusLevels.critical,
|
||||
summary: '[elasticsearch]: elasticsearch critical',
|
||||
summary: '1 service is critical: elasticsearch',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
},
|
||||
c: {
|
||||
level: ServiceStatusLevels.critical,
|
||||
summary: '[elasticsearch]: elasticsearch critical',
|
||||
summary: '1 service is critical: elasticsearch',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
},
|
||||
|
@ -218,13 +218,13 @@ describe('PluginStatusService', () => {
|
|||
a: { level: ServiceStatusLevels.available, summary: 'a status' }, // a is available depsite savedObjects being degraded
|
||||
b: {
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[savedObjects]: savedObjects degraded',
|
||||
summary: '1 service is degraded: savedObjects',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
},
|
||||
c: {
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[2] services are degraded',
|
||||
summary: '2 services are degraded: savedObjects, b',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
},
|
||||
|
@ -298,7 +298,7 @@ describe('PluginStatusService', () => {
|
|||
a: { level: ServiceStatusLevels.unavailable, summary: 'Status check timed out after 30s' },
|
||||
b: {
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: '[a]: Status check timed out after 30s',
|
||||
summary: '1 service is unavailable: a',
|
||||
detail: 'See the status page for more information',
|
||||
meta: {
|
||||
affectedServices: ['a'],
|
||||
|
@ -341,7 +341,7 @@ describe('PluginStatusService', () => {
|
|||
a: { level: ServiceStatusLevels.available, summary: 'a status' }, // a is available depsite savedObjects being degraded
|
||||
b: {
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[savedObjects]: savedObjects degraded',
|
||||
summary: '1 service is degraded: savedObjects',
|
||||
detail: 'See the status page for more information',
|
||||
meta: expect.any(Object),
|
||||
},
|
||||
|
|
|
@ -188,7 +188,7 @@ describe('StatusService', () => {
|
|||
);
|
||||
expect(await setup.overall$.pipe(first()).toPromise()).toMatchObject({
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[2] services are degraded',
|
||||
summary: '2 services are degraded: elasticsearch, savedObjects',
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -208,15 +208,15 @@ describe('StatusService', () => {
|
|||
const subResult3 = await setup.overall$.pipe(first()).toPromise();
|
||||
expect(subResult1).toMatchObject({
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[2] services are degraded',
|
||||
summary: '2 services are degraded: elasticsearch, savedObjects',
|
||||
});
|
||||
expect(subResult2).toMatchObject({
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[2] services are degraded',
|
||||
summary: '2 services are degraded: elasticsearch, savedObjects',
|
||||
});
|
||||
expect(subResult3).toMatchObject({
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[2] services are degraded',
|
||||
summary: '2 services are degraded: elasticsearch, savedObjects',
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -265,7 +265,7 @@ describe('StatusService', () => {
|
|||
"savedObjects",
|
||||
],
|
||||
},
|
||||
"summary": "[savedObjects]: This is degraded!",
|
||||
"summary": "1 service is degraded: savedObjects",
|
||||
},
|
||||
Object {
|
||||
"level": available,
|
||||
|
@ -315,7 +315,7 @@ describe('StatusService', () => {
|
|||
"savedObjects",
|
||||
],
|
||||
},
|
||||
"summary": "[savedObjects]: This is degraded!",
|
||||
"summary": "1 service is degraded: savedObjects",
|
||||
},
|
||||
Object {
|
||||
"level": available,
|
||||
|
@ -340,7 +340,7 @@ describe('StatusService', () => {
|
|||
);
|
||||
expect(await setup.coreOverall$.pipe(first()).toPromise()).toMatchObject({
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[2] services are degraded',
|
||||
summary: '2 services are degraded: elasticsearch, savedObjects',
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -357,7 +357,7 @@ describe('StatusService', () => {
|
|||
);
|
||||
expect(await setup.coreOverall$.pipe(first()).toPromise()).toMatchObject({
|
||||
level: ServiceStatusLevels.critical,
|
||||
summary: '[savedObjects]: This is critical!',
|
||||
summary: '1 service is critical: savedObjects',
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -379,15 +379,15 @@ describe('StatusService', () => {
|
|||
|
||||
expect(subResult1).toMatchObject({
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[2] services are degraded',
|
||||
summary: '2 services are degraded: elasticsearch, savedObjects',
|
||||
});
|
||||
expect(subResult2).toMatchObject({
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[2] services are degraded',
|
||||
summary: '2 services are degraded: elasticsearch, savedObjects',
|
||||
});
|
||||
expect(subResult3).toMatchObject({
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: '[2] services are degraded',
|
||||
summary: '2 services are degraded: elasticsearch, savedObjects',
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -436,7 +436,7 @@ describe('StatusService', () => {
|
|||
"savedObjects",
|
||||
],
|
||||
},
|
||||
"summary": "[savedObjects]: This is degraded!",
|
||||
"summary": "1 service is degraded: savedObjects",
|
||||
},
|
||||
Object {
|
||||
"level": available,
|
||||
|
@ -486,7 +486,7 @@ describe('StatusService', () => {
|
|||
"savedObjects",
|
||||
],
|
||||
},
|
||||
"summary": "[savedObjects]: This is degraded!",
|
||||
"summary": "1 service is degraded: savedObjects",
|
||||
},
|
||||
Object {
|
||||
"level": available,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue