Skip to content

Commit

Permalink
[Observability] not showing empty state when apps return hasData false (
Browse files Browse the repository at this point in the history
#71844) (#72065)

* show empty state when has data returns false

* adding return type

* addressing pr comments

Co-authored-by: Elastic Machine <[email protected]>

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
cauemarcondes and elasticmachine authored Jul 16, 2020
1 parent 310c880 commit 14d0645
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 13 deletions.
182 changes: 181 additions & 1 deletion x-pack/plugins/observability/public/data_handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,19 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { registerDataHandler, getDataHandler } from './data_handler';
import {
registerDataHandler,
getDataHandler,
unregisterDataHandler,
fetchHasData,
} from './data_handler';
import moment from 'moment';
import {
ApmFetchDataResponse,
LogsFetchDataResponse,
MetricsFetchDataResponse,
UptimeFetchDataResponse,
} from './typings';

const params = {
absoluteTime: {
Expand All @@ -19,6 +30,16 @@ const params = {
};

describe('registerDataHandler', () => {
const originalConsole = global.console;
beforeAll(() => {
// mocks console to avoid poluting the test output
global.console = ({ error: jest.fn() } as unknown) as typeof console;
});

afterAll(() => {
global.console = originalConsole;
});

describe('APM', () => {
registerDataHandler({
appName: 'apm',
Expand Down Expand Up @@ -369,4 +390,163 @@ describe('registerDataHandler', () => {
expect(hasData).toBeTruthy();
});
});
describe('fetchHasData', () => {
it('returns false when an exception happens', async () => {
unregisterDataHandler({ appName: 'apm' });
unregisterDataHandler({ appName: 'infra_logs' });
unregisterDataHandler({ appName: 'infra_metrics' });
unregisterDataHandler({ appName: 'uptime' });

registerDataHandler({
appName: 'apm',
fetchData: async () => (({} as unknown) as ApmFetchDataResponse),
hasData: async () => {
throw new Error('BOOM');
},
});
registerDataHandler({
appName: 'infra_logs',
fetchData: async () => (({} as unknown) as LogsFetchDataResponse),
hasData: async () => {
throw new Error('BOOM');
},
});
registerDataHandler({
appName: 'infra_metrics',
fetchData: async () => (({} as unknown) as MetricsFetchDataResponse),
hasData: async () => {
throw new Error('BOOM');
},
});
registerDataHandler({
appName: 'uptime',
fetchData: async () => (({} as unknown) as UptimeFetchDataResponse),
hasData: async () => {
throw new Error('BOOM');
},
});
expect(await fetchHasData()).toEqual({
apm: false,
uptime: false,
infra_logs: false,
infra_metrics: false,
});
});
it('returns true when has data and false when an exception happens', async () => {
unregisterDataHandler({ appName: 'apm' });
unregisterDataHandler({ appName: 'infra_logs' });
unregisterDataHandler({ appName: 'infra_metrics' });
unregisterDataHandler({ appName: 'uptime' });

registerDataHandler({
appName: 'apm',
fetchData: async () => (({} as unknown) as ApmFetchDataResponse),
hasData: async () => true,
});
registerDataHandler({
appName: 'infra_logs',
fetchData: async () => (({} as unknown) as LogsFetchDataResponse),
hasData: async () => true,
});
registerDataHandler({
appName: 'infra_metrics',
fetchData: async () => (({} as unknown) as MetricsFetchDataResponse),
hasData: async () => {
throw new Error('BOOM');
},
});
registerDataHandler({
appName: 'uptime',
fetchData: async () => (({} as unknown) as UptimeFetchDataResponse),
hasData: async () => {
throw new Error('BOOM');
},
});
expect(await fetchHasData()).toEqual({
apm: true,
uptime: false,
infra_logs: true,
infra_metrics: false,
});
});
it('returns true when has data', async () => {
unregisterDataHandler({ appName: 'apm' });
unregisterDataHandler({ appName: 'infra_logs' });
unregisterDataHandler({ appName: 'infra_metrics' });
unregisterDataHandler({ appName: 'uptime' });

registerDataHandler({
appName: 'apm',
fetchData: async () => (({} as unknown) as ApmFetchDataResponse),
hasData: async () => true,
});
registerDataHandler({
appName: 'infra_logs',
fetchData: async () => (({} as unknown) as LogsFetchDataResponse),
hasData: async () => true,
});
registerDataHandler({
appName: 'infra_metrics',
fetchData: async () => (({} as unknown) as MetricsFetchDataResponse),
hasData: async () => true,
});
registerDataHandler({
appName: 'uptime',
fetchData: async () => (({} as unknown) as UptimeFetchDataResponse),
hasData: async () => true,
});
expect(await fetchHasData()).toEqual({
apm: true,
uptime: true,
infra_logs: true,
infra_metrics: true,
});
});
it('returns false when has no data', async () => {
unregisterDataHandler({ appName: 'apm' });
unregisterDataHandler({ appName: 'infra_logs' });
unregisterDataHandler({ appName: 'infra_metrics' });
unregisterDataHandler({ appName: 'uptime' });

registerDataHandler({
appName: 'apm',
fetchData: async () => (({} as unknown) as ApmFetchDataResponse),
hasData: async () => false,
});
registerDataHandler({
appName: 'infra_logs',
fetchData: async () => (({} as unknown) as LogsFetchDataResponse),
hasData: async () => false,
});
registerDataHandler({
appName: 'infra_metrics',
fetchData: async () => (({} as unknown) as MetricsFetchDataResponse),
hasData: async () => false,
});
registerDataHandler({
appName: 'uptime',
fetchData: async () => (({} as unknown) as UptimeFetchDataResponse),
hasData: async () => false,
});
expect(await fetchHasData()).toEqual({
apm: false,
uptime: false,
infra_logs: false,
infra_metrics: false,
});
});
it('returns false when has data was not registered', async () => {
unregisterDataHandler({ appName: 'apm' });
unregisterDataHandler({ appName: 'infra_logs' });
unregisterDataHandler({ appName: 'infra_metrics' });
unregisterDataHandler({ appName: 'uptime' });

expect(await fetchHasData()).toEqual({
apm: false,
uptime: false,
infra_logs: false,
infra_metrics: false,
});
});
});
});
26 changes: 22 additions & 4 deletions x-pack/plugins/observability/public/data_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,27 @@ export function getDataHandler<T extends ObservabilityApp>(appName: T) {
}
}

export async function fetchHasData() {
export async function fetchHasData(): Promise<Record<ObservabilityApp, boolean>> {
const apps: ObservabilityApp[] = ['apm', 'uptime', 'infra_logs', 'infra_metrics'];
const promises = apps.map((app) => getDataHandler(app)?.hasData());
const [apm, uptime, logs, metrics] = await Promise.allSettled(promises);
return { apm, uptime, infra_logs: logs, infra_metrics: metrics };

const promises = apps.map(async (app) => getDataHandler(app)?.hasData() || false);

const results = await Promise.allSettled(promises);

const [apm, uptime, logs, metrics] = results.map((result) => {
if (result.status === 'fulfilled') {
return result.value;
}

// eslint-disable-next-line no-console
console.error('Error while fetching has data', result.reason);
return false;
});

return {
apm,
uptime,
infra_logs: logs,
infra_metrics: metrics,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -495,31 +495,31 @@ storiesOf('app/Overview', module)
fetchData: fetchApmData,
// @ts-ignore thows an error instead
hasData: async () => {
new Error('Error has data');
throw new Error('Error has data');
},
});
registerDataHandler({
appName: 'infra_logs',
fetchData: fetchLogsData,
// @ts-ignore thows an error instead
hasData: async () => {
new Error('Error has data');
throw new Error('Error has data');
},
});
registerDataHandler({
appName: 'infra_metrics',
fetchData: fetchMetricsData,
// @ts-ignore thows an error instead
hasData: async () => {
new Error('Error has data');
throw new Error('Error has data');
},
});
registerDataHandler({
appName: 'uptime',
fetchData: fetchUptimeData,
// @ts-ignore thows an error instead
hasData: async () => {
new Error('Error has data');
throw new Error('Error has data');
},
});
return (
Expand All @@ -545,31 +545,31 @@ storiesOf('app/Overview', module)
fetchData: fetchApmData,
// @ts-ignore thows an error instead
hasData: async () => {
new Error('Error has data');
throw new Error('Error has data');
},
});
registerDataHandler({
appName: 'infra_logs',
fetchData: fetchLogsData,
// @ts-ignore thows an error instead
hasData: async () => {
new Error('Error has data');
throw new Error('Error has data');
},
});
registerDataHandler({
appName: 'infra_metrics',
fetchData: fetchMetricsData,
// @ts-ignore thows an error instead
hasData: async () => {
new Error('Error has data');
throw new Error('Error has data');
},
});
registerDataHandler({
appName: 'uptime',
fetchData: fetchUptimeData,
// @ts-ignore thows an error instead
hasData: async () => {
new Error('Error has data');
throw new Error('Error has data');
},
});
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ import { getNewsFeed } from './get_news_feed';
import { AppMountContext } from 'kibana/public';

describe('getNewsFeed', () => {
const originalConsole = global.console;
beforeAll(() => {
// mocks console to avoid poluting the test output
global.console = ({ error: jest.fn() } as unknown) as typeof console;
});

afterAll(() => {
global.console = originalConsole;
});
it('Returns empty array when api throws exception', async () => {
const core = ({
http: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ import { getObservabilityAlerts } from './get_observability_alerts';
const basePath = { prepend: (path: string) => path };

describe('getObservabilityAlerts', () => {
const originalConsole = global.console;
beforeAll(() => {
// mocks console to avoid poluting the test output
global.console = ({ error: jest.fn() } as unknown) as typeof console;
});

afterAll(() => {
global.console = originalConsole;
});
it('Returns empty array when api throws exception', async () => {
const core = ({
http: {
Expand Down

0 comments on commit 14d0645

Please sign in to comment.