Skip to content

Commit

Permalink
[Actions] Fixed actions telemetry for multiple namespaces usage (#114748
Browse files Browse the repository at this point in the history
)

* [Actions] Fixed actions telemetry for multiple namespaces usage

* fixed tests
  • Loading branch information
YulNaumenko authored Oct 13, 2021
1 parent 77ad8fe commit c737c39
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 105 deletions.
159 changes: 90 additions & 69 deletions x-pack/plugins/actions/server/usage/actions_telemetry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -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,
Expand All @@ -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: {
Expand Down Expand Up @@ -202,28 +209,34 @@ Object {
},
})
);
const actionsBulkGet = jest.fn();
actionsBulkGet.mockReturnValue({
saved_objects: [
{
id: '1',
attributes: {
actionTypeId: '.server-log',
},
},
{
id: '123',
attributes: {
actionTypeId: '.slack',
},
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, 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,
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -399,34 +412,42 @@ Object {
},
})
);
const actionsBulkGet = jest.fn();
actionsBulkGet.mockReturnValue({
saved_objects: [
{
id: '1',
attributes: {
actionTypeId: '.server-log',
},
},
{
id: '123',
attributes: {
actionTypeId: '.slack',
},
},
{
id: '456',
attributes: {
actionTypeId: '.email',
},
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',
},
},
},
],
},
],
});
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,
Expand Down
46 changes: 28 additions & 18 deletions x-pack/plugins/actions/server/usage/actions_telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
21 changes: 3 additions & 18 deletions x-pack/plugins/actions/server/usage/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit c737c39

Please sign in to comment.