mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
# Backport This will backport the following commits from `main` to `8.x`: - [[APM][OTel] EDOT error summary fix (#217885)](https://github.com/elastic/kibana/pull/217885) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"jennypavlova","email":"dzheni.pavlova@elastic.co"},"sourceCommit":{"committedDate":"2025-04-15T19:44:11Z","message":"[APM][OTel] EDOT error summary fix (#217885)\n\n## Summary\n\nThis PR fixes the issue with the error summary missing items using edot.\nIt includes e2e tests with synthtrace for both edot and otel services.\n\nTODO \n\n- [x] Test with serverless (waiting for the PR to be deployed)\nTested on serverless works as expected: \n\n<img width=\"2560\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/8dd7962e-7d66-482d-97fb-0b08882bd04f\"\n/>","sha":"7c9a3ee1f2a7f4599cd294ef2890e7c1b9cefd27","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:fix","v9.0.0","ci:cloud-redeploy","ci:build-serverless-image","ci:project-deploy-observability","Team:obs-ux-infra_services","backport:version","v9.1.0","v8.19.0"],"title":"[APM][OTel] EDOT error summary fix","number":217885,"url":"https://github.com/elastic/kibana/pull/217885","mergeCommit":{"message":"[APM][OTel] EDOT error summary fix (#217885)\n\n## Summary\n\nThis PR fixes the issue with the error summary missing items using edot.\nIt includes e2e tests with synthtrace for both edot and otel services.\n\nTODO \n\n- [x] Test with serverless (waiting for the PR to be deployed)\nTested on serverless works as expected: \n\n<img width=\"2560\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/8dd7962e-7d66-482d-97fb-0b08882bd04f\"\n/>","sha":"7c9a3ee1f2a7f4599cd294ef2890e7c1b9cefd27"}},"sourceBranch":"main","suggestedTargetBranches":["9.0","8.x"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/217885","number":217885,"mergeCommit":{"message":"[APM][OTel] EDOT error summary fix (#217885)\n\n## Summary\n\nThis PR fixes the issue with the error summary missing items using edot.\nIt includes e2e tests with synthtrace for both edot and otel services.\n\nTODO \n\n- [x] Test with serverless (waiting for the PR to be deployed)\nTested on serverless works as expected: \n\n<img width=\"2560\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/8dd7962e-7d66-482d-97fb-0b08882bd04f\"\n/>","sha":"7c9a3ee1f2a7f4599cd294ef2890e7c1b9cefd27"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT-->
This commit is contained in:
parent
c2fee12120
commit
44a13ffe63
5 changed files with 45 additions and 23 deletions
|
@ -7,5 +7,5 @@
|
|||
|
||||
export interface Server {
|
||||
address?: string;
|
||||
port?: string;
|
||||
port?: number;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ import { ErrorTabKey, getTabs } from './error_tabs';
|
|||
import { ErrorUiActionsContextMenu } from './error_ui_actions_context_menu';
|
||||
import { SampleSummary } from './sample_summary';
|
||||
import { ErrorSampleContextualInsight } from './error_sample_contextual_insight';
|
||||
import { buildUrl } from '../../../../utils/build_url';
|
||||
|
||||
const TransactionLinkName = euiStyled.div`
|
||||
margin-left: ${({ theme }) => theme.eui.euiSizeS};
|
||||
|
@ -154,11 +155,22 @@ export function ErrorSampleDetails({
|
|||
|
||||
const tabs = getTabs(error);
|
||||
const currentTab = getCurrentTab(tabs, detailTab) as ErrorTab;
|
||||
const urlFromError = error.error.page?.url || error.url?.full;
|
||||
const urlFromTransaction = transaction?.transaction?.page?.url || transaction?.url?.full;
|
||||
const errorOrTransactionUrl = error?.url ? error : transaction;
|
||||
const errorOrTransactionHttp = error?.http ? error : transaction;
|
||||
const errorOrTransactionUserAgent = error?.user_agent
|
||||
? error.user_agent
|
||||
: transaction?.user_agent;
|
||||
|
||||
const errorUrl = error.error.page?.url || error.url?.full;
|
||||
const method = error.http?.request?.method;
|
||||
const status = error.http?.response?.status_code;
|
||||
const userAgent = error?.user_agent;
|
||||
// To get the error data needed for the summary we use the transaction fallback in case
|
||||
// the error data is not available.
|
||||
// In case of OTel the error data is not available in the error response and we need to use
|
||||
// the associated root span data (which is called "transaction" here because of the APM data model).
|
||||
const errorUrl = urlFromError || urlFromTransaction || buildUrl(errorOrTransactionUrl);
|
||||
const method = errorOrTransactionHttp?.http?.request?.method;
|
||||
const status = errorOrTransactionHttp?.http?.response?.status_code;
|
||||
const userAgent = errorOrTransactionUserAgent;
|
||||
const environment = error.service.environment;
|
||||
const serviceVersion = error.service.version;
|
||||
const isUnhandled = error.error.exception?.[0]?.handled === false;
|
||||
|
@ -205,7 +217,7 @@ export function ErrorSampleDetails({
|
|||
<EuiFlexItem>
|
||||
<EuiIcon type="apmTrace" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={{ whiteSpace: 'nowrap' }}>
|
||||
<EuiFlexItem css={{ whiteSpace: 'nowrap' }}>
|
||||
{i18n.translate('xpack.apm.errorSampleDetails.viewOccurrencesInTraceExplorer', {
|
||||
defaultMessage: 'Explore traces with this error',
|
||||
})}
|
||||
|
@ -223,7 +235,7 @@ export function ErrorSampleDetails({
|
|||
<EuiFlexItem>
|
||||
<EuiIcon type="discoverApp" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={{ whiteSpace: 'nowrap' }}>
|
||||
<EuiFlexItem css={{ whiteSpace: 'nowrap' }}>
|
||||
{i18n.translate(
|
||||
'xpack.apm.errorSampleDetails.viewOccurrencesInDiscoverButtonLabel',
|
||||
{
|
||||
|
@ -247,7 +259,7 @@ export function ErrorSampleDetails({
|
|||
<Summary
|
||||
items={[
|
||||
<TimestampTooltip time={errorData ? error.timestamp.us / 1000 : 0} />,
|
||||
errorUrl && method ? (
|
||||
errorUrl ? (
|
||||
<HttpInfoSummaryItem url={errorUrl} method={method} status={status} />
|
||||
) : null,
|
||||
userAgent?.name ? <UserAgentSummaryItem {...userAgent} /> : null,
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { buildUrl } from './build_url';
|
||||
import type { Transaction } from '../../typings/es_schemas/ui/transaction';
|
||||
import { type ItemType, buildUrl } from './build_url';
|
||||
|
||||
describe('buildUrl', () => {
|
||||
it('should return a full URL when all fields are provided', () => {
|
||||
|
@ -20,7 +19,7 @@ describe('buildUrl', () => {
|
|||
port: 443,
|
||||
},
|
||||
};
|
||||
const result = buildUrl(item as unknown as Transaction);
|
||||
const result = buildUrl(item);
|
||||
expect(result).toBe('ftp://example.com:443/some/path');
|
||||
});
|
||||
|
||||
|
@ -34,7 +33,7 @@ describe('buildUrl', () => {
|
|||
address: 'example.org',
|
||||
},
|
||||
};
|
||||
const result = buildUrl(item as Transaction);
|
||||
const result = buildUrl(item);
|
||||
expect(result).toBe('http://example.org/another/path');
|
||||
});
|
||||
|
||||
|
@ -48,7 +47,7 @@ describe('buildUrl', () => {
|
|||
port: 8443,
|
||||
},
|
||||
};
|
||||
const result = buildUrl(item as unknown as Transaction);
|
||||
const result = buildUrl(item);
|
||||
expect(result).toBe('https://example.net:8443/');
|
||||
});
|
||||
|
||||
|
@ -62,7 +61,7 @@ describe('buildUrl', () => {
|
|||
port: 8080,
|
||||
},
|
||||
};
|
||||
const result = buildUrl(item as unknown as Transaction);
|
||||
const result = buildUrl(item);
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
|
@ -76,7 +75,7 @@ describe('buildUrl', () => {
|
|||
port: 8080,
|
||||
},
|
||||
};
|
||||
const result = buildUrl(item as unknown as Transaction);
|
||||
const result = buildUrl(item);
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
|
@ -90,17 +89,17 @@ describe('buildUrl', () => {
|
|||
},
|
||||
server: {
|
||||
address: 'example.com',
|
||||
port: 'invalid-port',
|
||||
port: 'invalid', // Invalid port
|
||||
},
|
||||
};
|
||||
|
||||
const result = buildUrl(item as unknown as Transaction);
|
||||
const result = buildUrl(item as unknown as ItemType);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
||||
'Failed to build URL',
|
||||
expect.objectContaining({
|
||||
message: 'Invalid base URL: https://example.com:invalid-port',
|
||||
message: 'Invalid base URL: https://example.com:invalid',
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -109,7 +108,7 @@ describe('buildUrl', () => {
|
|||
|
||||
it('should handle an empty object gracefully', () => {
|
||||
const item = {};
|
||||
const result = buildUrl(item as Transaction);
|
||||
const result = buildUrl(item);
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,11 +4,18 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import type { Transaction } from '../../typings/es_schemas/ui/transaction';
|
||||
import type { Span } from '../../typings/es_schemas/ui/span';
|
||||
import type { APMError } from '../../typings/es_schemas/ui/apm_error';
|
||||
export interface ItemType {
|
||||
url?: {
|
||||
scheme?: string;
|
||||
path?: string;
|
||||
};
|
||||
server?: {
|
||||
address?: string;
|
||||
port?: number;
|
||||
};
|
||||
}
|
||||
|
||||
export const buildUrl = (item: Transaction | Span | APMError) => {
|
||||
export const buildUrl = (item?: ItemType) => {
|
||||
// URL fields from Otel
|
||||
const urlScheme = item?.url?.scheme;
|
||||
const urlPath = item?.url?.path;
|
||||
|
|
|
@ -128,6 +128,10 @@ export async function getTransaction({
|
|||
|
||||
return {
|
||||
...event,
|
||||
server: {
|
||||
...event.server,
|
||||
port: event.server?.port ? Number(event.server?.port) : undefined,
|
||||
},
|
||||
transaction: {
|
||||
...event.transaction,
|
||||
marks: source?.transaction?.marks,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue