Skip to content

Commit

Permalink
[8.9] [Uptime] Include synthetics-* for existing alerts (#160063) (#1…
Browse files Browse the repository at this point in the history
…61334)

# Backport

This will backport the following commits from `main` to `8.9`:
- [[Uptime] Include synthetics-* for existing alerts
(#160063)](#160063)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT
[{"author":{"name":"Shahzad","email":"shahzad31comp@gmail.com"},"sourceCommit":{"committedDate":"2023-07-06T10:26:22Z","message":"[Uptime]
Include synthetics-* for existing alerts
(#160063)","sha":"a2cc9a69241726a4498717f391ad18e35d38e7dc","branchLabelMapping":{"^v8.10.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","Team:uptime","release_note:skip","v8.9.0","v8.10.0"],"number":160063,"url":"https://github.com/elastic/kibana/pull/160063","mergeCommit":{"message":"[Uptime]
Include synthetics-* for existing alerts
(#160063)","sha":"a2cc9a69241726a4498717f391ad18e35d38e7dc"}},"sourceBranch":"main","suggestedTargetBranches":["8.9"],"targetPullRequestStates":[{"branch":"8.9","label":"v8.9.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.10.0","labelRegex":"^v8.10.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/160063","number":160063,"mergeCommit":{"message":"[Uptime]
Include synthetics-* for existing alerts
(#160063)","sha":"a2cc9a69241726a4498717f391ad18e35d38e7dc"}}]}]
BACKPORT-->
  • Loading branch information
shahzad31 authored Jul 6, 2023
1 parent 449fce9 commit 4699ce8
Show file tree
Hide file tree
Showing 12 changed files with 222 additions and 18 deletions.
2 changes: 1 addition & 1 deletion x-pack/plugins/synthetics/server/feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
*/

import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server';
import { umDynamicSettings } from './legacy_uptime/lib/saved_objects/uptime_settings';
import { syntheticsMonitorType, syntheticsParamType } from '../common/types/saved_objects';
import { SYNTHETICS_RULE_TYPES } from '../common/constants/synthetics_alerts';
import { privateLocationsSavedObjectName } from '../common/saved_objects/private_locations';
import { PLUGIN } from '../common/constants/plugin';
import { UPTIME_RULE_TYPES } from '../common/constants/uptime_alerts';
import { umDynamicSettings } from './legacy_uptime/lib/saved_objects/uptime_settings';
import { syntheticsApiKeyObjectType } from './legacy_uptime/lib/saved_objects/service_api_key';

export const uptimeFeature = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,10 @@ export const durationAnomalyAlertFactory: UptimeAlertTypeFactory<ActionGroupIds>
}) {
const uptimeEsClient = new UptimeEsClient(
savedObjectsClient,
scopedClusterClient.asCurrentUser
scopedClusterClient.asCurrentUser,
{
isLegacyAlert: true,
}
);
const { share, basePath } = server;
const alertsLocator: LocatorPublic<AlertsLocatorParams> | undefined =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,10 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory<ActionGroupIds> = (
share.url.locators.get(alertsLocatorID);
const uptimeEsClient = new UptimeEsClient(
savedObjectsClient,
scopedClusterClient.asCurrentUser
scopedClusterClient.asCurrentUser,
{
isLegacyAlert: true,
}
);

const filterString = await formatFilterString(uptimeEsClient, filters, search, libs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ export const tlsAlertFactory: UptimeAlertTypeFactory<ActionGroupIds> = (
spaceId,
startedAt,
state,
rule,
}) {
const { share, basePath } = _server;
const alertsLocator: LocatorPublic<AlertsLocatorParams> | undefined =
Expand All @@ -163,7 +164,10 @@ export const tlsAlertFactory: UptimeAlertTypeFactory<ActionGroupIds> = (

const uptimeEsClient = new UptimeEsClient(
savedObjectsClient,
scopedClusterClient.asCurrentUser
scopedClusterClient.asCurrentUser,
{
isLegacyAlert: true,
}
);

const certExpirationThreshold =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,10 @@ export const tlsLegacyAlertFactory: UptimeAlertTypeFactory<ActionGroupIds> = (_s

const uptimeEsClient = new UptimeEsClient(
savedObjectsClient,
scopedClusterClient.asCurrentUser
scopedClusterClient.asCurrentUser,
{
isLegacyAlert: true,
}
);
const { certs, total }: CertResult = await libs.requests.getCerts({
uptimeEsClient,
Expand Down
176 changes: 176 additions & 0 deletions x-pack/plugins/synthetics/server/legacy_uptime/lib/lib.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/*
* 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.
*/

import { UptimeEsClient } from './lib';
import { savedObjectsClientMock, uiSettingsServiceMock } from '@kbn/core/server/mocks';
import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks';
import { savedObjectsAdapter } from './saved_objects';

describe('UptimeEsClient', () => {
let uptimeEsClient: UptimeEsClient;
const savedObjectsClient = savedObjectsClientMock.create();
const esClient = elasticsearchClientMock.createClusterClient().asInternalUser;

beforeEach(() => {
uptimeEsClient = new UptimeEsClient(savedObjectsClient, esClient);
});

afterEach(() => {
jest.clearAllMocks();
});

describe('search', () => {
it('should call baseESClient.search with correct parameters', async () => {
const mockSearchParams = {
body: {
query: {
match_all: {},
},
},
};

const result = await uptimeEsClient.search({
body: {
query: {
match_all: {},
},
},
});

expect(esClient.search).toHaveBeenCalledWith(
{
index: 'heartbeat-8*,heartbeat-7*',
...mockSearchParams,
},
{ meta: true }
);
expect(result).toEqual({
body: {},
headers: {
'x-elastic-product': 'Elasticsearch',
},
meta: {},
statusCode: 200,
warnings: [],
});
});

it('should throw an error if baseESClient.search throws an error', async () => {
const mockSearchParams = {
body: {
query: {
match_all: {},
},
},
};
const mockError = new Error('Search error');
esClient.search.mockRejectedValueOnce(mockError);

await expect(uptimeEsClient.search(mockSearchParams)).rejects.toThrow(mockError);
expect(esClient.search).toHaveBeenCalledWith(
{
index: 'heartbeat-8*,heartbeat-7*',
...mockSearchParams,
},
{ meta: true }
);
});
});

describe('count', () => {
it('should call baseESClient.count with correct parameters', async () => {
const mockCountParams = {
index: 'example',
};

const result = await uptimeEsClient.count(mockCountParams);

expect(esClient.count).toHaveBeenCalledWith(mockCountParams, { meta: true });
expect(result).toEqual({
indices: 'heartbeat-8*,heartbeat-7*',
result: {
body: {},
headers: {
'x-elastic-product': 'Elasticsearch',
},
meta: {},
statusCode: 200,
warnings: [],
},
});
});

it('should throw an error if baseESClient.count throws an error', async () => {
const mockCountParams = {
index: 'example',
};
const mockError = new Error('Count error');
esClient.count.mockRejectedValueOnce(mockError);

await expect(uptimeEsClient.count(mockCountParams)).rejects.toThrow(mockError);
expect(esClient.count).toHaveBeenCalledWith(mockCountParams, { meta: true });
});
});

describe('getInspectEnabled', () => {
it('should return false if uiSettings is not available', async () => {
const result = await uptimeEsClient.getInspectEnabled();

expect(result).toBe(false);
});

it('should return the value from uiSettings if available', async () => {
const mockUiSettings = uiSettingsServiceMock.createClient();
uptimeEsClient.uiSettings = {
client: mockUiSettings,
} as any;

// @ts-expect-error
mockUiSettings.get.mockReturnValue(true);

await uptimeEsClient.getInspectEnabled();

expect(uptimeEsClient.isInspectorEnabled).toBe(true);
expect(mockUiSettings.get).toHaveBeenCalledWith('observability:enableInspectEsQueries');
});
});
describe('heartbeatIndices', () => {
it('appends synthetics-* in index for legacy alerts', async () => {
savedObjectsAdapter.getUptimeDynamicSettings = jest.fn().mockResolvedValue({
heartbeatIndices: 'heartbeat-8*,heartbeat-7*',
syntheticsIndexRemoved: true,
});
uptimeEsClient = new UptimeEsClient(savedObjectsClient, esClient, { isLegacyAlert: true });

const mockSearchParams = {
body: {
query: {
match_all: {},
},
},
};

await uptimeEsClient.search({
body: {
query: {
match_all: {},
},
},
});

expect(esClient.search).toHaveBeenCalledWith(
{
index: 'heartbeat-8*,heartbeat-7*,synthetics-*',
...mockSearchParams,
},
{ meta: true }
);
});
});

// Add more tests for other methods and edge cases
});
33 changes: 22 additions & 11 deletions x-pack/plugins/synthetics/server/legacy_uptime/lib/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,8 @@ import { enableInspectEsQueries } from '@kbn/observability-plugin/common';
import { getInspectResponse } from '@kbn/observability-shared-plugin/common';
import { API_URLS } from '../../../common/constants';
import { UptimeServerSetup } from './adapters';
import { UMLicenseCheck } from './domains';
import { UptimeRequests } from './requests';
import { savedObjectsAdapter } from './saved_objects/saved_objects';

export interface UMDomainLibs {
requests: UptimeRequests;
license: UMLicenseCheck;
}

export type { UMServerLibs } from '../uptime_server';

export interface CountResponse {
Expand All @@ -55,6 +48,7 @@ export class UptimeEsClient {
inspectableEsQueries: InspectResponse = [];
uiSettings?: CoreRequestHandlerContext['uiSettings'];
savedObjectsClient: SavedObjectsClientContract;
isLegacyAlert?: boolean;

constructor(
savedObjectsClient: SavedObjectsClientContract,
Expand All @@ -64,9 +58,17 @@ export class UptimeEsClient {
uiSettings?: CoreRequestHandlerContext['uiSettings'];
request?: KibanaRequest;
heartbeatIndices?: string;
isLegacyAlert?: boolean;
}
) {
const { isDev = false, uiSettings, request, heartbeatIndices = '' } = options ?? {};
const {
isLegacyAlert,
isDev = false,
uiSettings,
request,
heartbeatIndices = '',
} = options ?? {};
this.isLegacyAlert = isLegacyAlert;
this.uiSettings = uiSettings;
this.baseESClient = esClient;
this.savedObjectsClient = savedObjectsClient;
Expand Down Expand Up @@ -197,11 +199,20 @@ export class UptimeEsClient {
}

async getIndices() {
// if isLegacyAlert appends synthetics-* if it's not already there
let indices = '';
let syntheticsIndexRemoved = false;
if (this.heartbeatIndices) {
return this.heartbeatIndices;
indices = this.heartbeatIndices;
} else {
const settings = await savedObjectsAdapter.getUptimeDynamicSettings(this.savedObjectsClient);
indices = settings?.heartbeatIndices || '';
syntheticsIndexRemoved = settings.syntheticsIndexRemoved ?? false;
}
if (this.isLegacyAlert && !indices.includes('synthetics-') && syntheticsIndexRemoved) {
indices = indices + ',synthetics-*';
}
const settings = await savedObjectsAdapter.getUptimeDynamicSettings(this.savedObjectsClient);
return settings?.heartbeatIndices || '';
return indices;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ describe('remove890Indices migration', () => {
attributes: {
...doc.attributes,
heartbeatIndices: 'heartbeat-8*,something_else',
syntheticsIndexRemoved: true,
},
});
});
Expand All @@ -129,6 +130,7 @@ describe('remove890Indices migration', () => {
attributes: {
...doc.attributes,
heartbeatIndices: 'something_else,heartbeat-8*',
syntheticsIndexRemoved: true,
},
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,14 @@ export const remove890Indices: SavedObjectMigrationFn<
indicesArr.push('heartbeat-8*');
}

const syntheticsIndexRemoved = indexToRemove > -1;

return {
...doc,
attributes: {
...doc.attributes,
heartbeatIndices: indicesArr.join(','),
...(syntheticsIndexRemoved && { syntheticsIndexRemoved }),
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { SavedObjectsType } from '@kbn/core/server';
import { i18n } from '@kbn/i18n';
import { add820Indices, remove890Indices } from './migrations';
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/synthetics/server/runtime_types/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const DynamicSettingsAttributesCodec = t.intersection([
}),
t.partial({
defaultEmail: DefaultEmailCodec,
syntheticsIndexRemoved: t.boolean,
}),
]);

Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/translations/translations/fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -36846,7 +36846,6 @@
"xpack.synthetics.totalDuration.metrics": "Durée de l’étape",
"xpack.synthetics.totalDuration.transferSize": "Taille du transfert",
"xpack.synthetics.uptimeFeatureCatalogueTitle": "Uptime",
"xpack.synthetics.uptimeSettings.index": "Paramètres Uptime - Index",
"xpack.synthetics.wait": "Attendre",
"xpack.synthetics.waterfall.applyFilters.label": "Sélectionner un élément auquel appliquer le filtre",
"xpack.synthetics.waterfall.applyFilters.message": "Cliquer pour ajouter ou retirer le filtre",
Expand Down

0 comments on commit 4699ce8

Please sign in to comment.