[Obs Alerting] View in apm button - add defensive code (#184236)

## Summary

Resolves https://github.com/elastic/kibana/issues/184204

The page can break when the share plugin is undefined. This PR adds
defensive code to prevent errors when `share` is undefined.


![image](538a73e1-e8b5-4743-8a01-f723695dcf86)


![image](4a3a606e-4aa0-4aed-a644-83cdf3965dbd)


### Testing
Generate some mock APM data with ```node scripts/synthtrace.js
simple_trace --live```
Create an APM latency rule
Wait for the rule to be triggered, then navigate to the alert details
page
The alert details page should load properly
This commit is contained in:
Dominique Clarke 2024-05-26 09:36:57 -04:00 committed by GitHub
parent 61a28e76d2
commit 107075c94f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 56 additions and 12 deletions

View file

@ -76,7 +76,6 @@ export class Instance extends Entity<ApmFields> {
return new ApmError({
...this.fields,
'error.exception': [{ message, ...(type ? { type } : {}) }],
'error.grouping_name': getErrorGroupingKey(message),
'error.culprit': culprit,
});
}

View file

@ -60,11 +60,6 @@ describe('transactions with errors', () => {
.errors(instance.error({ message: 'test error' }).timestamp(timestamp))
.serialize();
expect(error['error.grouping_name']).toEqual(
'4274b1899eba687801198c89f64a3fdade080a475c8a54881ba8fa10e7f45691'
);
expect(error['error.grouping_key']).toMatchInlineSnapshot(
`"4274b1899eba687801198c89f64a3fdade080a475c8a54881ba8fa10e7f45691"`
);
expect(error['error.grouping_key']).toMatchInlineSnapshot(`"0000000000000000000000test error"`);
});
});

View file

@ -6,6 +6,8 @@
*/
import { getErrorGroupingKey } from '@kbn/apm-synthtrace-client/src/lib/apm/instance';
import { generateLongId } from '@kbn/apm-synthtrace-client/src/lib/utils/generate_id';
import url from 'url';
import { synthtrace } from '../../../synthtrace';
import { checkA11y } from '../../support/commands';
@ -69,7 +71,7 @@ describe('Error details', () => {
});
describe('when error has data', () => {
const errorGroupingKey = getErrorGroupingKey('Error 1');
const errorGroupingKey = generateLongId('Error 1');
const errorGroupingKeyShort = errorGroupingKey.slice(0, 5);
const errorDetailsPageHref = url.format({
pathname: `/app/apm/services/opbeans-java/errors/${errorGroupingKey}`,

View file

@ -0,0 +1,49 @@
/*
* 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 React from 'react';
import { render } from '@testing-library/react';
import { ViewInAPMButton } from './view_in_apm_button';
import * as apmContext from '../../../../context/apm_plugin/use_apm_plugin_context';
describe('ViewInApmButton', () => {
const config = {
serviceName: 'testService',
environment: 'testEnvironment',
transactionName: 'testTransaction',
transactionType: 'testTransactionType',
from: 'now-15m',
to: 'now',
};
beforeEach(() => {
jest.clearAllMocks();
});
it('hides button when share plugin is not available', () => {
const { queryByText } = render(<ViewInAPMButton {...config} />);
expect(queryByText('View in APM')).not.toBeInTheDocument();
});
it('reners correctly', () => {
jest.spyOn(apmContext, 'useApmPluginContext').mockReturnValue({
share: {
url: {
locators: {
// @ts-ignore
get: () => ({
navigate: jest.fn(),
}),
},
},
},
});
const { getByText } = render(<ViewInAPMButton {...config} />);
expect(getByText('View in APM')).toBeInTheDocument();
});
});

View file

@ -4,7 +4,6 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
/* Error Rate */
import React from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
@ -29,8 +28,8 @@ export function ViewInAPMButton({
to: string;
kuery?: string;
}) {
const { share } = useApmPluginContext();
const serviceNavigator = share.url.locators.get(APM_APP_LOCATOR_ID);
const { share } = useApmPluginContext() || {};
const serviceNavigator = share?.url?.locators?.get(APM_APP_LOCATOR_ID);
if (!serviceNavigator) {
return null;

View file

@ -74,7 +74,7 @@ export async function getIndicesLifecycleStatus({
filter_path: 'indices.*.phase',
});
return indices;
return indices || {};
}
export async function getIndicesInfo({