Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Dataset quality] Including integration information within stats #171663

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion x-pack/plugins/dataset_quality/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"server": true,
"browser": true,
"configPath": ["xpack", "datasetQuality"],
"requiredPlugins": ["data", "kibanaReact", "kibanaUtils", "controls", "embeddable", "share"],
"requiredPlugins": ["data", "kibanaReact", "kibanaUtils", "controls", "embeddable", "share", "fleet"],
"optionalPlugins": [],
"requiredBundles": [],
"extraPublicDirs": ["common"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ describe('getDataStreams', () => {
esClient: esClientMock,
type: 'logs',
datasetQuery: 'nginx',
sortOrder: 'asc',
uncategorisedOnly: true,
});
expect(dataStreamService.getMatchingDataStreams).toHaveBeenCalledWith(expect.anything(), {
Expand All @@ -129,7 +128,6 @@ describe('getDataStreams', () => {
esClient: esClientMock,
type: 'logs',
datasetQuery: 'nginx',
sortOrder: 'asc',
uncategorisedOnly: true,
});
expect(results.items.length).toBe(1);
Expand All @@ -140,62 +138,36 @@ describe('getDataStreams', () => {
esClient: esClientMock,
type: 'logs',
datasetQuery: 'nginx',
sortOrder: 'asc',
uncategorisedOnly: false,
});
expect(results.items.length).toBe(5);
});
});
describe('Can be sorted', () => {
it('Ascending', async () => {
const esClientMock = elasticsearchServiceMock.createElasticsearchClient();
const results = await getDataStreams({
esClient: esClientMock,
type: 'logs',
datasetQuery: 'nginx',
sortOrder: 'asc',
uncategorisedOnly: false,
});
expect(results.items[0].name).toBe('logs-elastic_agent-default');
});
it('Descending', async () => {
const esClientMock = elasticsearchServiceMock.createElasticsearchClient();
const results = await getDataStreams({
esClient: esClientMock,
type: 'logs',
datasetQuery: 'nginx',
sortOrder: 'desc',
uncategorisedOnly: false,
});
expect(results.items[0].name).toBe('logs-test.test-default');
});
});
it('Formats the items correctly', async () => {
const esClientMock = elasticsearchServiceMock.createElasticsearchClient();
const results = await getDataStreams({
esClient: esClientMock,
type: 'logs',
sortOrder: 'desc',
uncategorisedOnly: false,
});
expect(results.items).toEqual([
{ name: 'logs-test.test-default' },
expect(results.items.sort()).toEqual([
{
name: 'logs-elastic_agent.metricbeat-default',
integration: { name: 'elastic_agent', managed_by: 'fleet' },
name: 'logs-elastic_agent-default',
integration: 'elastic_agent',
},
{
name: 'logs-elastic_agent.fleet_server-default',
integration: { name: 'elastic_agent', managed_by: 'fleet' },
name: 'logs-elastic_agent.filebeat-default',
integration: 'elastic_agent',
},
{
name: 'logs-elastic_agent.filebeat-default',
integration: { name: 'elastic_agent', managed_by: 'fleet' },
name: 'logs-elastic_agent.fleet_server-default',
integration: 'elastic_agent',
},
{
name: 'logs-elastic_agent-default',
integration: { name: 'elastic_agent', managed_by: 'fleet' },
name: 'logs-elastic_agent.metricbeat-default',
integration: 'elastic_agent',
},
{ name: 'logs-test.test-default' },
]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ export async function getDataStreams(options: {
esClient: ElasticsearchClient;
type?: DataStreamTypes;
datasetQuery?: string;
sortOrder: 'asc' | 'desc';
uncategorisedOnly: boolean;
}) {
const { esClient, type, datasetQuery, uncategorisedOnly, sortOrder } = options;
const { esClient, type, datasetQuery, uncategorisedOnly } = options;

const allDataStreams = await dataStreamService.getMatchingDataStreams(esClient, {
type: type ?? '*',
Expand All @@ -31,25 +30,10 @@ export async function getDataStreams(options: {

const mappedDataStreams = filteredDataStreams.map((dataStream) => ({
name: dataStream.name,
...(dataStream._meta
? {
integration: {
name: dataStream._meta?.package?.name,
managed_by: dataStream._meta?.managed_by,
},
}
: {}),
integration: dataStream._meta?.package?.name,
}));

const sortedDataStreams = mappedDataStreams.sort((a, b) => {
if (sortOrder === 'desc') {
return b.name.localeCompare(a.name);
}

return a.name.localeCompare(b.name);
});

return {
items: sortedDataStreams,
items: mappedDataStreams,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,52 +63,30 @@ describe('getDataStreams', () => {
esClient: esClientMock,
type: 'logs',
datasetQuery: 'nginx',
sortOrder: 'asc',
});
expect(dataStreamService.getMatchingDataStreamsStats).toHaveBeenCalledWith(expect.anything(), {
type: 'logs',
dataset: '*nginx*',
});
});
describe('Can be sorted', () => {
it('Ascending', async () => {
const esClientMock = elasticsearchServiceMock.createElasticsearchClient();
const results = await getDataStreamsStats({
esClient: esClientMock,
type: 'logs',
sortOrder: 'asc',
});
expect(results.items[0].name).toBe('logs-elastic_agent-default');
});
it('Descending', async () => {
const esClientMock = elasticsearchServiceMock.createElasticsearchClient();
const results = await getDataStreamsStats({
esClient: esClientMock,
type: 'logs',
sortOrder: 'desc',
});
expect(results.items[0].name).toBe('logs-test.test-default');
});
});
it('Formats the items correctly', async () => {
const esClientMock = elasticsearchServiceMock.createElasticsearchClient();
const results = await getDataStreamsStats({
esClient: esClientMock,
type: 'logs',
sortOrder: 'desc',
});
expect(results.items).toEqual([
expect(results.items.sort()).toEqual([
{
name: 'logs-test.test-default',
size: '6.2mb',
size_bytes: 6570447,
last_activity: 1698913802000,
name: 'logs-elastic_agent-default',
size: '1gb',
size_bytes: 1170805528,
last_activity: 1698916071000,
},
{
name: 'logs-elastic_agent.metricbeat-default',
size: '1.6mb',
size_bytes: 1704807,
last_activity: 1698672046707,
name: 'logs-elastic_agent.filebeat-default',
size: '1.3mb',
size_bytes: 1459100,
last_activity: 1698902209996,
},
{
name: 'logs-elastic_agent.fleet_server-default',
Expand All @@ -117,16 +95,16 @@ describe('getDataStreams', () => {
last_activity: 1698914110010,
},
{
name: 'logs-elastic_agent.filebeat-default',
size: '1.3mb',
size_bytes: 1459100,
last_activity: 1698902209996,
name: 'logs-elastic_agent.metricbeat-default',
size: '1.6mb',
size_bytes: 1704807,
last_activity: 1698672046707,
},
{
name: 'logs-elastic_agent-default',
size: '1gb',
size_bytes: 1170805528,
last_activity: 1698916071000,
name: 'logs-test.test-default',
size: '6.2mb',
size_bytes: 6570447,
last_activity: 1698913802000,
},
]);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ export async function getDataStreamsStats(options: {
esClient: ElasticsearchClient;
type?: DataStreamTypes;
datasetQuery?: string;
sortOrder: 'asc' | 'desc';
}) {
const { esClient, type, datasetQuery, sortOrder } = options;
const { esClient, type, datasetQuery } = options;

const matchingDataStreamsStats = await dataStreamService.getMatchingDataStreamsStats(esClient, {
type: type ?? '*',
Expand All @@ -31,15 +30,7 @@ export async function getDataStreamsStats(options: {
};
});

const sortedDataStreams = mappedDataStreams.sort((a, b) => {
if (sortOrder === 'desc') {
return b.name.localeCompare(a.name);
}

return a.name.localeCompare(b.name);
});

return {
items: sortedDataStreams,
items: mappedDataStreams,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import * as t from 'io-ts';
import { keyBy, merge, values } from 'lodash';
import { dataStreamTypesRt, sortOrderRt } from '../../types/api_types';
import { dataStreamTypesRt } from '../../types/api_types';
import { DataStreamsStatResponse } from '../../types/data_stream';
import { createDatasetQualityServerRoute } from '../create_datasets_quality_server_route';
import { getDataStreams } from './get_data_streams';
Expand All @@ -21,19 +21,22 @@ const statsRoute = createDatasetQualityServerRoute({
t.partial({
datasetQuery: t.string,
}),
sortOrderRt,
]),
}),
options: {
tags: [],
},
async handler(resources): Promise<DataStreamsStatResponse> {
const { context, params } = resources;
const { context, params, plugins } = resources;
const coreContext = await context.core;

// Query datastreams as the current user as the Kibana internal user may not have all the required permissions
const esClient = coreContext.elasticsearch.client.asCurrentUser;

const fleetPluginStart = await plugins.fleet.start();
const packageClient = fleetPluginStart.packageService.asInternalUser;
yngrdyn marked this conversation as resolved.
Show resolved Hide resolved
const packages = await packageClient.getPackages();

const [dataStreams, dataStreamsStats] = await Promise.all([
getDataStreams({
esClient,
Expand All @@ -43,8 +46,20 @@ const statsRoute = createDatasetQualityServerRoute({
getDataStreamsStats({ esClient, ...params.query }),
]);

const installedPackages = dataStreams.items.map((item) => item.integration);

const integrations = packages
.filter((pkg) => installedPackages.includes(pkg.name))
.map((p) => ({
yngrdyn marked this conversation as resolved.
Show resolved Hide resolved
name: p.name,
title: p.title,
version: p.version,
icons: p.icons,
}));

return {
items: values(merge(keyBy(dataStreams.items, 'name'), keyBy(dataStreamsStats.items, 'name'))),
integrations,
};
},
});
Expand Down
11 changes: 7 additions & 4 deletions x-pack/plugins/dataset_quality/server/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
*/

import { CustomRequestHandlerContext } from '@kbn/core/server';
import { FleetSetupContract, FleetStartContract } from '@kbn/fleet-plugin/server';

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DatasetQualityPluginSetupDependencies {}
export interface DatasetQualityPluginSetupDependencies {
fleet: FleetSetupContract;
yngrdyn marked this conversation as resolved.
Show resolved Hide resolved
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DatasetQualityPluginStartDependencies {}
export interface DatasetQualityPluginStartDependencies {
fleet: FleetStartContract;
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DatasetQualityPluginSetup {}
Expand Down
4 changes: 0 additions & 4 deletions x-pack/plugins/dataset_quality/server/types/api_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,3 @@ export const dataStreamTypesRt = t.partial({
t.literal('profiling'),
]),
});

export const sortOrderRt = t.type({
sortOrder: t.union([t.literal('asc'), t.literal('desc')]),
});
7 changes: 3 additions & 4 deletions x-pack/plugins/dataset_quality/server/types/data_stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,19 @@
*/

import { ByteSize } from '@elastic/elasticsearch/lib/api/types';
import { Integration } from './integration';

export interface DataStreamsStatResponse {
items: DataStreamStat[];
integrations: Integration[];
}

export interface DataStreamStat {
name: string;
size?: ByteSize;
size_bytes?: number;
last_activity?: number;
integration?: {
name?: string;
managed_by?: string;
};
integration?: Integration;
}

export type DataStreamTypes = 'logs' | 'metrics' | 'traces' | 'synthetics' | 'profiling';
21 changes: 21 additions & 0 deletions x-pack/plugins/dataset_quality/server/types/integration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export interface Integration {
name: string;
title?: string;
version?: string;
icons?: IntegrationIcon[];
mohamedhamed-ahmed marked this conversation as resolved.
Show resolved Hide resolved
}

export interface IntegrationIcon {
path: string;
src: string;
title?: string;
size?: string;
type?: string;
}
1 change: 1 addition & 0 deletions x-pack/plugins/dataset_quality/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@kbn/core-plugins-server",
"@kbn/core-elasticsearch-server-mocks",
"@kbn/std",
"@kbn/fleet-plugin",
],
"exclude": [
"target/**/*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
params: {
query: {
type: 'logs',
sortOrder: 'asc',
},
},
});
Expand Down
Loading