[Discover][APM] Add icon to transaction name badge in summary column (#213428)

## Summary

Closes https://github.com/elastic/kibana/issues/211928

As part of the Traces in Discover initiative, we’ve added
`transaction.name` and `span.name` badges to the summary column. Some
documents can contain both, making it unclear which one represents the
transaction or the span name, and that's hot helpful for the filtering
experience the badges provide.

This PR addresses that by adding an icon as a prefix to the transaction
name, similar to the one used in the APM trace waterfall.


|Before|After|
|-|-|
|![Screenshot 2025-03-06 at 17 07
50](https://github.com/user-attachments/assets/2cd57f57-d430-418e-a727-7345fd65befc)|![Screenshot
2025-03-06 at 17 07
58](https://github.com/user-attachments/assets/6f618b3a-fcb8-4957-b3ab-93bd937761f7)|

We have two types of icons, the `merge` one by default or the `globe`
for rum agents.

![Screenshot 2025-03-06 at 16 04
45](https://github.com/user-attachments/assets/071050f3-2d86-4b96-b597-01338e5443af)

 ### Boy scouting

While playing around with the cell renderers, I realized that for long
values, the content was floating outside of the popover container.

![Screenshot 2025-03-06 at 14 05
03](https://github.com/user-attachments/assets/302dc6a9-9885-431e-a8f1-04d063ccb061)
So I've decided to add the same behaviour we have for the actions
popover in the flyout.
|Table|Flyout|
|-|-|
|![Screenshot 2025-03-06 at 16 41
04](https://github.com/user-attachments/assets/4a287c6e-6375-4afd-9b51-0e63bff12b27)|![Screenshot
2025-03-06 at 16 16
30](https://github.com/user-attachments/assets/c73d0dd7-a4ac-4d4c-8634-a2bfad771c0e)|

### How to test

Add this to your kibana.dev.yml:

```
discover.experimental.enabledProfiles:
  - traces-data-source-profile
`````

- Go to Discover page
- Select APM data view
- Check your traces data
This commit is contained in:
Irene Blanco 2025-03-07 11:15:15 +01:00 committed by GitHub
parent 4f2edcef97
commit e62cb6a37a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 88 additions and 0 deletions

View file

@ -96,6 +96,7 @@ export function CellActionsPopover({
<EuiFlexItem style={{ maxWidth: '200px' }}>
<EuiText
size="s"
className="eui-textBreakWord"
css={css`
font-family: ${euiTheme.font.familyCode};
`}

View file

@ -0,0 +1,55 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { render } from '@testing-library/react';
import { AgentName } from '@kbn/elastic-agent-utils';
import { TransactionNameIcon } from './transaction_name_icon';
jest.mock('@elastic/eui', () => ({
...jest.requireActual('@elastic/eui'),
useEuiTheme: jest.fn(() => ({
euiTheme: {
size: {
xs: '',
},
},
})),
}));
describe('TransactionNameIcon', () => {
const dataTestSub = 'discoverContextualComponentsSummaryColumnTransactionNameIcon';
it('should render the "globe" icon when agentName is a RUM agent', () => {
const { getByTestId } = render(TransactionNameIcon('rum-js'));
const icon = getByTestId(dataTestSub);
expect(icon).toHaveAttribute('data-euiicon-type', 'globe');
});
it('should render the "merge" icon when agentName is not a RUM agent', () => {
const { getByTestId } = render(TransactionNameIcon('go'));
const icon = getByTestId(dataTestSub);
expect(icon).toHaveAttribute('data-euiicon-type', 'merge');
});
it('should render the "merge" icon when agentName is undefined', () => {
const { getByTestId } = render(TransactionNameIcon(undefined as unknown as AgentName));
const icon = getByTestId(dataTestSub);
expect(icon).toHaveAttribute('data-euiicon-type', 'merge');
});
it('should render the "merge" icon when agentName is null', () => {
const { getByTestId } = render(TransactionNameIcon(null as unknown as AgentName));
const icon = getByTestId(dataTestSub);
expect(icon).toHaveAttribute('data-euiicon-type', 'merge');
});
});

View file

@ -0,0 +1,28 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React from 'react';
import { useEuiTheme, IconType, EuiIcon } from '@elastic/eui';
import { AgentName, isRumAgentName } from '@kbn/elastic-agent-utils';
import { css } from '@emotion/react';
export const TransactionNameIcon = (agentName: AgentName) => {
const { euiTheme } = useEuiTheme();
const icon: IconType = isRumAgentName(agentName) ? 'globe' : 'merge';
return (
<EuiIcon
data-test-subj="discoverContextualComponentsSummaryColumnTransactionNameIcon"
type={icon}
size="s"
css={css`
margin-right: ${euiTheme.size.xs};
`}
/>
);
};

View file

@ -24,6 +24,7 @@ import {
DataTableRecord,
getFieldValue,
INDEX_FIELD,
TRANSACTION_NAME_FIELD,
} from '@kbn/discover-utils';
import { TraceDocument, formatFieldValue } from '@kbn/discover-utils/src';
import { EuiIcon, useEuiTheme } from '@elastic/eui';
@ -32,6 +33,7 @@ import { testPatternAgainstAllowedList } from '@kbn/data-view-utils';
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
import { FieldBadgeWithActions, FieldBadgeWithActionsProps } from '../cell_actions_popover';
import { ServiceNameBadgeWithActions } from '../service_name_badge_with_actions';
import { TransactionNameIcon } from './icons/transaction_name_icon';
type FieldKey = keyof DataTableRecord['flattened'];
type FieldValue = NonNullable<DataTableRecord['flattened'][FieldKey]>;
@ -121,6 +123,8 @@ const getResourceBadgeIcon = (
case TRANSACTION_DURATION_FIELD:
case SPAN_DURATION_FIELD:
return DurationIcon;
case TRANSACTION_NAME_FIELD:
return () => TransactionNameIcon(fields[AGENT_NAME_FIELD] as AgentName);
}
};