[Actions] Fixed actions telemetry for multiple namespaces usage (#114748)

* [Actions] Fixed actions telemetry for multiple namespaces usage

* fixed tests
This commit is contained in:
Yuliia Naumenko 2021-10-13 14:22:40 -07:00 committed by GitHub
parent 77ad8fe991
commit c737c393cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 121 additions and 105 deletions

View file

@ -116,7 +116,7 @@ Object {
test('getInUseTotalCount', async () => {
const mockEsClient = elasticsearchClientMock.createClusterClient().asScoped().asInternalUser;
mockEsClient.search.mockReturnValue(
mockEsClient.search.mockReturnValueOnce(
// @ts-expect-error not full search response
elasticsearchClientMock.createSuccessTransportRequestPromise({
aggregations: {
@ -134,28 +134,35 @@ Object {
},
})
);
const actionsBulkGet = jest.fn();
actionsBulkGet.mockReturnValue({
saved_objects: [
{
id: '1',
attributes: {
actionTypeId: '.server-log',
},
},
{
id: '123',
attributes: {
actionTypeId: '.slack',
},
},
],
});
const telemetry = await getInUseTotalCount(mockEsClient, actionsBulkGet, 'test');
expect(mockEsClient.search).toHaveBeenCalledTimes(1);
expect(actionsBulkGet).toHaveBeenCalledTimes(1);
mockEsClient.search.mockReturnValueOnce(
// @ts-expect-error not full search response
elasticsearchClientMock.createSuccessTransportRequestPromise({
hits: {
hits: [
{
_source: {
action: {
id: '1',
actionTypeId: '.server-log',
},
},
},
{
_source: {
action: {
id: '2',
actionTypeId: '.slack',
},
},
},
],
},
})
);
const telemetry = await getInUseTotalCount(mockEsClient, 'test');
expect(mockEsClient.search).toHaveBeenCalledTimes(2);
expect(telemetry).toMatchInlineSnapshot(`
Object {
"countByAlertHistoryConnectorType": 0,
@ -170,7 +177,7 @@ Object {
test('getInUseTotalCount should count preconfigured alert history connector usage', async () => {
const mockEsClient = elasticsearchClientMock.createClusterClient().asScoped().asInternalUser;
mockEsClient.search.mockReturnValue(
mockEsClient.search.mockReturnValueOnce(
// @ts-expect-error not full search response
elasticsearchClientMock.createSuccessTransportRequestPromise({
aggregations: {
@ -202,28 +209,34 @@ Object {
},
})
);
const actionsBulkGet = jest.fn();
actionsBulkGet.mockReturnValue({
saved_objects: [
{
id: '1',
attributes: {
actionTypeId: '.server-log',
},
mockEsClient.search.mockReturnValueOnce(
// @ts-expect-error not full search response
elasticsearchClientMock.createSuccessTransportRequestPromise({
hits: {
hits: [
{
_source: {
action: {
id: '1',
actionTypeId: '.server-log',
},
},
},
{
_source: {
action: {
id: '2',
actionTypeId: '.slack',
},
},
},
],
},
{
id: '123',
attributes: {
actionTypeId: '.slack',
},
},
],
});
const telemetry = await getInUseTotalCount(mockEsClient, actionsBulkGet, 'test');
expect(mockEsClient.search).toHaveBeenCalledTimes(1);
expect(actionsBulkGet).toHaveBeenCalledTimes(1);
})
);
const telemetry = await getInUseTotalCount(mockEsClient, 'test');
expect(mockEsClient.search).toHaveBeenCalledTimes(2);
expect(telemetry).toMatchInlineSnapshot(`
Object {
"countByAlertHistoryConnectorType": 1,
@ -359,7 +372,7 @@ Object {
test('getInUseTotalCount() accounts for preconfigured connectors', async () => {
const mockEsClient = elasticsearchClientMock.createClusterClient().asScoped().asInternalUser;
mockEsClient.search.mockReturnValue(
mockEsClient.search.mockReturnValueOnce(
// @ts-expect-error not full search response
elasticsearchClientMock.createSuccessTransportRequestPromise({
aggregations: {
@ -399,34 +412,42 @@ Object {
},
})
);
const actionsBulkGet = jest.fn();
actionsBulkGet.mockReturnValue({
saved_objects: [
{
id: '1',
attributes: {
actionTypeId: '.server-log',
},
mockEsClient.search.mockReturnValueOnce(
// @ts-expect-error not full search response
elasticsearchClientMock.createSuccessTransportRequestPromise({
hits: {
hits: [
{
_source: {
action: {
id: '1',
actionTypeId: '.server-log',
},
},
},
{
_source: {
action: {
id: '2',
actionTypeId: '.slack',
},
},
},
{
_source: {
action: {
id: '3',
actionTypeId: '.email',
},
},
},
],
},
{
id: '123',
attributes: {
actionTypeId: '.slack',
},
},
{
id: '456',
attributes: {
actionTypeId: '.email',
},
},
],
});
const telemetry = await getInUseTotalCount(mockEsClient, actionsBulkGet, 'test');
expect(mockEsClient.search).toHaveBeenCalledTimes(1);
expect(actionsBulkGet).toHaveBeenCalledTimes(1);
})
);
const telemetry = await getInUseTotalCount(mockEsClient, 'test');
expect(mockEsClient.search).toHaveBeenCalledTimes(2);
expect(telemetry).toMatchInlineSnapshot(`
Object {
"countByAlertHistoryConnectorType": 1,

View file

@ -5,12 +5,7 @@
* 2.0.
*/
import {
ElasticsearchClient,
SavedObjectsBaseOptions,
SavedObjectsBulkGetObject,
SavedObjectsBulkResponse,
} from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { AlertHistoryEsIndexConnectorId } from '../../common';
import { ActionResult, PreConfiguredAction } from '../types';
@ -86,10 +81,6 @@ export async function getTotalCount(
export async function getInUseTotalCount(
esClient: ElasticsearchClient,
actionsBulkGet: (
objects?: SavedObjectsBulkGetObject[] | undefined,
options?: SavedObjectsBaseOptions | undefined
) => Promise<SavedObjectsBulkResponse<ActionResult<Record<string, unknown>>>>,
kibanaIndex: string
): Promise<{
countTotal: number;
@ -259,15 +250,34 @@ export async function getInUseTotalCount(
const preconfiguredActionsAggs =
// @ts-expect-error aggegation type is not specified
actionResults.aggregations.preconfigured_actions?.preconfiguredActionRefIds.value;
const bulkFilter = Object.entries(aggs.connectorIds).map(([key]) => ({
id: key,
type: 'action',
fields: ['id', 'actionTypeId'],
}));
const actions = await actionsBulkGet(bulkFilter);
const countByActionTypeId = actions.saved_objects.reduce(
const {
body: { hits: actions },
} = await esClient.search<{
action: ActionResult;
}>({
index: kibanaIndex,
_source_includes: ['action'],
body: {
query: {
bool: {
must: [
{
term: { type: 'action' },
},
{
terms: {
_id: Object.entries(aggs.connectorIds).map(([key]) => `action:${key}`),
},
},
],
},
},
},
});
const countByActionTypeId = actions.hits.reduce(
(actionTypeCount: Record<string, number>, action) => {
const alertTypeId = replaceFirstAndLastDotSymbols(action.attributes.actionTypeId);
const actionSource = action._source!;
const alertTypeId = replaceFirstAndLastDotSymbols(actionSource.action.actionTypeId);
const currentCount =
actionTypeCount[alertTypeId] !== undefined ? actionTypeCount[alertTypeId] : 0;
actionTypeCount[alertTypeId] = currentCount + 1;

View file

@ -5,19 +5,14 @@
* 2.0.
*/
import {
Logger,
CoreSetup,
SavedObjectsBulkGetObject,
SavedObjectsBaseOptions,
} from 'kibana/server';
import { Logger, CoreSetup } from 'kibana/server';
import moment from 'moment';
import {
RunContext,
TaskManagerSetupContract,
TaskManagerStartContract,
} from '../../../task_manager/server';
import { ActionResult, PreConfiguredAction } from '../types';
import { PreConfiguredAction } from '../types';
import { getTotalCount, getInUseTotalCount } from './actions_telemetry';
export const TELEMETRY_TASK_TYPE = 'actions_telemetry';
@ -83,22 +78,12 @@ export function telemetryTaskRunner(
},
]) => client.asInternalUser
);
const actionsBulkGet = (
objects?: SavedObjectsBulkGetObject[],
options?: SavedObjectsBaseOptions
) => {
return core
.getStartServices()
.then(([{ savedObjects }]) =>
savedObjects.createInternalRepository(['action']).bulkGet<ActionResult>(objects, options)
);
};
return {
async run() {
const esClient = await getEsClient();
return Promise.all([
getTotalCount(esClient, kibanaIndex, preconfiguredActions),
getInUseTotalCount(esClient, actionsBulkGet, kibanaIndex),
getInUseTotalCount(esClient, kibanaIndex),
])
.then(([totalAggegations, totalInUse]) => {
return {