[Synthetics] Update pings query to not use last 30 days time range !! (#208366)

## Summary

Fixes https://github.com/elastic/kibana/issues/198443 !!

Instead of using last 30 days, it will now uses last 24 hours otherwise
it will fall back to last 7 days and then last 30 days.

Last run should still work as expected 

<img width="1728" alt="image"
src="https://github.com/user-attachments/assets/abad5d83-5456-440e-b5b5-147915315120"
/>

---------

Co-authored-by: Justin Kambic <jk@elastic.co>
This commit is contained in:
Shahzad 2025-01-30 16:01:27 +01:00 committed by GitHub
parent cd9096cf73
commit 97e8bada1d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 130 additions and 32 deletions

View file

@ -11,6 +11,7 @@ export enum SYNTHETICS_API_URLS {
GET_SYNTHETICS_MONITOR = '/api/synthetics/monitors/{monitorId}',
PRIVATE_LOCATIONS = `/api/synthetics/private_locations`,
PARAMS = `/api/synthetics/params`,
LATEST_TEST_RUN = '/api/synthetics/latest_test_run',
// Service end points
INDEX_TEMPLATES = '/internal/synthetics/service/index_templates',

View file

@ -40,15 +40,11 @@ export const useMonitorLatestPing = (params?: UseMonitorLatestPingParams) => {
useEffect(() => {
if (monitorId && locationLabel) {
dispatch(getMonitorLastRunAction.get({ monitorId, locationId: locationLabel }));
dispatch(getMonitorLastRunAction.get({ monitorId, locationLabel }));
}
}, [dispatch, monitorId, locationLabel, isUpToDate, lastRefresh]);
if (!monitorId || !locationLabel) {
return { loading, latestPing: undefined, loaded };
}
if (!latestPing) {
if (!monitorId || !locationLabel || !latestPing) {
return { loading, latestPing: undefined, loaded };
}

View file

@ -20,8 +20,8 @@ export const getMonitorAction = createAsyncAction<
>('[MONITOR DETAILS] GET MONITOR');
export const getMonitorLastRunAction = createAsyncAction<
{ monitorId: string; locationId: string },
PingsResponse
{ monitorId: string; locationLabel: string },
{ ping?: Ping }
>('[MONITOR DETAILS] GET LAST RUN');
export const resetMonitorLastRunAction = createAction('[MONITOR DETAILS] LAST RUN RESET');

View file

@ -9,22 +9,13 @@ import moment from 'moment';
import { apiService } from '../../../../utils/api_service';
import {
EncryptedSyntheticsMonitorCodec,
Ping,
PingsResponse,
PingsResponseType,
SyntheticsMonitorWithId,
} from '../../../../../common/runtime_types';
import { INITIAL_REST_VERSION, SYNTHETICS_API_URLS } from '../../../../../common/constants';
export const fetchMonitorLastRun = async ({
monitorId,
locationId,
}: {
monitorId: string;
locationId: string;
}): Promise<PingsResponse> => {
return fetchMonitorRecentPings({ monitorId, locationId, size: 1 });
};
export interface MostRecentPingsRequest {
monitorId: string;
locationId: string;
@ -63,6 +54,20 @@ export const fetchMonitorRecentPings = async ({
);
};
export const fetchLatestTestRun = async ({
monitorId,
locationLabel,
}: {
monitorId: string;
locationLabel?: string;
}): Promise<{ ping?: Ping }> => {
return apiService.get<{ ping?: Ping }>(SYNTHETICS_API_URLS.LATEST_TEST_RUN, {
monitorId,
locationLabel,
version: INITIAL_REST_VERSION,
});
};
export const fetchSyntheticsMonitor = async ({
monitorId,
spaceId,

View file

@ -16,7 +16,7 @@ import {
getMonitorAction,
updateMonitorLastRunAction,
} from './actions';
import { fetchSyntheticsMonitor, fetchMonitorRecentPings, fetchMonitorLastRun } from './api';
import { fetchSyntheticsMonitor, fetchMonitorRecentPings, fetchLatestTestRun } from './api';
import { selectLastRunMetadata } from './selectors';
export function* fetchSyntheticsMonitorEffect() {
@ -32,7 +32,7 @@ export function* fetchSyntheticsMonitorEffect() {
yield takeLeading(
getMonitorLastRunAction.get,
fetchEffectFactory(
fetchMonitorLastRun,
fetchLatestTestRun,
getMonitorLastRunAction.success,
getMonitorLastRunAction.fail
)

View file

@ -67,7 +67,7 @@ export const monitorDetailsReducer = createReducer(initialState, (builder) => {
.addCase(getMonitorLastRunAction.success, (state, action) => {
state.lastRun.loading = false;
state.lastRun.loaded = true;
state.lastRun.data = action.payload.pings[0];
state.lastRun.data = action.payload?.ping;
})
.addCase(getMonitorLastRunAction.fail, (state, action) => {
state.lastRun.loading = false;

View file

@ -0,0 +1,43 @@
/*
* 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 { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { Ping } from '../../common/runtime_types';
import { SyntheticsEsClient } from '../lib';
import { getRangeFilter, SUMMARY_FILTER } from '../../common/constants/client_defaults';
export async function getLatestTestRun<F>({
syntheticsEsClient,
monitorId,
locationLabel,
from = 'now-1d',
to = 'now',
}: {
syntheticsEsClient: SyntheticsEsClient;
monitorId: string;
locationLabel?: string;
from?: string;
to?: string;
}): Promise<Ping | undefined> {
const response = await syntheticsEsClient.search({
body: {
query: {
bool: {
filter: [
SUMMARY_FILTER,
getRangeFilter({ from, to }),
{ term: { 'monitor.id': monitorId } },
...(locationLabel ? [{ term: { 'observer.geo.name': locationLabel } }] : []),
] as QueryDslQueryContainer[],
},
},
sort: [{ '@timestamp': { order: 'desc' } }],
},
});
return response.body.hits.hits[0]?._source as Ping | undefined;
}

View file

@ -6,9 +6,9 @@
*/
import { queryPings } from './query_pings';
import { SyntheticsEsClient } from '../../lib';
import { SyntheticsEsClient } from '../lib';
jest.mock('../../lib'); // Mock the ES client module
jest.mock('../lib'); // Mock the ES client module
const mockEsClient: Partial<SyntheticsEsClient> = {
search: jest.fn(),

View file

@ -10,14 +10,9 @@ import {
QueryDslFieldAndFormat,
QueryDslQueryContainer,
} from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { SUMMARY_FILTER } from '../../../common/constants/client_defaults';
import { SyntheticsEsClient } from '../../lib';
import {
GetPingsParams,
HttpResponseBody,
PingsResponse,
Ping,
} from '../../../common/runtime_types';
import { GetPingsParams, HttpResponseBody, Ping, PingsResponse } from '../../common/runtime_types';
import { SyntheticsEsClient } from '../lib';
import { SUMMARY_FILTER } from '../../common/constants/client_defaults';
const DEFAULT_PAGE_SIZE = 25;

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import { syntheticsGetLatestTestRunRoute } from './pings/get_latest_test_run';
import { deleteSyntheticsParamsBulkRoute } from './settings/params/delete_params_bulk';
import { deleteSyntheticsMonitorBulkRoute } from './monitor_cruds/bulk_cruds/delete_monitor_bulk';
import {
@ -117,4 +118,5 @@ export const syntheticsAppPublicRestApiRoutes: SyntheticsRestApiRouteFactory[] =
deleteSyntheticsMonitorRoute,
deleteSyntheticsMonitorBulkRoute,
deleteSyntheticsParamsBulkRoute,
syntheticsGetLatestTestRunRoute,
];

View file

@ -0,0 +1,56 @@
/*
* 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 { schema, TypeOf } from '@kbn/config-schema';
import { Ping } from '../../../common/runtime_types';
import { getLatestTestRun } from '../../queries/get_latest_test_run';
import { SyntheticsRestApiRouteFactory } from '../types';
import { SYNTHETICS_API_URLS } from '../../../common/constants';
export const getLatestTestRunRouteQuerySchema = schema.object({
from: schema.maybe(schema.string()),
to: schema.maybe(schema.string()),
locationLabel: schema.maybe(schema.string()),
monitorId: schema.string(),
});
type GetPingsRouteRequest = TypeOf<typeof getLatestTestRunRouteQuerySchema>;
export const syntheticsGetLatestTestRunRoute: SyntheticsRestApiRouteFactory = () => ({
method: 'GET',
path: SYNTHETICS_API_URLS.LATEST_TEST_RUN,
validate: {},
validation: {
request: {
query: getLatestTestRunRouteQuerySchema,
},
},
handler: async ({ syntheticsEsClient, request, response }): Promise<{ ping?: Ping }> => {
const { from, to, monitorId, locationLabel } = request.query as GetPingsRouteRequest;
const getPing = (fromVal: string) => {
return getLatestTestRun({
syntheticsEsClient,
from: fromVal,
to: to || 'now',
monitorId,
locationLabel,
});
};
// we will try to get the latest ping from the last day,
// if it doesn't exist we will try to get the latest ping from the last week
const ping = await getPing(from || 'now-1d');
// if from is provided, we will only try to get the latest ping from the provided time range
if (ping && from) {
return { ping };
}
// fall back to 1w and then max 30 days
return { ping: (await getPing('now-1w')) || (await getPing('now-30d')) };
},
});

View file

@ -6,9 +6,9 @@
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { queryPings } from '../../queries/query_pings';
import { SyntheticsRestApiRouteFactory } from '../types';
import { SYNTHETICS_API_URLS } from '../../../common/constants';
import { queryPings } from '../../common/pings/query_pings';
export const getPingsRouteQuerySchema = schema.object({
from: schema.string(),