[Infra] Fix call to service api (#203451)

fixes [203389](https://github.com/elastic/kibana/issues/203389)
## Summary

Fix the call to `/api/infra/services` when using a relative date range


![service_api_relative_date_range](https://github.com/user-attachments/assets/772bba2c-07c8-4031-8d8a-61bdc7ab6d70)


### How to test
- Navigate to host detail view, and change the data picker to use
relative dates
- Click on Submit
This commit is contained in:
Carlos Crespo 2024-12-10 14:33:32 +01:00 committed by GitHub
parent 13c5722dae
commit 1a20fda702
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 114 additions and 24 deletions

View file

@ -11,6 +11,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
import type { TimeRange } from '@kbn/es-query';
import { useLinkProps } from '@kbn/observability-shared-plugin/public';
import { decodeOrThrow } from '@kbn/io-ts-utils';
import { useTimeRange } from '../../../../hooks/use_time_range';
import { ServicesAPIResponseRT } from '../../../../../common/http_api';
import { isPending, useFetcher } from '../../../../hooks/use_fetcher';
import { Section } from '../../components/section';
@ -44,13 +45,18 @@ export const ServicesContent = ({
app: 'apm',
pathname: '/onboarding',
});
const parsedDateRange = useTimeRange({
rangeFrom: dateRange.from,
rangeTo: dateRange.to,
});
const params = useMemo(
() => ({
filters: { [HOST_NAME_FIELD]: hostName },
from: dateRange.from,
to: dateRange.to,
...parsedDateRange,
}),
[hostName, dateRange.from, dateRange.to]
[hostName, parsedDateRange]
);
const query = useMemo(() => ({ ...params, filters: JSON.stringify(params.filters) }), [params]);

View file

@ -0,0 +1,59 @@
/*
* 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 { renderHook } from '@testing-library/react-hooks';
import { useTimeRange } from './use_time_range';
import * as datemath from '../utils/datemath';
jest.mock('../utils/datemath');
describe('useTimeRange', () => {
const mockParseDateRange = datemath.parseDateRange as jest.Mock;
beforeEach(() => {
Date.now = jest.fn(() => new Date(Date.UTC(2021, 0, 1, 12)).valueOf());
});
afterEach(() => {
jest.clearAllMocks();
});
it('returns default timestamps when rangeFrom and rangeTo are not provided', () => {
const { result } = renderHook(() => useTimeRange({}));
const now = Date.now();
const expectedFrom = new Date(now - 15 * 60000).toISOString();
const expectedTo = new Date(now).toISOString();
expect(result.current.from).toBe(expectedFrom);
expect(result.current.to).toBe(expectedTo);
});
it('returns parsed date range when rangeFrom and rangeTo are provided', () => {
const mockFrom = '2021-01-01T00:00:00.000Z';
const mockTo = '2021-01-01T01:00:00.000Z';
mockParseDateRange.mockReturnValue({ from: mockFrom, to: mockTo });
const { result } = renderHook(() => useTimeRange({ rangeFrom: 'now-15m', rangeTo: 'now' }));
expect(result.current.from).toBe(mockFrom);
expect(result.current.to).toBe(mockTo);
});
it('returns default timestamps when parseDateRange returns undefined values', () => {
mockParseDateRange.mockReturnValue({ from: undefined, to: undefined });
const { result } = renderHook(() => useTimeRange({ rangeFrom: 'now-15m', rangeTo: 'now' }));
const now = Date.now();
const expectedFrom = new Date(now - 15 * 60000).toISOString();
const expectedTo = new Date(now).toISOString();
expect(result.current.from).toBe(expectedFrom);
expect(result.current.to).toBe(expectedTo);
});
});

View file

@ -0,0 +1,39 @@
/*
* 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 { useMemo } from 'react';
import { parseDateRange } from '../utils/datemath';
const DEFAULT_FROM_IN_MILLISECONDS = 15 * 60000;
const getDefaultTimestamps = () => {
const now = Date.now();
return {
from: new Date(now - DEFAULT_FROM_IN_MILLISECONDS).toISOString(),
to: new Date(now).toISOString(),
};
};
export const useTimeRange = ({ rangeFrom, rangeTo }: { rangeFrom?: string; rangeTo?: string }) => {
const parsedDateRange = useMemo(() => {
const defaults = getDefaultTimestamps();
if (!rangeFrom || !rangeTo) {
return defaults;
}
const { from = defaults.from, to = defaults.to } = parseDateRange({
from: rangeFrom,
to: rangeTo,
});
return { from, to };
}, [rangeFrom, rangeTo]);
return parsedDateRange;
};

View file

@ -5,14 +5,14 @@
* 2.0.
*/
import createContainer from 'constate';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { buildEsQuery, Filter, fromKueryExpression, TimeRange, type Query } from '@kbn/es-query';
import { Subscription, map, tap } from 'rxjs';
import deepEqual from 'fast-deep-equal';
import useEffectOnce from 'react-use/lib/useEffectOnce';
import { useKibanaQuerySettings } from '@kbn/observability-shared-plugin/public';
import { useTimeRange } from '../../../../hooks/use_time_range';
import { useSearchSessionContext } from '../../../../hooks/use_search_session';
import { parseDateRange } from '../../../../utils/datemath';
import { useKibanaContextForPlugin } from '../../../../hooks/use_kibana';
import { telemetryTimeRangeFormatter } from '../../../../../common/formatters/telemetry_time_range';
import { useMetricsDataViewContext } from '../../../../containers/metrics_source';
@ -38,17 +38,6 @@ const buildQuerySubmittedPayload = (
};
};
const DEFAULT_FROM_IN_MILLISECONDS = 15 * 60000;
const getDefaultTimestamps = () => {
const now = Date.now();
return {
from: new Date(now - DEFAULT_FROM_IN_MILLISECONDS).toISOString(),
to: new Date(now).toISOString(),
};
};
export const useUnifiedSearch = () => {
const [error, setError] = useState<Error | null>(null);
const [searchCriteria, setSearch] = useHostsUrlState();
@ -57,6 +46,11 @@ export const useUnifiedSearch = () => {
const { services } = useKibanaContextForPlugin();
const kibanaQuerySettings = useKibanaQuerySettings();
const parsedDateRange = useTimeRange({
rangeFrom: searchCriteria.dateRange.from,
rangeTo: searchCriteria.dateRange.to,
});
const {
data: {
query: { filterManager: filterManagerService, queryString: queryStringService },
@ -120,14 +114,6 @@ export const useUnifiedSearch = () => {
[onDateRangeChange, updateSearchSessionId]
);
const parsedDateRange = useMemo(() => {
const defaults = getDefaultTimestamps();
const { from = defaults.from, to = defaults.to } = parseDateRange(searchCriteria.dateRange);
return { from, to };
}, [searchCriteria.dateRange]);
const getDateRangeAsTimestamp = useCallback(() => {
const from = new Date(parsedDateRange.from).getTime();
const to = new Date(parsedDateRange.to).getTime();