From 77dd6f775121bb0c893f084c8154318a4dac8c62 Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Mon, 5 Feb 2024 12:24:14 +0000 Subject: [PATCH 01/17] new API --- .../app/transaction_details/profiling_tab.tsx | 27 ++++++++++++ .../transaction_details_tabs.tsx | 2 + .../apm/server/routes/profiling/route.ts | 41 +++++++++++++++++++ .../common/profiling_es_client.ts | 2 + .../server/services/fetch_flamechart/index.ts | 21 +++++++++- .../utils/create_profiling_es_client.ts | 28 +++++++++++++ 6 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx new file mode 100644 index 0000000000000..41ffa59db804e --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx @@ -0,0 +1,27 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import React from 'react'; + +function ProfilingTab() { + return ( +
+ {i18n.translate('xpack.apm.profilingTab.div.caueLabel', { + defaultMessage: 'caue', + })} +
+ ); +} + +export const profilingTab = { + dataTestSubj: 'apmProfilingTabButton', + key: 'Profiling', + label: i18n.translate('xpack.apm.transactionDetails.tabs.ProfilingLabel', { + defaultMessage: 'Universal Profiling', + }), + component: ProfilingTab, +}; diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx index ba74d9e94d08e..176c4cb8e58f0 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx @@ -36,6 +36,7 @@ import { useSampleChartSelection } from '../../../hooks/use_sample_chart_selecti import { FETCH_STATUS } from '../../../hooks/use_fetcher'; import { useCriticalPathFeatureEnabledSetting } from '../../../hooks/use_critical_path_feature_enabled_setting'; import { aggregatedCriticalPathTab } from './aggregated_critical_path_tab'; +import { profilingTab } from './profiling_tab'; export interface TabContentProps { clearChartSelection: () => void; @@ -50,6 +51,7 @@ const tabs = [ traceSamplesTab, latencyCorrelationsTab, failedTransactionsCorrelationsTab, + profilingTab, ]; export function TransactionDetailsTabs() { diff --git a/x-pack/plugins/apm/server/routes/profiling/route.ts b/x-pack/plugins/apm/server/routes/profiling/route.ts index 0421cb994124a..56a77f2fc1b77 100644 --- a/x-pack/plugins/apm/server/routes/profiling/route.ts +++ b/x-pack/plugins/apm/server/routes/profiling/route.ts @@ -86,6 +86,46 @@ const profilingFlamegraphRoute = createApmServerRoute({ }, }); +const transactionsFlamegraphRoute = createApmServerRoute({ + endpoint: 'GET /internal/apm/services/{serviceName}/transactions/flamegraph', + params: t.type({ + path: t.type({ serviceName: t.string }), + query: t.intersection([ + rangeRt, + kueryRt, + t.type({ transactionName: t.string }), + ]), + }), + options: { tags: ['access:apm'] }, + handler: async (resources): Promise => { + const { context, plugins, params } = resources; + const core = await context.core; + const [esClient, profilingDataAccessStart] = await Promise.all([ + core.elasticsearch.client, + await plugins.profilingDataAccess?.start(), + ]); + if (profilingDataAccessStart) { + const { serviceName } = params.path; + const { start, end, kuery, transactionName } = params.query; + + return await profilingDataAccessStart?.services.fetchFlamechartData({ + core, + esClient: esClient.asCurrentUser, + rangeFromMs: start, + rangeToMs: end, + kuery, + // TODO: caue fix this + indices: '.ds-traces-apm-default-2024.02.02-000001', + stacktraceIdsField: 'transaction.profiler_stack_trace_ids', + serviceName, + transactionName, + }); + } + + return undefined; + }, +}); + const profilingFunctionsRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/services/{serviceName}/profiling/functions', params: t.type({ @@ -190,4 +230,5 @@ export const profilingRouteRepository = { ...profilingFlamegraphRoute, ...profilingStatusRoute, ...profilingFunctionsRoute, + ...transactionsFlamegraphRoute, }; diff --git a/x-pack/plugins/profiling_data_access/common/profiling_es_client.ts b/x-pack/plugins/profiling_data_access/common/profiling_es_client.ts index 39c95aa26d933..cae446c08d6d4 100644 --- a/x-pack/plugins/profiling_data_access/common/profiling_es_client.ts +++ b/x-pack/plugins/profiling_data_access/common/profiling_es_client.ts @@ -42,5 +42,7 @@ export interface ProfilingESClient { pervCPUWattArm64?: number; awsCostDiscountRate?: number; costPervCPUPerHour?: number; + indices?: string; + stacktraceIdsField?: string; }): Promise; } diff --git a/x-pack/plugins/profiling_data_access/server/services/fetch_flamechart/index.ts b/x-pack/plugins/profiling_data_access/server/services/fetch_flamechart/index.ts index 669b444e18c21..d3d48b2d1b350 100644 --- a/x-pack/plugins/profiling_data_access/server/services/fetch_flamechart/index.ts +++ b/x-pack/plugins/profiling_data_access/server/services/fetch_flamechart/index.ts @@ -24,12 +24,26 @@ export interface FetchFlamechartParams { rangeFromMs: number; rangeToMs: number; kuery: string; + indices?: string; + stacktraceIdsField?: string; + serviceName?: string; + transactionName?: string; } const targetSampleSize = 20000; // minimum number of samples to get statistically sound results export function createFetchFlamechart({ createProfilingEsClient }: RegisterServicesParams) { - return async ({ core, esClient, rangeFromMs, rangeToMs, kuery }: FetchFlamechartParams) => { + return async ({ + core, + esClient, + rangeFromMs, + rangeToMs, + kuery, + indices, + stacktraceIdsField, + serviceName, + transactionName, + }: FetchFlamechartParams) => { const rangeFromSecs = rangeFromMs / 1000; const rangeToSecs = rangeToMs / 1000; @@ -52,10 +66,13 @@ export function createFetchFlamechart({ createProfilingEsClient }: RegisterServi const profilingEsClient = createProfilingEsClient({ esClient }); const totalSeconds = rangeToSecs - rangeFromSecs; const flamegraph = await profilingEsClient.profilingFlamegraph({ + // TODO: caue maybe receive the query as a new argument?! query: { bool: { filter: [ ...kqlQuery(kuery), + ...(serviceName ? [{ term: { 'service.name': serviceName } }] : []), + ...(transactionName ? [{ term: { 'transaction.name': transactionName } }] : []), { range: { ['@timestamp']: { @@ -76,6 +93,8 @@ export function createFetchFlamechart({ createProfilingEsClient }: RegisterServi pervCPUWattArm64, awsCostDiscountRate: percentToFactor(awsCostDiscountRate), costPervCPUPerHour, + indices, + stacktraceIdsField, }); return { ...flamegraph, TotalSeconds: totalSeconds }; }; diff --git a/x-pack/plugins/profiling_data_access/server/utils/create_profiling_es_client.ts b/x-pack/plugins/profiling_data_access/server/utils/create_profiling_es_client.ts index 4e293031aa327..70d5ffee4be0b 100644 --- a/x-pack/plugins/profiling_data_access/server/utils/create_profiling_es_client.ts +++ b/x-pack/plugins/profiling_data_access/server/utils/create_profiling_es_client.ts @@ -110,8 +110,34 @@ export function createProfilingEsClient({ costPervCPUPerHour, pervCPUWattArm64, pervCPUWattX86, + indices, + stacktraceIdsField, }) { const controller = new AbortController(); + console.log( + '#####', + JSON.stringify( + { + method: 'POST', + path: encodeURI('/_profiling/flamegraph'), + body: { + query, + sample_size: sampleSize, + requested_duration: durationSeconds, + co2_per_kwh: co2PerKWH, + per_core_watt_x86: pervCPUWattX86, + per_core_watt_arm64: pervCPUWattArm64, + datacenter_pue: datacenterPUE, + aws_cost_factor: awsCostDiscountRate, + cost_per_core_hour: costPervCPUPerHour, + indices, + stacktrace_ids_field: stacktraceIdsField, + }, + }, + null, + 2 + ) + ); const promise = withProfilingSpan('_profiling/flamegraph', () => { return esClient.transport.request( @@ -128,6 +154,8 @@ export function createProfilingEsClient({ datacenter_pue: datacenterPUE, aws_cost_factor: awsCostDiscountRate, cost_per_core_hour: costPervCPUPerHour, + indices, + stacktrace_ids_field: stacktraceIdsField, }, }, { From d9984a7b1e86a0ec7091ceecd0a46e6195c5ff20 Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Mon, 5 Feb 2024 14:05:29 +0000 Subject: [PATCH 02/17] refactoring flamegraph comps --- .../profiling_flamegraph.tsx | 58 ++++--------------- .../app/transaction_details/profiling_tab.tsx | 48 +++++++++++++-- .../profiling/flamegraph/flamegraph_link.tsx | 35 +++++++++++ .../shared/profiling/flamegraph/index.tsx | 45 ++++++++++++++ 4 files changed, 133 insertions(+), 53 deletions(-) create mode 100644 x-pack/plugins/apm/public/components/shared/profiling/flamegraph/flamegraph_link.tsx create mode 100644 x-pack/plugins/apm/public/components/shared/profiling/flamegraph/index.tsx diff --git a/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_flamegraph.tsx b/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_flamegraph.tsx index bbae54abdf708..9edff8d21bb17 100644 --- a/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_flamegraph.tsx +++ b/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_flamegraph.tsx @@ -5,16 +5,7 @@ * 2.0. */ -import { - EuiEmptyPrompt, - EuiFlexGroup, - EuiFlexItem, - EuiLink, - EuiSpacer, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { EmbeddableFlamegraph } from '@kbn/observability-shared-plugin/public'; -import { isEmpty } from 'lodash'; +import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import React from 'react'; import { ApmDataSourceWithSummary } from '../../../../common/data_source'; import { ApmDocumentType } from '../../../../common/document_type'; @@ -23,12 +14,9 @@ import { mergeKueries, toKueryFilterFormat, } from '../../../../common/utils/kuery_utils'; -import { - FETCH_STATUS, - isPending, - useFetcher, -} from '../../../hooks/use_fetcher'; -import { useProfilingPlugin } from '../../../hooks/use_profiling_plugin'; +import { useFetcher } from '../../../hooks/use_fetcher'; +import { ProfilingFlamegraphChart } from '../../shared/profiling/flamegraph'; +import { ProfilingFlamegraphLink } from '../../shared/profiling/flamegraph/flamegraph_link'; import { HostnamesFilterWarning } from './host_names_filter_warning'; interface Props { @@ -54,8 +42,6 @@ export function ProfilingFlamegraph({ rangeFrom, rangeTo, }: Props) { - const { profilingLocators } = useProfilingPlugin(); - const { data, status } = useFetcher( (callApmApi) => { if (dataSource) { @@ -93,40 +79,16 @@ export function ProfilingFlamegraph({
- - {i18n.translate('xpack.apm.profiling.flamegraph.link', { - defaultMessage: 'Go to Universal Profiling Flamegraph', - })} - +
- {status === FETCH_STATUS.SUCCESS && isEmpty(data) ? ( - - {i18n.translate('xpack.apm.profiling.flamegraph.noDataFound', { - defaultMessage: 'No data found', - })} - - } - /> - ) : ( - - )} + ); } diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx index 41ffa59db804e..6bb828d075f6d 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx @@ -4,16 +4,54 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; +import { useApmParams } from '../../../hooks/use_apm_params'; +import { useFetcher } from '../../../hooks/use_fetcher'; +import { useTimeRange } from '../../../hooks/use_time_range'; +import { ProfilingFlamegraphChart } from '../../shared/profiling/flamegraph'; +import { ProfilingFlamegraphLink } from '../../shared/profiling/flamegraph/flamegraph_link'; function ProfilingTab() { + const { + query: { rangeFrom, rangeTo, environment, kuery, transactionName }, + path: { serviceName }, + } = useApmParams('/services/{serviceName}/transactions/view'); + const { start, end } = useTimeRange({ rangeFrom, rangeTo }); + + const { data, status } = useFetcher( + (callApmApi) => { + return callApmApi( + 'GET /internal/apm/services/{serviceName}/transactions/flamegraph', + { + params: { + path: { serviceName }, + query: { + start, + end, + kuery, + transactionName, + }, + }, + } + ); + }, + [serviceName, start, end, kuery, transactionName] + ); + return ( -
- {i18n.translate('xpack.apm.profilingTab.div.caueLabel', { - defaultMessage: 'caue', - })} -
+ <> +
+ +
+ + + ); } diff --git a/x-pack/plugins/apm/public/components/shared/profiling/flamegraph/flamegraph_link.tsx b/x-pack/plugins/apm/public/components/shared/profiling/flamegraph/flamegraph_link.tsx new file mode 100644 index 0000000000000..8b90573b463dc --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/profiling/flamegraph/flamegraph_link.tsx @@ -0,0 +1,35 @@ +/* + * 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 { EuiLink } from '@elastic/eui'; +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { useProfilingPlugin } from '../../../../hooks/use_profiling_plugin'; + +interface Props { + kuery: string; + rangeFrom: string; + rangeTo: string; +} + +export function ProfilingFlamegraphLink({ kuery, rangeFrom, rangeTo }: Props) { + const { profilingLocators } = useProfilingPlugin(); + return ( + + {i18n.translate('xpack.apm.profiling.flamegraph.link', { + defaultMessage: 'Go to Universal Profiling Flamegraph', + })} + + ); +} diff --git a/x-pack/plugins/apm/public/components/shared/profiling/flamegraph/index.tsx b/x-pack/plugins/apm/public/components/shared/profiling/flamegraph/index.tsx new file mode 100644 index 0000000000000..afacbaa22ad95 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/profiling/flamegraph/index.tsx @@ -0,0 +1,45 @@ +/* + * 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 { EuiEmptyPrompt } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { EmbeddableFlamegraph } from '@kbn/observability-shared-plugin/public'; +import { BaseFlameGraph } from '@kbn/profiling-utils'; +import { isEmpty } from 'lodash'; +import React from 'react'; +import { FETCH_STATUS, isPending } from '../../../../hooks/use_fetcher'; + +interface Props { + data?: BaseFlameGraph; + status: FETCH_STATUS; +} + +export function ProfilingFlamegraphChart({ data, status }: Props) { + return ( + <> + {status === FETCH_STATUS.SUCCESS && isEmpty(data) ? ( + + {i18n.translate('xpack.apm.profiling.flamegraph.noDataFound', { + defaultMessage: 'No data found', + })} + + } + /> + ) : ( +
+ +
+ )} + + ); +} From f10165807814c63ac82874e67614bf8b729ed926 Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Tue, 6 Feb 2024 13:08:48 +0000 Subject: [PATCH 03/17] refactoring flamegraph service --- packages/kbn-io-ts-utils/index.ts | 1 + .../src/iso_to_epoch_secs_rt/index.test.ts | 33 +++++++++ .../src/iso_to_epoch_secs_rt/index.ts | 25 +++++++ .../shared/profiling/flamegraph/index.tsx | 3 +- .../apm/server/routes/profiling/route.ts | 70 +++++++++++++++---- .../server/services/fetch_flamechart/index.ts | 42 ++--------- 6 files changed, 123 insertions(+), 51 deletions(-) create mode 100644 packages/kbn-io-ts-utils/src/iso_to_epoch_secs_rt/index.test.ts create mode 100644 packages/kbn-io-ts-utils/src/iso_to_epoch_secs_rt/index.ts diff --git a/packages/kbn-io-ts-utils/index.ts b/packages/kbn-io-ts-utils/index.ts index 8f1b974eccdcb..2a6c02f6cdf17 100644 --- a/packages/kbn-io-ts-utils/index.ts +++ b/packages/kbn-io-ts-utils/index.ts @@ -15,6 +15,7 @@ export { jsonRt } from './src/json_rt'; export { mergeRt } from './src/merge_rt'; export { strictKeysRt } from './src/strict_keys_rt'; export { isoToEpochRt } from './src/iso_to_epoch_rt'; +export { isoToEpochSecsRt } from './src/iso_to_epoch_secs_rt'; export { toNumberRt } from './src/to_number_rt'; export { toBooleanRt } from './src/to_boolean_rt'; export { toJsonSchema } from './src/to_json_schema'; diff --git a/packages/kbn-io-ts-utils/src/iso_to_epoch_secs_rt/index.test.ts b/packages/kbn-io-ts-utils/src/iso_to_epoch_secs_rt/index.test.ts new file mode 100644 index 0000000000000..d9c06a2f61b5c --- /dev/null +++ b/packages/kbn-io-ts-utils/src/iso_to_epoch_secs_rt/index.test.ts @@ -0,0 +1,33 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { isoToEpochSecsRt } from '.'; +import { isRight } from 'fp-ts/lib/Either'; + +describe('isoToEpochSecsRt', () => { + it('validates whether its input is a valid ISO timestamp', () => { + expect(isRight(isoToEpochSecsRt.decode(1566299881499))).toBe(false); + + expect(isRight(isoToEpochSecsRt.decode('2019-08-20T11:18:31.407Z'))).toBe(true); + }); + + it('decodes valid ISO timestamps to epoch secs time', () => { + const iso = '2019-08-20T11:18:31.407Z'; + const result = isoToEpochSecsRt.decode(iso); + + if (isRight(result)) { + expect(result.right).toBe(new Date(iso).getTime() / 1000); + } else { + fail(); + } + }); + + it('encodes epoch secs time to ISO string', () => { + expect(isoToEpochSecsRt.encode(1566299911407)).toBe('2019-08-20T11:18:31.407Z'); + }); +}); diff --git a/packages/kbn-io-ts-utils/src/iso_to_epoch_secs_rt/index.ts b/packages/kbn-io-ts-utils/src/iso_to_epoch_secs_rt/index.ts new file mode 100644 index 0000000000000..a4bbfdc59b603 --- /dev/null +++ b/packages/kbn-io-ts-utils/src/iso_to_epoch_secs_rt/index.ts @@ -0,0 +1,25 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { chain } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/function'; +import * as t from 'io-ts'; +import { isoToEpochRt } from '../iso_to_epoch_rt'; + +export const isoToEpochSecsRt = new t.Type( + 'isoToEpochSecsRt', + t.number.is, + (value) => + pipe( + isoToEpochRt.decode(value), + chain((epochMsValue) => { + return t.success(epochMsValue / 1000); + }) + ), + (output) => new Date(output).toISOString() +); diff --git a/x-pack/plugins/apm/public/components/shared/profiling/flamegraph/index.tsx b/x-pack/plugins/apm/public/components/shared/profiling/flamegraph/index.tsx index afacbaa22ad95..bfb49918fb987 100644 --- a/x-pack/plugins/apm/public/components/shared/profiling/flamegraph/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/profiling/flamegraph/index.tsx @@ -20,7 +20,8 @@ interface Props { export function ProfilingFlamegraphChart({ data, status }: Props) { return ( <> - {status === FETCH_STATUS.SUCCESS && isEmpty(data) ? ( + {status === FETCH_STATUS.SUCCESS && + (isEmpty(data) || data?.TotalSamples === 0) ? ( { - const rangeFromSecs = rangeFromMs / 1000; - const rangeToSecs = rangeToMs / 1000; - const [ co2PerKWH, datacenterPUE, @@ -64,27 +54,9 @@ export function createFetchFlamechart({ createProfilingEsClient }: RegisterServi ]); const profilingEsClient = createProfilingEsClient({ esClient }); - const totalSeconds = rangeToSecs - rangeFromSecs; + const flamegraph = await profilingEsClient.profilingFlamegraph({ - // TODO: caue maybe receive the query as a new argument?! - query: { - bool: { - filter: [ - ...kqlQuery(kuery), - ...(serviceName ? [{ term: { 'service.name': serviceName } }] : []), - ...(transactionName ? [{ term: { 'transaction.name': transactionName } }] : []), - { - range: { - ['@timestamp']: { - gte: String(rangeFromSecs), - lt: String(rangeToSecs), - format: 'epoch_second', - }, - }, - }, - ], - }, - }, + query, sampleSize: targetSampleSize, durationSeconds: totalSeconds, co2PerKWH, From e76d2b1df3a337a6d8c55dad33629eeaea18632e Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Tue, 6 Feb 2024 13:10:40 +0000 Subject: [PATCH 04/17] refacotring infra plugin --- .../lib/fetch_profiling_flamegraph.ts | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/infra/server/routes/profiling/lib/fetch_profiling_flamegraph.ts b/x-pack/plugins/infra/server/routes/profiling/lib/fetch_profiling_flamegraph.ts index 8b3ab0414f5c8..51e2e9f8d7f11 100644 --- a/x-pack/plugins/infra/server/routes/profiling/lib/fetch_profiling_flamegraph.ts +++ b/x-pack/plugins/infra/server/routes/profiling/lib/fetch_profiling_flamegraph.ts @@ -8,6 +8,7 @@ import type { CoreRequestHandlerContext } from '@kbn/core-http-request-handler-context-server'; import type { ProfilingDataAccessPluginStart } from '@kbn/profiling-data-access-plugin/server'; import type { BaseFlameGraph } from '@kbn/profiling-utils'; +import { kqlQuery } from '@kbn/observability-plugin/server'; import type { InfraProfilingFlamegraphRequestParams } from '../../../../common/http_api/profiling_api'; export async function fetchProfilingFlamegraph( @@ -15,11 +16,28 @@ export async function fetchProfilingFlamegraph( profilingDataAccess: ProfilingDataAccessPluginStart, coreRequestContext: CoreRequestHandlerContext ): Promise { + const startSecs = from / 1000; + const endSecs = to / 1000; + return await profilingDataAccess.services.fetchFlamechartData({ core: coreRequestContext, esClient: coreRequestContext.elasticsearch.client.asCurrentUser, - rangeFromMs: from, - rangeToMs: to, - kuery, + totalSeconds: endSecs - startSecs, + query: { + bool: { + filter: [ + ...kqlQuery(kuery), + { + range: { + ['@timestamp']: { + gte: String(startSecs), + lt: String(endSecs), + format: 'epoch_second', + }, + }, + }, + ], + }, + }, }); } From cc8c8dbb9b7690ad384875b1846ec3cb9e13db6c Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Tue, 6 Feb 2024 13:25:55 +0000 Subject: [PATCH 05/17] new transactions functions api --- .../apm/server/routes/profiling/route.ts | 45 +++++++++++++++++++ .../common/profiling_es_client.ts | 2 + .../server/services/functions/index.ts | 6 +++ .../services/search_stack_traces/index.ts | 6 +++ .../utils/create_profiling_es_client.ts | 28 ++---------- 5 files changed, 63 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/apm/server/routes/profiling/route.ts b/x-pack/plugins/apm/server/routes/profiling/route.ts index 3a665360f0275..853b1a944af90 100644 --- a/x-pack/plugins/apm/server/routes/profiling/route.ts +++ b/x-pack/plugins/apm/server/routes/profiling/route.ts @@ -236,6 +236,50 @@ const profilingFunctionsRoute = createApmServerRoute({ }, }); +const transactionsFunctionsRoute = createApmServerRoute({ + endpoint: 'GET /internal/apm/services/{serviceName}/transactions/functions', + params: t.type({ + path: t.type({ serviceName: t.string }), + query: t.intersection([ + rangeRt, + t.type({ + startIndex: toNumberRt, + endIndex: toNumberRt, + transactionName: t.string, + }), + kueryRt, + ]), + }), + options: { tags: ['access:apm'] }, + handler: async (resources): Promise => { + const { context, plugins, params } = resources; + const core = await context.core; + const [esClient, profilingDataAccessStart] = await Promise.all([ + core.elasticsearch.client, + await plugins.profilingDataAccess?.start(), + ]); + if (profilingDataAccessStart) { + const { start, end, startIndex, endIndex, kuery } = params.query; + const { serviceName } = params.path; + + return profilingDataAccessStart?.services.fetchFunction({ + core, + esClient: esClient.asCurrentUser, + rangeFromMs: start, + rangeToMs: end, + kuery, + startIndex, + endIndex, + // TODO: caue fix this + indices: '.ds-traces-apm-default-2024.02.02-000001', + stacktraceIdsField: 'transaction.profiler_stack_trace_ids', + }); + } + + return undefined; + }, +}); + const profilingStatusRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/profiling/status', options: { tags: ['access:apm'] }, @@ -271,4 +315,5 @@ export const profilingRouteRepository = { ...profilingStatusRoute, ...profilingFunctionsRoute, ...transactionsFlamegraphRoute, + ...transactionsFunctionsRoute, }; diff --git a/x-pack/plugins/profiling_data_access/common/profiling_es_client.ts b/x-pack/plugins/profiling_data_access/common/profiling_es_client.ts index cae446c08d6d4..c8316fecf4c96 100644 --- a/x-pack/plugins/profiling_data_access/common/profiling_es_client.ts +++ b/x-pack/plugins/profiling_data_access/common/profiling_es_client.ts @@ -29,6 +29,8 @@ export interface ProfilingESClient { pervCPUWattArm64?: number; awsCostDiscountRate?: number; costPervCPUPerHour?: number; + indices?: string; + stacktraceIdsField?: string; }): Promise; profilingStatus(params?: { waitForResourcesCreated?: boolean }): Promise; getEsClient(): ElasticsearchClient; diff --git a/x-pack/plugins/profiling_data_access/server/services/functions/index.ts b/x-pack/plugins/profiling_data_access/server/services/functions/index.ts index 8492562d9c775..b08d920a36aac 100644 --- a/x-pack/plugins/profiling_data_access/server/services/functions/index.ts +++ b/x-pack/plugins/profiling_data_access/server/services/functions/index.ts @@ -27,6 +27,8 @@ export interface FetchFunctionsParams { kuery: string; startIndex: number; endIndex: number; + indices?: string; + stacktraceIdsField?: string; } const targetSampleSize = 20000; // minimum number of samples to get statistically sound results @@ -40,6 +42,8 @@ export function createFetchFunctions({ createProfilingEsClient }: RegisterServic kuery, startIndex, endIndex, + indices, + stacktraceIdsField, }: FetchFunctionsParams) => { const rangeFromSecs = rangeFromMs / 1000; const rangeToSecs = rangeToMs / 1000; @@ -77,6 +81,8 @@ export function createFetchFunctions({ createProfilingEsClient }: RegisterServic pervCPUWattArm64, awsCostDiscountRate: percentToFactor(awsCostDiscountRate), costPervCPUPerHour, + indices, + stacktraceIdsField, } ); diff --git a/x-pack/plugins/profiling_data_access/server/services/search_stack_traces/index.ts b/x-pack/plugins/profiling_data_access/server/services/search_stack_traces/index.ts index 6da9187d7a2ed..2b24c7a1071c7 100644 --- a/x-pack/plugins/profiling_data_access/server/services/search_stack_traces/index.ts +++ b/x-pack/plugins/profiling_data_access/server/services/search_stack_traces/index.ts @@ -22,6 +22,8 @@ export async function searchStackTraces({ pervCPUWattArm64, awsCostDiscountRate, costPervCPUPerHour, + indices, + stacktraceIdsField, }: { client: ProfilingESClient; sampleSize: number; @@ -35,6 +37,8 @@ export async function searchStackTraces({ pervCPUWattArm64: number; awsCostDiscountRate: number; costPervCPUPerHour: number; + indices?: string; + stacktraceIdsField?: string; }) { const response = await client.profilingStacktraces({ query: { @@ -62,6 +66,8 @@ export async function searchStackTraces({ pervCPUWattArm64, awsCostDiscountRate, costPervCPUPerHour, + indices, + stacktraceIdsField, }); return decodeStackTraceResponse(response); diff --git a/x-pack/plugins/profiling_data_access/server/utils/create_profiling_es_client.ts b/x-pack/plugins/profiling_data_access/server/utils/create_profiling_es_client.ts index 70d5ffee4be0b..a06568418771a 100644 --- a/x-pack/plugins/profiling_data_access/server/utils/create_profiling_es_client.ts +++ b/x-pack/plugins/profiling_data_access/server/utils/create_profiling_es_client.ts @@ -49,6 +49,8 @@ export function createProfilingEsClient({ costPervCPUPerHour, pervCPUWattArm64, pervCPUWattX86, + indices, + stacktraceIdsField, }) { const controller = new AbortController(); const promise = withProfilingSpan('_profiling/stacktraces', () => { @@ -66,6 +68,8 @@ export function createProfilingEsClient({ datacenter_pue: datacenterPUE, aws_cost_factor: awsCostDiscountRate, cost_per_core_hour: costPervCPUPerHour, + indices, + stacktrace_ids_field: stacktraceIdsField, }, }, { @@ -114,30 +118,6 @@ export function createProfilingEsClient({ stacktraceIdsField, }) { const controller = new AbortController(); - console.log( - '#####', - JSON.stringify( - { - method: 'POST', - path: encodeURI('/_profiling/flamegraph'), - body: { - query, - sample_size: sampleSize, - requested_duration: durationSeconds, - co2_per_kwh: co2PerKWH, - per_core_watt_x86: pervCPUWattX86, - per_core_watt_arm64: pervCPUWattArm64, - datacenter_pue: datacenterPUE, - aws_cost_factor: awsCostDiscountRate, - cost_per_core_hour: costPervCPUPerHour, - indices, - stacktrace_ids_field: stacktraceIdsField, - }, - }, - null, - 2 - ) - ); const promise = withProfilingSpan('_profiling/flamegraph', () => { return esClient.transport.request( From 707159bb35c304feea54c7610abf4712f3f83ae6 Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Tue, 6 Feb 2024 14:04:21 +0000 Subject: [PATCH 06/17] functions components refac --- .../profiling_top_functions.tsx | 24 ++----- .../profiling_flamegraph.tsx | 64 +++++++++++++++++ .../app/transaction_details/profiling_tab.tsx | 49 +++++-------- .../profiling_top_functions.tsx | 71 +++++++++++++++++++ .../top_functions/top_functions_link.tsx | 40 +++++++++++ 5 files changed, 198 insertions(+), 50 deletions(-) create mode 100644 x-pack/plugins/apm/public/components/app/transaction_details/profiling_flamegraph.tsx create mode 100644 x-pack/plugins/apm/public/components/app/transaction_details/profiling_top_functions.tsx create mode 100644 x-pack/plugins/apm/public/components/shared/profiling/top_functions/top_functions_link.tsx diff --git a/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_top_functions.tsx b/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_top_functions.tsx index 0462af188d3f9..be9ca21f80709 100644 --- a/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_top_functions.tsx +++ b/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_top_functions.tsx @@ -5,8 +5,7 @@ * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiLink, EuiSpacer } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; +import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { EmbeddableFunctions } from '@kbn/observability-shared-plugin/public'; import React from 'react'; import { ApmDataSourceWithSummary } from '../../../../common/data_source'; @@ -17,7 +16,7 @@ import { toKueryFilterFormat, } from '../../../../common/utils/kuery_utils'; import { isPending, useFetcher } from '../../../hooks/use_fetcher'; -import { useProfilingPlugin } from '../../../hooks/use_profiling_plugin'; +import { ProfilingTopNFunctionsLink } from '../../shared/profiling/top_functions/top_functions_link'; import { HostnamesFilterWarning } from './host_names_filter_warning'; interface Props { @@ -47,8 +46,6 @@ export function ProfilingTopNFunctions({ rangeFrom, rangeTo, }: Props) { - const { profilingLocators } = useProfilingPlugin(); - const { data, status } = useFetcher( (callApmApi) => { if (dataSource) { @@ -97,18 +94,11 @@ export function ProfilingTopNFunctions({
- - {i18n.translate('xpack.apm.profiling.topnFunctions.link', { - defaultMessage: 'Go to Universal Profiling Functions', - })} - +
diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_flamegraph.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_flamegraph.tsx new file mode 100644 index 0000000000000..a3b69d068eecc --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_flamegraph.tsx @@ -0,0 +1,64 @@ +/* + * 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 { EuiSpacer } from '@elastic/eui'; +import React from 'react'; +import { useFetcher } from '../../../hooks/use_fetcher'; +import { useTimeRange } from '../../../hooks/use_time_range'; +import { ProfilingFlamegraphChart } from '../../shared/profiling/flamegraph'; +import { ProfilingFlamegraphLink } from '../../shared/profiling/flamegraph/flamegraph_link'; + +interface Props { + serviceName: string; + rangeFrom: string; + rangeTo: string; + kuery: string; + transactionName: string; +} + +export function ProfilingFlamegraph({ + serviceName, + rangeFrom, + rangeTo, + kuery, + transactionName, +}: Props) { + const { start, end } = useTimeRange({ rangeFrom, rangeTo }); + + const { data, status } = useFetcher( + (callApmApi) => { + return callApmApi( + 'GET /internal/apm/services/{serviceName}/transactions/flamegraph', + { + params: { + path: { serviceName }, + query: { + start, + end, + kuery, + transactionName, + }, + }, + } + ); + }, + [serviceName, start, end, kuery, transactionName] + ); + + return ( + <> +
+ +
+ + + + ); +} diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx index 6bb828d075f6d..fea02996a9b3a 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx @@ -8,49 +8,32 @@ import { EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { useApmParams } from '../../../hooks/use_apm_params'; -import { useFetcher } from '../../../hooks/use_fetcher'; -import { useTimeRange } from '../../../hooks/use_time_range'; -import { ProfilingFlamegraphChart } from '../../shared/profiling/flamegraph'; -import { ProfilingFlamegraphLink } from '../../shared/profiling/flamegraph/flamegraph_link'; +import { ProfilingFlamegraph } from './profiling_flamegraph'; +import { ProfilingTopNFunctions } from './profiling_top_functions'; function ProfilingTab() { const { query: { rangeFrom, rangeTo, environment, kuery, transactionName }, path: { serviceName }, } = useApmParams('/services/{serviceName}/transactions/view'); - const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - - const { data, status } = useFetcher( - (callApmApi) => { - return callApmApi( - 'GET /internal/apm/services/{serviceName}/transactions/flamegraph', - { - params: { - path: { serviceName }, - query: { - start, - end, - kuery, - transactionName, - }, - }, - } - ); - }, - [serviceName, start, end, kuery, transactionName] - ); return ( <> -
- -
+ - + ); } diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_top_functions.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_top_functions.tsx new file mode 100644 index 0000000000000..ff9c361be3d78 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_top_functions.tsx @@ -0,0 +1,71 @@ +/* + * 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 { EuiSpacer } from '@elastic/eui'; +import { EmbeddableFunctions } from '@kbn/observability-shared-plugin/public'; +import React from 'react'; +import { isPending, useFetcher } from '../../../hooks/use_fetcher'; +import { useTimeRange } from '../../../hooks/use_time_range'; +import { ProfilingTopNFunctionsLink } from '../../shared/profiling/top_functions/top_functions_link'; + +interface Props { + serviceName: string; + rangeFrom: string; + rangeTo: string; + kuery: string; + transactionName: string; +} + +export function ProfilingTopNFunctions({ + serviceName, + rangeFrom, + rangeTo, + kuery, + transactionName, +}: Props) { + const { start, end } = useTimeRange({ rangeFrom, rangeTo }); + + const { data, status } = useFetcher( + (callApmApi) => { + return callApmApi( + 'GET /internal/apm/services/{serviceName}/transactions/functions', + { + params: { + path: { serviceName }, + query: { + start, + end, + kuery, + transactionName, + startIndex: 0, + endIndex: 10, + }, + }, + } + ); + }, + [serviceName, start, end, kuery, transactionName] + ); + + return ( + <> +
+ +
+ + + + ); +} diff --git a/x-pack/plugins/apm/public/components/shared/profiling/top_functions/top_functions_link.tsx b/x-pack/plugins/apm/public/components/shared/profiling/top_functions/top_functions_link.tsx new file mode 100644 index 0000000000000..cb7a39646f03a --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/profiling/top_functions/top_functions_link.tsx @@ -0,0 +1,40 @@ +/* + * 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 { EuiLink } from '@elastic/eui'; +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { useProfilingPlugin } from '../../../../hooks/use_profiling_plugin'; + +interface Props { + kuery: string; + rangeFrom: string; + rangeTo: string; +} + +export function ProfilingTopNFunctionsLink({ + kuery, + rangeFrom, + rangeTo, +}: Props) { + const { profilingLocators } = useProfilingPlugin(); + + return ( + + {i18n.translate('xpack.apm.profiling.topnFunctions.link', { + defaultMessage: 'Go to Universal Profiling Functions', + })} + + ); +} From 25fc34dfcc7219678a61e3ca348c0667c5e33a21 Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Tue, 6 Feb 2024 14:54:42 +0000 Subject: [PATCH 07/17] adding tabs to UP tab --- .../app/transaction_details/profiling_tab.tsx | 73 ++++++++++++++----- .../transaction_details_tabs.tsx | 50 +++++-------- 2 files changed, 72 insertions(+), 51 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx index fea02996a9b3a..cd0e1b25a0ea5 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx @@ -4,9 +4,13 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { EuiSpacer } from '@elastic/eui'; +import { + EuiSpacer, + EuiTabbedContent, + EuiTabbedContentProps, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import React from 'react'; +import React, { useMemo } from 'react'; import { useApmParams } from '../../../hooks/use_apm_params'; import { ProfilingFlamegraph } from './profiling_flamegraph'; import { ProfilingTopNFunctions } from './profiling_top_functions'; @@ -17,24 +21,55 @@ function ProfilingTab() { path: { serviceName }, } = useApmParams('/services/{serviceName}/transactions/view'); + const tabs = useMemo((): EuiTabbedContentProps['tabs'] => { + return [ + { + id: 'flamegraph', + name: i18n.translate( + 'xpack.apm.transactions.profiling.tabs.flamegraph', + { defaultMessage: 'Flamegraph' } + ), + content: ( + <> + + + + ), + }, + { + id: 'topNFunctions', + name: i18n.translate( + 'xpack.apm.transactions.profiling.tabs.topNFunctions', + { defaultMessage: 'Top 10 Functions' } + ), + content: ( + <> + + + + ), + }, + ]; + }, [kuery, rangeFrom, rangeTo, serviceName, transactionName]); + return ( - <> - - - - + ); } diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx index 176c4cb8e58f0..3f2ff0dd10076 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx @@ -7,36 +7,26 @@ import React, { useCallback, useEffect, useState } from 'react'; +import { XYBrushEvent } from '@elastic/charts'; +import { EuiPanel, EuiSpacer, EuiTab, EuiTabs } from '@elastic/eui'; import { omit } from 'lodash'; import { useHistory } from 'react-router-dom'; -import { - EuiPanel, - EuiSpacer, - EuiTabs, - EuiTab, - EuiFlexItem, - EuiFlexGroup, -} from '@elastic/eui'; - -import { XYBrushEvent } from '@elastic/charts'; +import { maybe } from '../../../../common/utils/maybe'; import { useLegacyUrlParams } from '../../../context/url_params_context/use_url_params'; import { useAnyOfApmParams } from '../../../hooks/use_apm_params'; +import { useCriticalPathFeatureEnabledSetting } from '../../../hooks/use_critical_path_feature_enabled_setting'; +import { FETCH_STATUS } from '../../../hooks/use_fetcher'; +import { useSampleChartSelection } from '../../../hooks/use_sample_chart_selection'; import { TraceSamplesFetchResult, useTransactionTraceSamplesFetcher, } from '../../../hooks/use_transaction_trace_samples_fetcher'; - -import { maybe } from '../../../../common/utils/maybe'; import { fromQuery, toQuery } from '../../shared/links/url_helpers'; - +import { aggregatedCriticalPathTab } from './aggregated_critical_path_tab'; import { failedTransactionsCorrelationsTab } from './failed_transactions_correlations_tab'; import { latencyCorrelationsTab } from './latency_correlations_tab'; -import { traceSamplesTab } from './trace_samples_tab'; -import { useSampleChartSelection } from '../../../hooks/use_sample_chart_selection'; -import { FETCH_STATUS } from '../../../hooks/use_fetcher'; -import { useCriticalPathFeatureEnabledSetting } from '../../../hooks/use_critical_path_feature_enabled_setting'; -import { aggregatedCriticalPathTab } from './aggregated_critical_path_tab'; import { profilingTab } from './profiling_tab'; +import { traceSamplesTab } from './trace_samples_tab'; export interface TabContentProps { clearChartSelection: () => void; @@ -142,20 +132,16 @@ export function TransactionDetailsTabs() { - - - - - + ); From 2e00af17fa0bcf63bcc2a5c6ae7bd1ba2eac0c60 Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Tue, 6 Feb 2024 16:47:12 +0000 Subject: [PATCH 08/17] refactoring functions service --- .../profiling_flamegraph.tsx | 19 +- .../app/transaction_details/profiling_tab.tsx | 23 +- .../profiling_top_functions.tsx | 19 +- .../apm/server/routes/profiling/route.ts | 198 ++++++++++++------ .../lib/fetch_profiling_functions.ts | 23 +- .../profiling/server/routes/flamechart.ts | 23 +- .../profiling/server/routes/functions.ts | 24 ++- .../server/services/functions/index.ts | 19 +- .../services/search_stack_traces/index.ts | 28 +-- 9 files changed, 258 insertions(+), 118 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_flamegraph.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_flamegraph.tsx index a3b69d068eecc..308ce1473f10a 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_flamegraph.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_flamegraph.tsx @@ -17,6 +17,8 @@ interface Props { rangeTo: string; kuery: string; transactionName: string; + transactionType?: string; + environment: string; } export function ProfilingFlamegraph({ @@ -25,11 +27,16 @@ export function ProfilingFlamegraph({ rangeTo, kuery, transactionName, + transactionType, + environment, }: Props) { const { start, end } = useTimeRange({ rangeFrom, rangeTo }); const { data, status } = useFetcher( (callApmApi) => { + if (!transactionType) { + return; + } return callApmApi( 'GET /internal/apm/services/{serviceName}/transactions/flamegraph', { @@ -40,12 +47,22 @@ export function ProfilingFlamegraph({ end, kuery, transactionName, + transactionType, + environment, }, }, } ); }, - [serviceName, start, end, kuery, transactionName] + [ + serviceName, + start, + end, + kuery, + transactionName, + transactionType, + environment, + ] ); return ( diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx index cd0e1b25a0ea5..e3871539f2037 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx @@ -17,7 +17,14 @@ import { ProfilingTopNFunctions } from './profiling_top_functions'; function ProfilingTab() { const { - query: { rangeFrom, rangeTo, environment, kuery, transactionName }, + query: { + rangeFrom, + rangeTo, + environment, + kuery, + transactionName, + transactionType, + }, path: { serviceName }, } = useApmParams('/services/{serviceName}/transactions/view'); @@ -38,6 +45,8 @@ function ProfilingTab() { rangeTo={rangeTo} kuery={kuery} transactionName={transactionName} + transactionType={transactionType} + environment={environment} /> ), @@ -57,12 +66,22 @@ function ProfilingTab() { rangeTo={rangeTo} kuery={kuery} transactionName={transactionName} + transactionType={transactionType} + environment={environment} /> ), }, ]; - }, [kuery, rangeFrom, rangeTo, serviceName, transactionName]); + }, [ + environment, + kuery, + rangeFrom, + rangeTo, + serviceName, + transactionName, + transactionType, + ]); return ( { + if (!transactionType) { + return; + } return callApmApi( 'GET /internal/apm/services/{serviceName}/transactions/functions', { @@ -42,12 +49,22 @@ export function ProfilingTopNFunctions({ transactionName, startIndex: 0, endIndex: 10, + transactionType, + environment, }, }, } ); }, - [serviceName, start, end, kuery, transactionName] + [ + serviceName, + start, + end, + kuery, + transactionName, + transactionType, + environment, + ] ); return ( diff --git a/x-pack/plugins/apm/server/routes/profiling/route.ts b/x-pack/plugins/apm/server/routes/profiling/route.ts index 853b1a944af90..f05ba6064fb39 100644 --- a/x-pack/plugins/apm/server/routes/profiling/route.ts +++ b/x-pack/plugins/apm/server/routes/profiling/route.ts @@ -13,6 +13,7 @@ import { HOST_NAME, SERVICE_NAME, TRANSACTION_NAME, + TRANSACTION_TYPE, } from '../../../common/es_fields/apm'; import { mergeKueries, @@ -27,6 +28,7 @@ import { serviceTransactionDataSourceRt, } from '../default_api_types'; import { getServiceHostNames } from './get_service_host_names'; +import { environmentQuery } from '../../../common/utils/environment_query'; const profilingFlamegraphRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/services/{serviceName}/profiling/flamegraph', @@ -109,63 +111,6 @@ const profilingFlamegraphRoute = createApmServerRoute({ }, }); -const transactionsFlamegraphRoute = createApmServerRoute({ - endpoint: 'GET /internal/apm/services/{serviceName}/transactions/flamegraph', - params: t.type({ - path: t.type({ serviceName: t.string }), - query: t.intersection([ - kueryRt, - t.type({ - transactionName: t.string, - start: isoToEpochSecsRt, - end: isoToEpochSecsRt, - }), - ]), - }), - options: { tags: ['access:apm'] }, - handler: async (resources): Promise => { - const { context, plugins, params } = resources; - const core = await context.core; - const [esClient, profilingDataAccessStart] = await Promise.all([ - core.elasticsearch.client, - await plugins.profilingDataAccess?.start(), - ]); - if (profilingDataAccessStart) { - const { serviceName } = params.path; - const { start, end, kuery, transactionName } = params.query; - - return await profilingDataAccessStart?.services.fetchFlamechartData({ - core, - esClient: esClient.asCurrentUser, - // TODO: caue fix this - indices: '.ds-traces-apm-default-2024.02.02-000001', - stacktraceIdsField: 'transaction.profiler_stack_trace_ids', - totalSeconds: end - start, - query: { - bool: { - filter: [ - ...kqlQuery(kuery), - ...termQuery(SERVICE_NAME, serviceName), - ...termQuery(TRANSACTION_NAME, transactionName), - { - range: { - ['@timestamp']: { - gte: String(start), - lt: String(end), - format: 'epoch_second', - }, - }, - }, - ], - }, - }, - }); - } - - return undefined; - }, -}); - const profilingFunctionsRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/services/{serviceName}/profiling/functions', params: t.type({ @@ -217,17 +162,36 @@ const profilingFunctionsRoute = createApmServerRoute({ return undefined; } + const startSecs = start / 1000; + const endSecs = end / 1000; + const functions = await profilingDataAccessStart?.services.fetchFunction({ core, esClient: esClient.asCurrentUser, - rangeFromMs: start, - rangeToMs: end, - kuery: mergeKueries([ - `(${toKueryFilterFormat(HOST_NAME, serviceHostNames)})`, - kuery, - ]), startIndex, endIndex, + totalSeconds: endSecs - startSecs, + query: { + bool: { + filter: [ + ...kqlQuery( + mergeKueries([ + `(${toKueryFilterFormat(HOST_NAME, serviceHostNames)})`, + kuery, + ]) + ), + { + range: { + ['@timestamp']: { + gte: String(startSecs), + lt: String(endSecs), + format: 'epoch_second', + }, + }, + }, + ], + }, + }, }); return { functions, hostNames: serviceHostNames }; } @@ -236,16 +200,87 @@ const profilingFunctionsRoute = createApmServerRoute({ }, }); +const transactionsFlamegraphRoute = createApmServerRoute({ + endpoint: 'GET /internal/apm/services/{serviceName}/transactions/flamegraph', + params: t.type({ + path: t.type({ serviceName: t.string }), + query: t.intersection([ + kueryRt, + environmentRt, + t.type({ + transactionName: t.string, + start: isoToEpochSecsRt, + end: isoToEpochSecsRt, + transactionType: t.string, + }), + ]), + }), + options: { tags: ['access:apm'] }, + handler: async (resources): Promise => { + const { context, plugins, params } = resources; + const core = await context.core; + const [esClient, profilingDataAccessStart] = await Promise.all([ + core.elasticsearch.client, + await plugins.profilingDataAccess?.start(), + ]); + if (profilingDataAccessStart) { + const { serviceName } = params.path; + const { + start, + end, + kuery, + transactionName, + transactionType, + environment, + } = params.query; + + return await profilingDataAccessStart?.services.fetchFlamechartData({ + core, + esClient: esClient.asCurrentUser, + // TODO: caue fix this + indices: '.ds-traces-apm-default-2024.02.02-000001', + stacktraceIdsField: 'transaction.profiler_stack_trace_ids', + totalSeconds: end - start, + query: { + bool: { + filter: [ + ...kqlQuery(kuery), + ...termQuery(SERVICE_NAME, serviceName), + ...termQuery(TRANSACTION_NAME, transactionName), + ...environmentQuery(environment), + ...termQuery(TRANSACTION_TYPE, transactionType), + { + range: { + ['@timestamp']: { + gte: String(start), + lt: String(end), + format: 'epoch_second', + }, + }, + }, + ], + }, + }, + }); + } + + return undefined; + }, +}); + const transactionsFunctionsRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/services/{serviceName}/transactions/functions', params: t.type({ path: t.type({ serviceName: t.string }), query: t.intersection([ - rangeRt, + environmentRt, t.type({ + start: isoToEpochSecsRt, + end: isoToEpochSecsRt, startIndex: toNumberRt, endIndex: toNumberRt, transactionName: t.string, + transactionType: t.string, }), kueryRt, ]), @@ -259,20 +294,47 @@ const transactionsFunctionsRoute = createApmServerRoute({ await plugins.profilingDataAccess?.start(), ]); if (profilingDataAccessStart) { - const { start, end, startIndex, endIndex, kuery } = params.query; + const { + start, + end, + startIndex, + endIndex, + kuery, + transactionName, + transactionType, + environment, + } = params.query; const { serviceName } = params.path; return profilingDataAccessStart?.services.fetchFunction({ core, esClient: esClient.asCurrentUser, - rangeFromMs: start, - rangeToMs: end, - kuery, startIndex, endIndex, // TODO: caue fix this indices: '.ds-traces-apm-default-2024.02.02-000001', stacktraceIdsField: 'transaction.profiler_stack_trace_ids', + totalSeconds: end - start, + query: { + bool: { + filter: [ + ...kqlQuery(kuery), + ...termQuery(SERVICE_NAME, serviceName), + ...termQuery(TRANSACTION_NAME, transactionName), + ...environmentQuery(environment), + ...termQuery(TRANSACTION_TYPE, transactionType), + { + range: { + ['@timestamp']: { + gte: String(start), + lt: String(end), + format: 'epoch_second', + }, + }, + }, + ], + }, + }, }); } diff --git a/x-pack/plugins/infra/server/routes/profiling/lib/fetch_profiling_functions.ts b/x-pack/plugins/infra/server/routes/profiling/lib/fetch_profiling_functions.ts index fb78075ca3545..fdf2399be4faa 100644 --- a/x-pack/plugins/infra/server/routes/profiling/lib/fetch_profiling_functions.ts +++ b/x-pack/plugins/infra/server/routes/profiling/lib/fetch_profiling_functions.ts @@ -8,6 +8,7 @@ import type { CoreRequestHandlerContext } from '@kbn/core-http-request-handler-context-server'; import type { ProfilingDataAccessPluginStart } from '@kbn/profiling-data-access-plugin/server'; import type { TopNFunctions } from '@kbn/profiling-utils'; +import { kqlQuery } from '@kbn/observability-plugin/server'; import type { InfraProfilingFunctionsRequestParams } from '../../../../common/http_api/profiling_api'; export async function fetchProfilingFunctions( @@ -16,14 +17,30 @@ export async function fetchProfilingFunctions( coreRequestContext: CoreRequestHandlerContext ): Promise { const { kuery, from, to, startIndex, endIndex } = params; + const startSecs = from / 1000; + const endSecs = to / 1000; return await profilingDataAccess.services.fetchFunction({ core: coreRequestContext, esClient: coreRequestContext.elasticsearch.client.asCurrentUser, - rangeFromMs: from, - rangeToMs: to, - kuery, startIndex, endIndex, + totalSeconds: endSecs - startSecs, + query: { + bool: { + filter: [ + ...kqlQuery(kuery), + { + range: { + ['@timestamp']: { + gte: String(startSecs), + lt: String(endSecs), + format: 'epoch_second', + }, + }, + }, + ], + }, + }, }); } diff --git a/x-pack/plugins/profiling/server/routes/flamechart.ts b/x-pack/plugins/profiling/server/routes/flamechart.ts index ac8d988e5f0ca..86d384f62f609 100644 --- a/x-pack/plugins/profiling/server/routes/flamechart.ts +++ b/x-pack/plugins/profiling/server/routes/flamechart.ts @@ -6,6 +6,7 @@ */ import { schema } from '@kbn/config-schema'; +import { kqlQuery } from '@kbn/observability-plugin/server'; import { IDLE_SOCKET_TIMEOUT, RouteRegisterParameters } from '.'; import { getRoutePaths } from '../../common'; import { handleRouteHandlerError } from '../utils/handle_route_error_handler'; @@ -35,15 +36,31 @@ export function registerFlameChartSearchRoute({ const { timeFrom, timeTo, kuery } = request.query; const core = await context.core; + const startSecs = timeFrom / 1000; + const endSecs = timeTo / 1000; try { const esClient = await getClient(context); const flamegraph = await profilingDataAccess.services.fetchFlamechartData({ core, esClient, - rangeFromMs: timeFrom, - rangeToMs: timeTo, - kuery, + totalSeconds: endSecs - startSecs, + query: { + bool: { + filter: [ + ...kqlQuery(kuery), + { + range: { + ['@timestamp']: { + gte: String(startSecs), + lt: String(endSecs), + format: 'epoch_second', + }, + }, + }, + ], + }, + }, }); return response.ok({ body: flamegraph }); diff --git a/x-pack/plugins/profiling/server/routes/functions.ts b/x-pack/plugins/profiling/server/routes/functions.ts index ca118cc54a81b..a261708c5b457 100644 --- a/x-pack/plugins/profiling/server/routes/functions.ts +++ b/x-pack/plugins/profiling/server/routes/functions.ts @@ -6,6 +6,7 @@ */ import { schema, TypeOf } from '@kbn/config-schema'; +import { kqlQuery } from '@kbn/observability-plugin/server'; import { IDLE_SOCKET_TIMEOUT, RouteRegisterParameters } from '.'; import { getRoutePaths } from '../../common'; import { handleRouteHandlerError } from '../utils/handle_route_error_handler'; @@ -40,15 +41,32 @@ export function registerTopNFunctionsSearchRoute({ const core = await context.core; const { timeFrom, timeTo, startIndex, endIndex, kuery }: QuerySchemaType = request.query; + const startSecs = timeFrom / 1000; + const endSecs = timeTo / 1000; + const esClient = await getClient(context); const topNFunctions = await profilingDataAccess.services.fetchFunction({ core, esClient, - rangeFromMs: timeFrom, - rangeToMs: timeTo, - kuery, startIndex, endIndex, + totalSeconds: endSecs - startSecs, + query: { + bool: { + filter: [ + ...kqlQuery(kuery), + { + range: { + ['@timestamp']: { + gte: String(startSecs), + lt: String(endSecs), + format: 'epoch_second', + }, + }, + }, + ], + }, + }, }); return response.ok({ diff --git a/x-pack/plugins/profiling_data_access/server/services/functions/index.ts b/x-pack/plugins/profiling_data_access/server/services/functions/index.ts index b08d920a36aac..860315b1d0990 100644 --- a/x-pack/plugins/profiling_data_access/server/services/functions/index.ts +++ b/x-pack/plugins/profiling_data_access/server/services/functions/index.ts @@ -14,6 +14,7 @@ import { } from '@kbn/observability-plugin/common'; import { CoreRequestHandlerContext, ElasticsearchClient } from '@kbn/core/server'; import { createTopNFunctions } from '@kbn/profiling-utils'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { percentToFactor } from '../../utils/percent_to_factor'; import { withProfilingSpan } from '../../utils/with_profiling_span'; import { RegisterServicesParams } from '../register_services'; @@ -22,13 +23,12 @@ import { searchStackTraces } from '../search_stack_traces'; export interface FetchFunctionsParams { core: CoreRequestHandlerContext; esClient: ElasticsearchClient; - rangeFromMs: number; - rangeToMs: number; - kuery: string; startIndex: number; endIndex: number; indices?: string; stacktraceIdsField?: string; + query: QueryDslQueryContainer; + totalSeconds: number; } const targetSampleSize = 20000; // minimum number of samples to get statistically sound results @@ -37,18 +37,13 @@ export function createFetchFunctions({ createProfilingEsClient }: RegisterServic return async ({ core, esClient, - rangeFromMs, - rangeToMs, - kuery, startIndex, endIndex, indices, stacktraceIdsField, + query, + totalSeconds, }: FetchFunctionsParams) => { - const rangeFromSecs = rangeFromMs / 1000; - const rangeToSecs = rangeToMs / 1000; - const totalSeconds = rangeToSecs - rangeFromSecs; - const [ co2PerKWH, datacenterPUE, @@ -70,9 +65,6 @@ export function createFetchFunctions({ createProfilingEsClient }: RegisterServic const { events, stackTraces, executables, stackFrames, samplingRate } = await searchStackTraces( { client: profilingEsClient, - rangeFrom: rangeFromSecs, - rangeTo: rangeToSecs, - kuery, sampleSize: targetSampleSize, durationSeconds: totalSeconds, co2PerKWH, @@ -83,6 +75,7 @@ export function createFetchFunctions({ createProfilingEsClient }: RegisterServic costPervCPUPerHour, indices, stacktraceIdsField, + query, } ); diff --git a/x-pack/plugins/profiling_data_access/server/services/search_stack_traces/index.ts b/x-pack/plugins/profiling_data_access/server/services/search_stack_traces/index.ts index 2b24c7a1071c7..aa3d0e4e62684 100644 --- a/x-pack/plugins/profiling_data_access/server/services/search_stack_traces/index.ts +++ b/x-pack/plugins/profiling_data_access/server/services/search_stack_traces/index.ts @@ -6,15 +6,12 @@ */ import { decodeStackTraceResponse } from '@kbn/profiling-utils'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ProfilingESClient } from '../../../common/profiling_es_client'; -import { kqlQuery } from '../../utils/query'; export async function searchStackTraces({ client, sampleSize, - rangeFrom, - rangeTo, - kuery, durationSeconds, co2PerKWH, datacenterPUE, @@ -24,12 +21,10 @@ export async function searchStackTraces({ costPervCPUPerHour, indices, stacktraceIdsField, + query, }: { client: ProfilingESClient; sampleSize: number; - rangeFrom: number; - rangeTo: number; - kuery: string; durationSeconds: number; co2PerKWH: number; datacenterPUE: number; @@ -39,25 +34,10 @@ export async function searchStackTraces({ costPervCPUPerHour: number; indices?: string; stacktraceIdsField?: string; + query: QueryDslQueryContainer; }) { const response = await client.profilingStacktraces({ - query: { - bool: { - filter: [ - ...kqlQuery(kuery), - { - range: { - ['@timestamp']: { - gte: String(rangeFrom), - lt: String(rangeTo), - format: 'epoch_second', - boost: 1.0, - }, - }, - }, - ], - }, - }, + query, sampleSize, durationSeconds, co2PerKWH, From c2ee821bfdfe9ec4d3c996e8343b57112fb83d03 Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Thu, 8 Feb 2024 14:22:56 +0000 Subject: [PATCH 09/17] adding new setting --- .../server/collectors/management/schema.ts | 4 ++++ .../server/collectors/management/types.ts | 1 + .../app/settings/general_settings/index.tsx | 5 ++++- x-pack/plugins/observability/common/index.ts | 1 + .../plugins/observability/common/ui_settings_keys.ts | 1 + x-pack/plugins/observability/server/ui_settings.ts | 12 ++++++++++++ 6 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts index a527feefa754b..5b201d6147b0c 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -568,6 +568,10 @@ export const stackManagementSchema: MakeSchemaFrom = { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, }, + 'observability:apmEnableTransactionProfiling': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, 'observability:profilingPerVCPUWattX86': { type: 'integer', _meta: { description: 'Non-default value of setting.' }, diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts index 6c5945a9f6805..a52e65b48cd8f 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts @@ -165,4 +165,5 @@ export interface UsageStats { 'observability:profilingCostPervCPUPerHour': number; 'observability:profilingAWSCostDiscountRate': number; 'data_views:fields_excluded_data_tiers': string; + 'observability:apmEnableTransactionProfiling': boolean; } diff --git a/x-pack/plugins/apm/public/components/app/settings/general_settings/index.tsx b/x-pack/plugins/apm/public/components/app/settings/general_settings/index.tsx index 114d080fb3a34..28f0396c8e91e 100644 --- a/x-pack/plugins/apm/public/components/app/settings/general_settings/index.tsx +++ b/x-pack/plugins/apm/public/components/app/settings/general_settings/index.tsx @@ -21,6 +21,7 @@ import { enableAgentExplorerView, apmEnableProfilingIntegration, apmEnableTableSearchBar, + apmEnableTransactionProfiling, } from '@kbn/observability-plugin/common'; import { isEmpty } from 'lodash'; import React from 'react'; @@ -58,7 +59,9 @@ function getApmSettingsKeys(isProfilingIntegrationEnabled: boolean) { ]; if (isProfilingIntegrationEnabled) { - keys.push(apmEnableProfilingIntegration); + keys.push( + ...[apmEnableProfilingIntegration, apmEnableTransactionProfiling] + ); } return keys; diff --git a/x-pack/plugins/observability/common/index.ts b/x-pack/plugins/observability/common/index.ts index 106eea543760f..acb3e8b40c82c 100644 --- a/x-pack/plugins/observability/common/index.ts +++ b/x-pack/plugins/observability/common/index.ts @@ -49,6 +49,7 @@ export { profilingPervCPUWattArm64, profilingAWSCostDiscountRate, profilingCostPervCPUPerHour, + apmEnableTransactionProfiling, } from './ui_settings_keys'; export { diff --git a/x-pack/plugins/observability/common/ui_settings_keys.ts b/x-pack/plugins/observability/common/ui_settings_keys.ts index 028103f56a207..06d370b5ac852 100644 --- a/x-pack/plugins/observability/common/ui_settings_keys.ts +++ b/x-pack/plugins/observability/common/ui_settings_keys.ts @@ -36,3 +36,4 @@ export const profilingCo2PerKWH = 'observability:profilingCo2PerKWH'; export const profilingDatacenterPUE = 'observability:profilingDatacenterPUE'; export const profilingAWSCostDiscountRate = 'observability:profilingAWSCostDiscountRate'; export const profilingCostPervCPUPerHour = 'observability:profilingCostPervCPUPerHour'; +export const apmEnableTransactionProfiling = 'observability:apmEnableTransactionProfiling'; diff --git a/x-pack/plugins/observability/server/ui_settings.ts b/x-pack/plugins/observability/server/ui_settings.ts index 0ccd75c9ae3a3..7136bd5913963 100644 --- a/x-pack/plugins/observability/server/ui_settings.ts +++ b/x-pack/plugins/observability/server/ui_settings.ts @@ -38,6 +38,7 @@ import { profilingAWSCostDiscountRate, profilingCostPervCPUPerHour, enableInfrastructureProfilingIntegration, + apmEnableTransactionProfiling, } from '../common/ui_settings_keys'; const betaLabel = i18n.translate('xpack.observability.uiSettings.betaLabel', { @@ -523,6 +524,17 @@ export const uiSettings: Record = { schema: schema.number({ min: 0, max: 100 }), requiresPageReload: true, }, + [apmEnableTransactionProfiling]: { + category: [observabilityFeatureId], + name: i18n.translate('xpack.observability.apmEnableTransactionProfiling', { + defaultMessage: 'Enable Universal Profiling on Transactions view', + }), + value: false, + description: i18n.translate('xpack.observability.apmEnableTransactionProfilingDescription', { + defaultMessage: 'TBD', + }), + schema: schema.boolean(), + }, }; function throttlingDocsLink({ href }: { href: string }) { From 7093d78a7648bad725c0c80ab0f75b633efe11b9 Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Thu, 8 Feb 2024 14:58:54 +0000 Subject: [PATCH 10/17] hidding tab when setting is off --- .../transaction_details_tabs.tsx | 30 ++++++++++++------- .../use_profiling_integration_setting.ts | 17 ++++++++++- .../observability/server/ui_settings.ts | 1 + 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx index 3f2ff0dd10076..56511f94fb38d 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { XYBrushEvent } from '@elastic/charts'; import { EuiPanel, EuiSpacer, EuiTab, EuiTabs } from '@elastic/eui'; @@ -27,6 +27,7 @@ import { failedTransactionsCorrelationsTab } from './failed_transactions_correla import { latencyCorrelationsTab } from './latency_correlations_tab'; import { profilingTab } from './profiling_tab'; import { traceSamplesTab } from './trace_samples_tab'; +import { useTransactionProfilingSetting } from '../../../hooks/use_profiling_integration_setting'; export interface TabContentProps { clearChartSelection: () => void; @@ -37,13 +38,6 @@ export interface TabContentProps { traceSamplesFetchResult: TraceSamplesFetchResult; } -const tabs = [ - traceSamplesTab, - latencyCorrelationsTab, - failedTransactionsCorrelationsTab, - profilingTab, -]; - export function TransactionDetailsTabs() { const { query } = useAnyOfApmParams( '/services/{serviceName}/transactions/view', @@ -51,10 +45,24 @@ export function TransactionDetailsTabs() { ); const isCriticalPathFeatureEnabled = useCriticalPathFeatureEnabledSetting(); + const isTransactionProfilingEnabled = useTransactionProfilingSetting(); + + const availableTabs = useMemo(() => { + const tabs = [ + traceSamplesTab, + latencyCorrelationsTab, + failedTransactionsCorrelationsTab, + ]; + if (isCriticalPathFeatureEnabled) { + tabs.push(aggregatedCriticalPathTab); + } + + if (isTransactionProfilingEnabled) { + tabs.push(profilingTab); + } - const availableTabs = isCriticalPathFeatureEnabled - ? tabs.concat(aggregatedCriticalPathTab) - : tabs; + return tabs; + }, [isCriticalPathFeatureEnabled, isTransactionProfilingEnabled]); const { urlParams } = useLegacyUrlParams(); const history = useHistory(); diff --git a/x-pack/plugins/apm/public/hooks/use_profiling_integration_setting.ts b/x-pack/plugins/apm/public/hooks/use_profiling_integration_setting.ts index 1bf19e1043e91..bb35b8db6e451 100644 --- a/x-pack/plugins/apm/public/hooks/use_profiling_integration_setting.ts +++ b/x-pack/plugins/apm/public/hooks/use_profiling_integration_setting.ts @@ -6,8 +6,12 @@ */ import { useUiSetting } from '@kbn/kibana-react-plugin/public'; -import { apmEnableProfilingIntegration } from '@kbn/observability-plugin/common'; +import { + apmEnableProfilingIntegration, + apmEnableTransactionProfiling, +} from '@kbn/observability-plugin/common'; import { ApmFeatureFlagName } from '../../common/apm_feature_flags'; +import { useApmPluginContext } from '../context/apm_plugin/use_apm_plugin_context'; import { useApmFeatureFlag } from './use_apm_feature_flag'; export function useProfilingIntegrationSetting() { @@ -23,3 +27,14 @@ export function useProfilingIntegrationSetting() { isProfilingIntegrationUiSettingEnabled ); } + +export function useTransactionProfilingSetting() { + const { core } = useApmPluginContext(); + const isProfilingIntegrationEnabled = useProfilingIntegrationSetting(); + + const isTransactionProfilingEnabled = core.uiSettings.get( + apmEnableTransactionProfiling + ); + + return isProfilingIntegrationEnabled && isTransactionProfilingEnabled; +} diff --git a/x-pack/plugins/observability/server/ui_settings.ts b/x-pack/plugins/observability/server/ui_settings.ts index 7136bd5913963..825d098faebae 100644 --- a/x-pack/plugins/observability/server/ui_settings.ts +++ b/x-pack/plugins/observability/server/ui_settings.ts @@ -534,6 +534,7 @@ export const uiSettings: Record = { defaultMessage: 'TBD', }), schema: schema.boolean(), + requiresPageReload: true, }, }; From 5162d3301d1c6e21d4d555ef47b47e32d78400b0 Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Thu, 8 Feb 2024 15:06:20 +0000 Subject: [PATCH 11/17] setting name --- x-pack/plugins/observability/server/ui_settings.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/x-pack/plugins/observability/server/ui_settings.ts b/x-pack/plugins/observability/server/ui_settings.ts index 825d098faebae..c0807b38381c9 100644 --- a/x-pack/plugins/observability/server/ui_settings.ts +++ b/x-pack/plugins/observability/server/ui_settings.ts @@ -527,12 +527,9 @@ export const uiSettings: Record = { [apmEnableTransactionProfiling]: { category: [observabilityFeatureId], name: i18n.translate('xpack.observability.apmEnableTransactionProfiling', { - defaultMessage: 'Enable Universal Profiling on Transactions view', + defaultMessage: 'Enable Universal Profiling on Transaction view', }), value: false, - description: i18n.translate('xpack.observability.apmEnableTransactionProfilingDescription', { - defaultMessage: 'TBD', - }), schema: schema.boolean(), requiresPageReload: true, }, From 7220618704d798399c403584eb248dad46f63dcf Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Thu, 8 Feb 2024 16:04:28 +0000 Subject: [PATCH 12/17] empty state --- .../app/transaction_details/profiling_tab.tsx | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx index e3871539f2037..aed03162c5bc8 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx @@ -5,13 +5,17 @@ * 2.0. */ import { + EuiLoadingSpinner, EuiSpacer, EuiTabbedContent, EuiTabbedContentProps, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useMemo } from 'react'; +import { css } from '@emotion/react'; +import { ProfilingEmptyState } from '@kbn/observability-shared-plugin/public'; import { useApmParams } from '../../../hooks/use_apm_params'; +import { useProfilingPlugin } from '../../../hooks/use_profiling_plugin'; import { ProfilingFlamegraph } from './profiling_flamegraph'; import { ProfilingTopNFunctions } from './profiling_top_functions'; @@ -27,6 +31,7 @@ function ProfilingTab() { }, path: { serviceName }, } = useApmParams('/services/{serviceName}/transactions/view'); + const { isProfilingAvailable, isLoading } = useProfilingPlugin(); const tabs = useMemo((): EuiTabbedContentProps['tabs'] => { return [ @@ -83,6 +88,23 @@ function ProfilingTab() { transactionType, ]); + if (isLoading) { + return ( +
+ +
+ ); + } + + if (isProfilingAvailable === false) { + return ; + } + return ( Date: Thu, 8 Feb 2024 16:56:04 +0000 Subject: [PATCH 13/17] ci --- src/plugins/telemetry/schema/oss_plugins.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index 23239ab0b0ca8..073275112b04a 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -10168,6 +10168,12 @@ "description": "Non-default value of setting." } }, + "observability:apmEnableTransactionProfiling": { + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } + }, "observability:profilingPerVCPUWattX86": { "type": "integer", "_meta": { From a24fbcc0189ddcdeb94470ec6c43576076b7e890 Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Fri, 9 Feb 2024 16:14:27 +0000 Subject: [PATCH 14/17] some fixes --- x-pack/plugins/apm/common/es_fields/apm.ts | 2 + .../create_apm_event_client/index.ts | 4 ++ .../apm/server/routes/profiling/route.ts | 45 +++++++++++++------ .../common/profiling_es_client.ts | 4 +- .../server/services/fetch_flamechart/index.ts | 2 +- .../server/services/functions/index.ts | 2 +- .../services/search_stack_traces/index.ts | 2 +- 7 files changed, 42 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/apm/common/es_fields/apm.ts b/x-pack/plugins/apm/common/es_fields/apm.ts index a6cef6ce73e11..05efeceb11f28 100644 --- a/x-pack/plugins/apm/common/es_fields/apm.ts +++ b/x-pack/plugins/apm/common/es_fields/apm.ts @@ -65,6 +65,8 @@ export const TRANSACTION_OVERFLOW_COUNT = 'transaction.aggregation.overflow_count'; // for transaction metrics export const TRANSACTION_ROOT = 'transaction.root'; +export const TRANSACTION_PROFILER_STACK_TRACE_IDS = + 'transaction.profiler_stack_trace_ids'; export const EVENT_OUTCOME = 'event.outcome'; diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts index 53e4c91f384f3..d1dbb3a8e6c9c 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts @@ -342,4 +342,8 @@ export class APMEventClient { cb: (opts) => this.esClient.termsEnum(requestParams, opts), }); } + + getIndexFromProcessorEvent(processorEvent: ProcessorEvent) { + return processorEventsToIndex([processorEvent], this.indices); + } } diff --git a/x-pack/plugins/apm/server/routes/profiling/route.ts b/x-pack/plugins/apm/server/routes/profiling/route.ts index f05ba6064fb39..17f2005588a2a 100644 --- a/x-pack/plugins/apm/server/routes/profiling/route.ts +++ b/x-pack/plugins/apm/server/routes/profiling/route.ts @@ -9,10 +9,12 @@ import { isoToEpochSecsRt, toNumberRt } from '@kbn/io-ts-utils'; import type { BaseFlameGraph, TopNFunctions } from '@kbn/profiling-utils'; import * as t from 'io-ts'; import { kqlQuery, termQuery } from '@kbn/observability-plugin/server'; +import { ProcessorEvent } from '@kbn/observability-plugin/common'; import { HOST_NAME, SERVICE_NAME, TRANSACTION_NAME, + TRANSACTION_PROFILER_STACK_TRACE_IDS, TRANSACTION_TYPE, } from '../../../common/es_fields/apm'; import { @@ -219,10 +221,12 @@ const transactionsFlamegraphRoute = createApmServerRoute({ handler: async (resources): Promise => { const { context, plugins, params } = resources; const core = await context.core; - const [esClient, profilingDataAccessStart] = await Promise.all([ - core.elasticsearch.client, - await plugins.profilingDataAccess?.start(), - ]); + const [esClient, profilingDataAccessStart, apmEventClient] = + await Promise.all([ + core.elasticsearch.client, + await plugins.profilingDataAccess?.start(), + getApmEventClient(resources), + ]); if (profilingDataAccessStart) { const { serviceName } = params.path; const { @@ -234,12 +238,17 @@ const transactionsFlamegraphRoute = createApmServerRoute({ environment, } = params.query; + // TODO: This will be used once the ES bug is fixed + const indices = apmEventClient.getIndexFromProcessorEvent( + ProcessorEvent.transaction + ); + console.log('### caue handler: index:', indices); + return await profilingDataAccessStart?.services.fetchFlamechartData({ core, esClient: esClient.asCurrentUser, - // TODO: caue fix this - indices: '.ds-traces-apm-default-2024.02.02-000001', - stacktraceIdsField: 'transaction.profiler_stack_trace_ids', + indices: ['traces-apm-default'], + stacktraceIdsField: TRANSACTION_PROFILER_STACK_TRACE_IDS, totalSeconds: end - start, query: { bool: { @@ -289,10 +298,13 @@ const transactionsFunctionsRoute = createApmServerRoute({ handler: async (resources): Promise => { const { context, plugins, params } = resources; const core = await context.core; - const [esClient, profilingDataAccessStart] = await Promise.all([ - core.elasticsearch.client, - await plugins.profilingDataAccess?.start(), - ]); + + const [esClient, profilingDataAccessStart, apmEventClient] = + await Promise.all([ + core.elasticsearch.client, + await plugins.profilingDataAccess?.start(), + getApmEventClient(resources), + ]); if (profilingDataAccessStart) { const { start, @@ -306,14 +318,19 @@ const transactionsFunctionsRoute = createApmServerRoute({ } = params.query; const { serviceName } = params.path; + // TODO: This will be used once the ES bug is fixed + const indices = apmEventClient.getIndexFromProcessorEvent( + ProcessorEvent.transaction + ); + console.log('### caue handler: index:', indices); + return profilingDataAccessStart?.services.fetchFunction({ core, esClient: esClient.asCurrentUser, startIndex, endIndex, - // TODO: caue fix this - indices: '.ds-traces-apm-default-2024.02.02-000001', - stacktraceIdsField: 'transaction.profiler_stack_trace_ids', + indices: ['traces-apm-default'], + stacktraceIdsField: TRANSACTION_PROFILER_STACK_TRACE_IDS, totalSeconds: end - start, query: { bool: { diff --git a/x-pack/plugins/profiling_data_access/common/profiling_es_client.ts b/x-pack/plugins/profiling_data_access/common/profiling_es_client.ts index c8316fecf4c96..4fdaef437c64f 100644 --- a/x-pack/plugins/profiling_data_access/common/profiling_es_client.ts +++ b/x-pack/plugins/profiling_data_access/common/profiling_es_client.ts @@ -29,7 +29,7 @@ export interface ProfilingESClient { pervCPUWattArm64?: number; awsCostDiscountRate?: number; costPervCPUPerHour?: number; - indices?: string; + indices?: string[]; stacktraceIdsField?: string; }): Promise; profilingStatus(params?: { waitForResourcesCreated?: boolean }): Promise; @@ -44,7 +44,7 @@ export interface ProfilingESClient { pervCPUWattArm64?: number; awsCostDiscountRate?: number; costPervCPUPerHour?: number; - indices?: string; + indices?: string[]; stacktraceIdsField?: string; }): Promise; } diff --git a/x-pack/plugins/profiling_data_access/server/services/fetch_flamechart/index.ts b/x-pack/plugins/profiling_data_access/server/services/fetch_flamechart/index.ts index d7d19f8573a65..46b288c5ea361 100644 --- a/x-pack/plugins/profiling_data_access/server/services/fetch_flamechart/index.ts +++ b/x-pack/plugins/profiling_data_access/server/services/fetch_flamechart/index.ts @@ -20,7 +20,7 @@ import { RegisterServicesParams } from '../register_services'; export interface FetchFlamechartParams { esClient: ElasticsearchClient; core: CoreRequestHandlerContext; - indices?: string; + indices?: string[]; stacktraceIdsField?: string; query: QueryDslQueryContainer; totalSeconds: number; diff --git a/x-pack/plugins/profiling_data_access/server/services/functions/index.ts b/x-pack/plugins/profiling_data_access/server/services/functions/index.ts index 860315b1d0990..5fee6c9ae660a 100644 --- a/x-pack/plugins/profiling_data_access/server/services/functions/index.ts +++ b/x-pack/plugins/profiling_data_access/server/services/functions/index.ts @@ -25,7 +25,7 @@ export interface FetchFunctionsParams { esClient: ElasticsearchClient; startIndex: number; endIndex: number; - indices?: string; + indices?: string[]; stacktraceIdsField?: string; query: QueryDslQueryContainer; totalSeconds: number; diff --git a/x-pack/plugins/profiling_data_access/server/services/search_stack_traces/index.ts b/x-pack/plugins/profiling_data_access/server/services/search_stack_traces/index.ts index aa3d0e4e62684..80eea0299bac1 100644 --- a/x-pack/plugins/profiling_data_access/server/services/search_stack_traces/index.ts +++ b/x-pack/plugins/profiling_data_access/server/services/search_stack_traces/index.ts @@ -32,7 +32,7 @@ export async function searchStackTraces({ pervCPUWattArm64: number; awsCostDiscountRate: number; costPervCPUPerHour: number; - indices?: string; + indices?: string[]; stacktraceIdsField?: string; query: QueryDslQueryContainer; }) { From 3f3e055b8fbaad9f235dfac4ff45b3e41858695e Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Mon, 12 Feb 2024 12:28:50 +0000 Subject: [PATCH 15/17] addressing pr comments --- .../profiling_flamegraph.tsx | 13 +++--- .../profiling_top_functions.tsx | 13 +++--- .../profiling_flamegraph.tsx | 13 +++--- .../app/transaction_details/profiling_tab.tsx | 16 +++---- .../profiling_top_functions.tsx | 13 +++--- .../profiling/flamegraph/flamegraph_link.tsx | 43 +++++++++++++------ .../shared/profiling/flamegraph/index.tsx | 12 +++--- .../top_functions/top_functions_link.tsx | 37 ++++++++++------ .../create_apm_event_client/index.ts | 2 +- .../apm/server/routes/profiling/route.ts | 12 ++---- 10 files changed, 94 insertions(+), 80 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_flamegraph.tsx b/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_flamegraph.tsx index 9edff8d21bb17..2504ce687307b 100644 --- a/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_flamegraph.tsx +++ b/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_flamegraph.tsx @@ -78,13 +78,12 @@ export function ProfilingFlamegraph({ -
- -
+
diff --git a/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_top_functions.tsx b/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_top_functions.tsx index be9ca21f80709..8785a4974a2d3 100644 --- a/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_top_functions.tsx +++ b/x-pack/plugins/apm/public/components/app/profiling_overview/profiling_top_functions.tsx @@ -93,13 +93,12 @@ export function ProfilingTopNFunctions({ -
- -
+
diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_flamegraph.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_flamegraph.tsx index 308ce1473f10a..2f87d2be50214 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_flamegraph.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_flamegraph.tsx @@ -67,13 +67,12 @@ export function ProfilingFlamegraph({ return ( <> -
- -
+ diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx index aed03162c5bc8..1728e214ff8f3 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_tab.tsx @@ -5,6 +5,8 @@ * 2.0. */ import { + EuiFlexGroup, + EuiFlexItem, EuiLoadingSpinner, EuiSpacer, EuiTabbedContent, @@ -12,7 +14,6 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useMemo } from 'react'; -import { css } from '@emotion/react'; import { ProfilingEmptyState } from '@kbn/observability-shared-plugin/public'; import { useApmParams } from '../../../hooks/use_apm_params'; import { useProfilingPlugin } from '../../../hooks/use_profiling_plugin'; @@ -90,14 +91,11 @@ function ProfilingTab() { if (isLoading) { return ( -
- -
+ + + + + ); } diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_top_functions.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_top_functions.tsx index 0f1103e81d550..96ef5f3497346 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/profiling_top_functions.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/profiling_top_functions.tsx @@ -69,13 +69,12 @@ export function ProfilingTopNFunctions({ return ( <> -
- -
+ - {i18n.translate('xpack.apm.profiling.flamegraph.link', { - defaultMessage: 'Go to Universal Profiling Flamegraph', - })} - + + + + {i18n.translate('xpack.apm.profiling.flamegraph.link', { + defaultMessage: 'Go to Universal Profiling Flamegraph', + })} + + + ); } diff --git a/x-pack/plugins/apm/public/components/shared/profiling/flamegraph/index.tsx b/x-pack/plugins/apm/public/components/shared/profiling/flamegraph/index.tsx index bfb49918fb987..cfe92331486a2 100644 --- a/x-pack/plugins/apm/public/components/shared/profiling/flamegraph/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/profiling/flamegraph/index.tsx @@ -33,13 +33,11 @@ export function ProfilingFlamegraphChart({ data, status }: Props) { } /> ) : ( -
- -
+ )} ); diff --git a/x-pack/plugins/apm/public/components/shared/profiling/top_functions/top_functions_link.tsx b/x-pack/plugins/apm/public/components/shared/profiling/top_functions/top_functions_link.tsx index cb7a39646f03a..852abd9a94376 100644 --- a/x-pack/plugins/apm/public/components/shared/profiling/top_functions/top_functions_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/profiling/top_functions/top_functions_link.tsx @@ -5,7 +5,12 @@ * 2.0. */ -import { EuiLink } from '@elastic/eui'; +import { + EuiFlexGroup, + EuiFlexGroupProps, + EuiFlexItem, + EuiLink, +} from '@elastic/eui'; import React from 'react'; import { i18n } from '@kbn/i18n'; import { useProfilingPlugin } from '../../../../hooks/use_profiling_plugin'; @@ -14,27 +19,33 @@ interface Props { kuery: string; rangeFrom: string; rangeTo: string; + justifyContent?: EuiFlexGroupProps['justifyContent']; } export function ProfilingTopNFunctionsLink({ kuery, rangeFrom, rangeTo, + justifyContent = 'flexStart', }: Props) { const { profilingLocators } = useProfilingPlugin(); return ( - - {i18n.translate('xpack.apm.profiling.topnFunctions.link', { - defaultMessage: 'Go to Universal Profiling Functions', - })} - + + + + {i18n.translate('xpack.apm.profiling.topnFunctions.link', { + defaultMessage: 'Go to Universal Profiling Functions', + })} + + + ); } diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts index d1dbb3a8e6c9c..1a180d2adaf14 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts @@ -343,7 +343,7 @@ export class APMEventClient { }); } - getIndexFromProcessorEvent(processorEvent: ProcessorEvent) { + getIndicesFromProcessorEvent(processorEvent: ProcessorEvent) { return processorEventsToIndex([processorEvent], this.indices); } } diff --git a/x-pack/plugins/apm/server/routes/profiling/route.ts b/x-pack/plugins/apm/server/routes/profiling/route.ts index 17f2005588a2a..9009f60da03a1 100644 --- a/x-pack/plugins/apm/server/routes/profiling/route.ts +++ b/x-pack/plugins/apm/server/routes/profiling/route.ts @@ -238,16 +238,14 @@ const transactionsFlamegraphRoute = createApmServerRoute({ environment, } = params.query; - // TODO: This will be used once the ES bug is fixed - const indices = apmEventClient.getIndexFromProcessorEvent( + const indices = apmEventClient.getIndicesFromProcessorEvent( ProcessorEvent.transaction ); - console.log('### caue handler: index:', indices); return await profilingDataAccessStart?.services.fetchFlamechartData({ core, esClient: esClient.asCurrentUser, - indices: ['traces-apm-default'], + indices, stacktraceIdsField: TRANSACTION_PROFILER_STACK_TRACE_IDS, totalSeconds: end - start, query: { @@ -318,18 +316,16 @@ const transactionsFunctionsRoute = createApmServerRoute({ } = params.query; const { serviceName } = params.path; - // TODO: This will be used once the ES bug is fixed - const indices = apmEventClient.getIndexFromProcessorEvent( + const indices = apmEventClient.getIndicesFromProcessorEvent( ProcessorEvent.transaction ); - console.log('### caue handler: index:', indices); return profilingDataAccessStart?.services.fetchFunction({ core, esClient: esClient.asCurrentUser, startIndex, endIndex, - indices: ['traces-apm-default'], + indices, stacktraceIdsField: TRANSACTION_PROFILER_STACK_TRACE_IDS, totalSeconds: end - start, query: { From 280f09cd7f53d2674b260b9a346ca69a55227c9e Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Mon, 12 Feb 2024 12:50:31 +0000 Subject: [PATCH 16/17] adding docs --- docs/management/advanced-options.asciidoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 41e2d6c6bb45a..838eec2521608 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -445,6 +445,9 @@ Determines whether the <> is enable [[observability-apm-enable-infra-view]]`observability:enableInfrastructureView`:: Enables the Infrastructure view in the APM app. +[[observability-apm-enable-transaction-profiling]]`observability:apmEnableTransactionProfiling`:: +Enable Universal Profiling on Transaction view. + [[observability-enable-inspect-es-queries]]`observability:enableInspectEsQueries`:: When enabled, allows you to inspect {es} queries in API responses. From c521634edf69d02cdea4cac568718af58506bc51 Mon Sep 17 00:00:00 2001 From: Caue Marcondes Date: Mon, 12 Feb 2024 14:26:47 +0000 Subject: [PATCH 17/17] fixing test --- .../common/es_fields/__snapshots__/es_fields.test.ts.snap | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/x-pack/plugins/apm/common/es_fields/__snapshots__/es_fields.test.ts.snap b/x-pack/plugins/apm/common/es_fields/__snapshots__/es_fields.test.ts.snap index 0fa795b696455..f313ef593cf04 100644 --- a/x-pack/plugins/apm/common/es_fields/__snapshots__/es_fields.test.ts.snap +++ b/x-pack/plugins/apm/common/es_fields/__snapshots__/es_fields.test.ts.snap @@ -320,6 +320,8 @@ exports[`Error TRANSACTION_OVERFLOW_COUNT 1`] = `undefined`; exports[`Error TRANSACTION_PAGE_URL 1`] = `undefined`; +exports[`Error TRANSACTION_PROFILER_STACK_TRACE_IDS 1`] = `undefined`; + exports[`Error TRANSACTION_RESULT 1`] = `undefined`; exports[`Error TRANSACTION_ROOT 1`] = `undefined`; @@ -645,6 +647,8 @@ exports[`Span TRANSACTION_OVERFLOW_COUNT 1`] = `undefined`; exports[`Span TRANSACTION_PAGE_URL 1`] = `undefined`; +exports[`Span TRANSACTION_PROFILER_STACK_TRACE_IDS 1`] = `undefined`; + exports[`Span TRANSACTION_RESULT 1`] = `undefined`; exports[`Span TRANSACTION_ROOT 1`] = `undefined`; @@ -988,6 +992,8 @@ exports[`Transaction TRANSACTION_OVERFLOW_COUNT 1`] = `undefined`; exports[`Transaction TRANSACTION_PAGE_URL 1`] = `undefined`; +exports[`Transaction TRANSACTION_PROFILER_STACK_TRACE_IDS 1`] = `undefined`; + exports[`Transaction TRANSACTION_RESULT 1`] = `"transaction result"`; exports[`Transaction TRANSACTION_ROOT 1`] = `undefined`;