[APM] "View job" link from latency charts leads to a malfunctioning page (#86788)
* fixing ML links * fixing ML links
This commit is contained in:
parent
0d3daa564f
commit
cfec38eea6
|
@ -4,26 +4,26 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
EuiPanel,
|
||||
EuiTitle,
|
||||
EuiText,
|
||||
EuiSpacer,
|
||||
EuiButton,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiPanel,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { FETCH_STATUS } from '../../../../hooks/use_fetcher';
|
||||
import { ITableColumn, ManagedTable } from '../../../shared/ManagedTable';
|
||||
import { LoadingStatePrompt } from '../../../shared/LoadingStatePrompt';
|
||||
import { MLSingleMetricLink } from '../../../shared/Links/MachineLearningLinks/MLSingleMetricLink';
|
||||
import { MLManageJobsLink } from '../../../shared/Links/MachineLearningLinks/MLManageJobsLink';
|
||||
import React from 'react';
|
||||
import { getEnvironmentLabel } from '../../../../../common/environment_filter_values';
|
||||
import { LegacyJobsCallout } from './legacy_jobs_callout';
|
||||
import { FETCH_STATUS } from '../../../../hooks/use_fetcher';
|
||||
import { MLExplorerLink } from '../../../shared/Links/MachineLearningLinks/MLExplorerLink';
|
||||
import { MLManageJobsLink } from '../../../shared/Links/MachineLearningLinks/MLManageJobsLink';
|
||||
import { LoadingStatePrompt } from '../../../shared/LoadingStatePrompt';
|
||||
import { ITableColumn, ManagedTable } from '../../../shared/ManagedTable';
|
||||
import { AnomalyDetectionApiResponse } from './index';
|
||||
import { LegacyJobsCallout } from './legacy_jobs_callout';
|
||||
|
||||
type Jobs = AnomalyDetectionApiResponse['jobs'];
|
||||
|
||||
|
@ -44,14 +44,14 @@ const columns: Array<ITableColumn<Jobs[0]>> = [
|
|||
{ defaultMessage: 'Action' }
|
||||
),
|
||||
render: (jobId: string) => (
|
||||
<MLSingleMetricLink jobId={jobId}>
|
||||
<MLExplorerLink jobId={jobId}>
|
||||
{i18n.translate(
|
||||
'xpack.apm.settings.anomalyDetection.jobList.mlJobLinkText',
|
||||
{
|
||||
defaultMessage: 'View job in ML',
|
||||
}
|
||||
)}
|
||||
</MLSingleMetricLink>
|
||||
</MLExplorerLink>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Location } from 'history';
|
||||
import React from 'react';
|
||||
import { getRenderedHref } from '../../../../utils/testHelpers';
|
||||
import { MLExplorerLink } from './MLExplorerLink';
|
||||
|
||||
describe('MLExplorerLink', () => {
|
||||
it('should produce the correct URL with jobId', async () => {
|
||||
const href = await getRenderedHref(
|
||||
() => (
|
||||
<MLExplorerLink jobId="myservicename-mytransactiontype-high_mean_response_time" />
|
||||
),
|
||||
{
|
||||
search:
|
||||
'?rangeFrom=now/w&rangeTo=now-4h&refreshPaused=true&refreshInterval=0',
|
||||
} as Location
|
||||
);
|
||||
|
||||
expect(href).toMatchInlineSnapshot(
|
||||
`"/app/ml/explorer?_g=(ml:(jobIds:!(myservicename-mytransactiontype-high_mean_response_time)),refreshInterval:(pause:!t,value:0),time:(from:now%2Fw,to:now-4h))&_a=(explorer:(mlExplorerFilter:(),mlExplorerSwimlane:()))"`
|
||||
);
|
||||
});
|
||||
|
||||
it('correctly encodes time range values', async () => {
|
||||
const href = await getRenderedHref(
|
||||
() => (
|
||||
<MLExplorerLink jobId="apm-production-485b-high_mean_transaction_duration" />
|
||||
),
|
||||
{
|
||||
search:
|
||||
'?rangeFrom=2020-07-29T17:27:29.000Z&rangeTo=2020-07-29T18:45:00.000Z&refreshInterval=10000&refreshPaused=true',
|
||||
} as Location
|
||||
);
|
||||
|
||||
expect(href).toMatchInlineSnapshot(
|
||||
`"/app/ml/explorer?_g=(ml:(jobIds:!(apm-production-485b-high_mean_transaction_duration)),refreshInterval:(pause:!t,value:10000),time:(from:'2020-07-29T17:27:29.000Z',to:'2020-07-29T18:45:00.000Z'))&_a=(explorer:(mlExplorerFilter:(),mlExplorerSwimlane:()))"`
|
||||
);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { ReactNode } from 'react';
|
||||
import { EuiLink } from '@elastic/eui';
|
||||
import { UI_SETTINGS } from '../../../../../../../../src/plugins/data/common';
|
||||
import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context';
|
||||
import { useMlHref, ML_PAGES } from '../../../../../../ml/public';
|
||||
import { useUrlParams } from '../../../../context/url_params_context/use_url_params';
|
||||
import { TimePickerRefreshInterval } from '../../DatePicker/typings';
|
||||
|
||||
interface Props {
|
||||
children?: ReactNode;
|
||||
jobId: string;
|
||||
external?: boolean;
|
||||
}
|
||||
|
||||
export function MLExplorerLink({ jobId, external, children }: Props) {
|
||||
const href = useExplorerHref({ jobId });
|
||||
|
||||
return (
|
||||
<EuiLink
|
||||
children={children}
|
||||
href={href}
|
||||
external={external}
|
||||
target={external ? '_blank' : undefined}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function useExplorerHref({ jobId }: { jobId: string }) {
|
||||
const {
|
||||
core,
|
||||
plugins: { ml },
|
||||
} = useApmPluginContext();
|
||||
const { urlParams } = useUrlParams();
|
||||
|
||||
const timePickerRefreshIntervalDefaults = core.uiSettings.get<TimePickerRefreshInterval>(
|
||||
UI_SETTINGS.TIMEPICKER_REFRESH_INTERVAL_DEFAULTS
|
||||
);
|
||||
|
||||
const {
|
||||
// hardcoding a custom default of 1 hour since the default kibana timerange of 15 minutes is shorter than the ML interval
|
||||
rangeFrom = 'now-1h',
|
||||
rangeTo = 'now',
|
||||
refreshInterval = timePickerRefreshIntervalDefaults.value,
|
||||
refreshPaused = timePickerRefreshIntervalDefaults.pause,
|
||||
} = urlParams;
|
||||
|
||||
const href = useMlHref(ml, core.http.basePath.get(), {
|
||||
page: ML_PAGES.ANOMALY_EXPLORER,
|
||||
pageState: {
|
||||
jobIds: [jobId],
|
||||
timeRange: { from: rangeFrom, to: rangeTo },
|
||||
refreshInterval: { pause: refreshPaused, value: refreshInterval },
|
||||
},
|
||||
});
|
||||
|
||||
return href;
|
||||
}
|
|
@ -10,6 +10,7 @@ import { isEmpty } from 'lodash';
|
|||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import styled from 'styled-components';
|
||||
import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context';
|
||||
import { useUrlParams } from '../../../../context/url_params_context/use_url_params';
|
||||
import { MLSingleMetricLink } from '../../Links/MachineLearningLinks/MLSingleMetricLink';
|
||||
|
||||
|
@ -33,12 +34,13 @@ const ShiftedEuiText = styled(EuiText)`
|
|||
export function MLHeader({ hasValidMlLicense, mlJobId }: Props) {
|
||||
const { serviceName } = useParams<{ serviceName?: string }>();
|
||||
const { urlParams } = useUrlParams();
|
||||
const { transactionType } = useApmServiceContext();
|
||||
|
||||
if (!hasValidMlLicense || !mlJobId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { kuery, transactionType } = urlParams;
|
||||
const { kuery } = urlParams;
|
||||
|
||||
const hasKuery = !isEmpty(kuery);
|
||||
const icon = hasKuery ? (
|
||||
|
|
Loading…
Reference in a new issue