Skip to content

Commit

Permalink
[Infra] Fix call to service api (elastic#203451)
Browse files Browse the repository at this point in the history
fixes [203389](elastic#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
  • Loading branch information
crespocarlos authored Dec 10, 2024
1 parent 13c5722 commit 1a20fda
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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]);
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
});
});
Original file line number Diff line number Diff line change
@@ -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;
};
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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();
Expand All @@ -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 },
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit 1a20fda

Please sign in to comment.