Skip to content

Commit

Permalink
[7.9] [Logs UI] Tweak logs query for the observability dashboard (ela…
Browse files Browse the repository at this point in the history
  • Loading branch information
Alejandro Fernández authored Jul 30, 2020
1 parent 22da4f2 commit 46a17fd
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 47 deletions.
75 changes: 32 additions & 43 deletions x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@ import { callFetchLogSourceStatusAPI } from '../containers/logs/log_source/api/f
import { InfraClientCoreSetup, InfraClientStartDeps } from '../types';

interface StatsAggregation {
buckets: Array<{ key: string; doc_count: number }>;
}

interface SeriesAggregation {
buckets: Array<{
key_as_string: string;
key: number;
key: string;
doc_count: number;
dataset: StatsAggregation;
series: {
buckets: Array<{
key_as_string: string;
key: number;
doc_count: number;
}>;
};
}>;
}

Expand Down Expand Up @@ -131,18 +132,13 @@ function buildLogOverviewAggregations(logParams: LogParams, params: FetchDataPar
terms: {
field: 'event.dataset',
size: 4,
},
},
series: {
date_histogram: {
field: logParams.timestampField,
fixed_interval: params.bucketSize,
missing: 'unknown',
},
aggs: {
dataset: {
terms: {
field: 'event.dataset',
size: 4,
series: {
date_histogram: {
field: logParams.timestampField,
fixed_interval: params.bucketSize,
},
},
},
Expand All @@ -152,34 +148,27 @@ function buildLogOverviewAggregations(logParams: LogParams, params: FetchDataPar

function processLogsOverviewAggregations(aggregations: {
stats: StatsAggregation;
series: SeriesAggregation;
}): StatsAndSeries {
const processedStats = aggregations.stats.buckets.reduce<StatsAndSeries['stats']>(
(result, bucket) => {
result[bucket.key] = {
type: 'number',
label: bucket.key,
value: bucket.doc_count,
};

return result;
},
{}
);

const processedSeries = aggregations.series.buckets.reduce<StatsAndSeries['series']>(
(result, bucket) => {
const x = bucket.key; // the timestamp of the bucket
bucket.dataset.buckets.forEach((b) => {
const label = b.key;
result[label] = result[label] || { label, coordinates: [] };
result[label].coordinates.push({ x, y: b.doc_count });
});
const processedStats: StatsAndSeries['stats'] = {};
const processedSeries: StatsAndSeries['series'] = {};

return result;
},
{}
);
aggregations.stats.buckets.forEach((stat) => {
const label = stat.key;

processedStats[stat.key] = {
type: 'number',
label,
value: stat.doc_count,
};

stat.series.buckets.forEach((series) => {
processedSeries[label] = processedSeries[label] || { label, coordinates: [] };
processedSeries[label].coordinates.push({
x: series.key,
y: series.doc_count,
});
});
});

return {
stats: processedStats,
Expand Down
99 changes: 95 additions & 4 deletions x-pack/plugins/infra/public/utils/logs_overview_fetches.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,45 @@ import { CoreStart } from 'kibana/public';
import { coreMock } from 'src/core/public/mocks';
import { dataPluginMock } from 'src/plugins/data/public/mocks';
import { callFetchLogSourceStatusAPI } from '../containers/logs/log_source/api/fetch_log_source_status';
import { callFetchLogSourceConfigurationAPI } from '../containers/logs/log_source/api/fetch_log_source_configuration';
import { InfraClientStartDeps, InfraClientStartExports } from '../types';
import { getLogsHasDataFetcher } from './logs_overview_fetchers';
import { getLogsHasDataFetcher, getLogsOverviewDataFetcher } from './logs_overview_fetchers';
import { GetLogSourceConfigurationSuccessResponsePayload } from '../../common/http_api/log_sources/get_log_source_configuration';

jest.mock('../containers/logs/log_source/api/fetch_log_source_status');
const mockedCallFetchLogSourceStatusAPI = callFetchLogSourceStatusAPI as jest.MockedFunction<
typeof callFetchLogSourceStatusAPI
>;

jest.mock('../containers/logs/log_source/api/fetch_log_source_configuration');
const mockedCallFetchLogSourceConfigurationAPI = callFetchLogSourceConfigurationAPI as jest.MockedFunction<
typeof callFetchLogSourceConfigurationAPI
>;

const DEFAULT_PARAMS = {
absoluteTime: { start: 1593430680000, end: 1593430800000 },
relativeTime: { start: 'now-2m', end: 'now' }, // Doesn't matter for the test
bucketSize: '30s', // Doesn't matter for the test
};

function setup() {
const core = coreMock.createStart();
const data = dataPluginMock.createStartContract();

// `dataResponder.mockReturnValue()` will be the `response` in
//
// const searcher = data.search.getSearchStrategy('sth');
// searcher.search(...).subscribe((**response**) => {});
//
const dataResponder = jest.fn();

(data.search.search as jest.Mock).mockReturnValue({
subscribe: (progress: Function, error: Function, finish: Function) => {
progress(dataResponder());
finish();
},
});

const mockedGetStartServices = jest.fn(() => {
const deps = { data };
return Promise.resolve([
Expand All @@ -28,7 +55,7 @@ function setup() {
void 0 as InfraClientStartExports,
]) as Promise<[CoreStart, InfraClientStartDeps, InfraClientStartExports]>;
});
return { core, mockedGetStartServices };
return { core, mockedGetStartServices, dataResponder };
}

describe('Logs UI Observability Homepage Functions', () => {
Expand Down Expand Up @@ -80,8 +107,72 @@ describe('Logs UI Observability Homepage Functions', () => {
});

describe('getLogsOverviewDataFetcher()', () => {
it.skip('should work', async () => {
// Pending
beforeAll(() => {
mockedCallFetchLogSourceConfigurationAPI.mockResolvedValue({
data: {
configuration: {
logAlias: 'filebeat-*',
fields: { timestamp: '@timestamp', tiebreaker: '_doc' },
},
},
} as GetLogSourceConfigurationSuccessResponsePayload);
});

afterAll(() => {
mockedCallFetchLogSourceConfigurationAPI.mockReset();
});

it('should work', async () => {
const { mockedGetStartServices, dataResponder } = setup();

dataResponder.mockReturnValue({
rawResponse: {
aggregations: {
stats: {
buckets: [
{
key: 'nginx',
doc_count: 250, // Count is for 2 minutes
series: {
buckets: [
// Counts are per 30 seconds
{ key: 1593430680000, doc_count: 25 },
{ key: 1593430710000, doc_count: 50 },
{ key: 1593430740000, doc_count: 75 },
{ key: 1593430770000, doc_count: 100 },
],
},
},
],
},
},
},
});

const fetchData = getLogsOverviewDataFetcher(mockedGetStartServices);
const response = await fetchData(DEFAULT_PARAMS);

expect(response).toMatchObject({
stats: {
nginx: {
label: 'nginx',
type: 'number',
// Rate is normalized to logs in one minute
value: 125,
},
},
series: {
nginx: {
coordinates: [
// Rates are normalized to logs in one minute
{ x: 1593430680000, y: 50 },
{ x: 1593430710000, y: 100 },
{ x: 1593430740000, y: 150 },
{ x: 1593430770000, y: 200 },
],
},
},
});
});
});
});

0 comments on commit 46a17fd

Please sign in to comment.