"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.registerGetApmTimeseriesFunction = registerGetApmTimeseriesFunction; var _eui = require("@elastic/eui"); var _lodash = require("lodash"); var _react = _interopRequireDefault(require("react")); var _i18n = require("@kbn/i18n"); var _public = require("@kbn/kibana-react-plugin/public"); var _use_fetcher = require("../hooks/use_fetcher"); var _create_call_apm_api = require("../services/rest/create_call_apm_api"); var _timezone = require("../components/shared/charts/helper/timezone"); var _timeseries_chart = require("../components/shared/charts/timeseries_chart"); var _chart_pointer_event_context = require("../context/chart_pointer_event/chart_pointer_event_context"); var _app_root = require("../components/routing/app_root"); var _get_timeseries_color = require("../components/shared/charts/helper/get_timeseries_color"); var _latency_aggregation_types = require("../../common/latency_aggregation_types"); var _formatters = require("../../common/utils/formatters"); var _helper = require("../components/shared/charts/transaction_charts/helper"); var _non_empty_string_ref = require("../utils/non_empty_string_ref"); /* * 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. */ function registerGetApmTimeseriesFunction({ registerFunction }) { registerFunction({ contexts: ['apm'], name: 'get_apm_timeseries', descriptionForUser: _i18n.i18n.translate('xpack.apm.observabilityAiAssistant.functions.registerGetApmTimeseries.descriptionForUser', { defaultMessage: `Display different APM metrics, like throughput, failure rate, or latency, for any service or all services, or any or all of its dependencies, both as a timeseries and as a single statistic. Additionally, the function will return any changes, such as spikes, step and trend changes, or dips. You can also use it to compare data by requesting two different time ranges, or for instance two different service versions` }), description: `Visualise and analyse different APM metrics, like throughput, failure rate, or latency, for any service or all services, or any or all of its dependencies, both as a timeseries and as a single statistic. A visualisation will be displayed above your reply - DO NOT attempt to display or generate an image yourself, or any other placeholder. Additionally, the function will return any changes, such as spikes, step and trend changes, or dips. You can also use it to compare data by requesting two different time ranges, or for instance two different service versions.`, parameters: { type: 'object', properties: { start: { type: 'string', description: 'The start of the time range, in Elasticsearch date math, like `now`.' }, end: { type: 'string', description: 'The end of the time range, in Elasticsearch date math, like `now-24h`.' }, stats: { type: 'array', items: { type: 'object', properties: { timeseries: { description: 'The metric to be displayed', oneOf: [{ type: 'object', properties: { name: { type: 'string', enum: ['transaction_throughput', 'transaction_failure_rate'] }, 'transaction.type': { type: 'string', description: 'The transaction type' } }, required: ['name'] }, { type: 'object', properties: { name: { type: 'string', enum: ['exit_span_throughput', 'exit_span_failure_rate', 'exit_span_latency'] }, 'span.destination.service.resource': { type: 'string', description: 'The name of the downstream dependency for the service' } }, required: ['name'] }, { type: 'object', properties: { name: { type: 'string', const: 'error_event_rate' } }, required: ['name'] }, { type: 'object', properties: { name: { type: 'string', const: 'transaction_latency' }, 'transaction.type': { type: 'string' }, function: { type: 'string', enum: ['avg', 'p95', 'p99'] } }, required: ['name', 'function'] }] }, 'service.name': { ..._non_empty_string_ref.NON_EMPTY_STRING, description: 'The name of the service' }, 'service.environment': { description: 'The environment that the service is running in. If undefined, all environments will be included. Only use this if you have confirmed the environment that the service is running in.' }, filter: { type: 'string', description: 'a KQL query to filter the data by. If no filter should be applied, leave it empty.' }, title: { type: 'string', description: 'A unique, human readable, concise title for this specific group series.' }, offset: { type: 'string', description: 'The offset. Right: 15m. 8h. 1d. Wrong: -15m. -8h. -1d.' } }, required: ['service.name', 'timeseries', 'title'] } } }, required: ['stats', 'start', 'end'] } }, async ({ arguments: { stats, start, end } }, signal) => { const response = await (0, _create_call_apm_api.callApmApi)('POST /internal/apm/assistant/get_apm_timeseries', { signal, params: { body: { stats: stats, start, end } } }); return response; }, ({ arguments: args, response }) => { const groupedSeries = (0, _lodash.groupBy)(response.data, series => series.group); const { services: { uiSettings } } = (0, _public.useKibana)(); const timeZone = (0, _timezone.getTimeZone)(uiSettings); return /*#__PURE__*/_react.default.createElement(_chart_pointer_event_context.ChartPointerEventContextProvider, null, /*#__PURE__*/_react.default.createElement(_app_root.ApmThemeProvider, null, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { direction: "column" }, Object.values(groupedSeries).map(groupSeries => { const groupId = groupSeries[0].group; const maxY = (0, _helper.getMaxY)(groupSeries); const latencyFormatter = (0, _formatters.getDurationFormatter)(maxY, 10, 1000); let yLabelFormat; const firstStat = groupSeries[0].stat; switch (firstStat.timeseries.name) { case 'transaction_throughput': case 'exit_span_throughput': case 'error_event_rate': yLabelFormat = _formatters.asTransactionRate; break; case 'transaction_latency': case 'exit_span_latency': yLabelFormat = (0, _helper.getResponseTimeTickFormatter)(latencyFormatter); break; case 'transaction_failure_rate': case 'exit_span_failure_rate': yLabelFormat = y => (0, _formatters.asPercent)(y || 0, 100); break; } const timeseries = groupSeries.map(series => { let chartType; const data = series.data; switch (series.stat.timeseries.name) { case 'transaction_throughput': case 'exit_span_throughput': chartType = _get_timeseries_color.ChartType.THROUGHPUT; break; case 'transaction_failure_rate': case 'exit_span_failure_rate': chartType = _get_timeseries_color.ChartType.FAILED_TRANSACTION_RATE; break; case 'transaction_latency': if (series.stat.timeseries.function === _latency_aggregation_types.LatencyAggregationType.p99) { chartType = _get_timeseries_color.ChartType.LATENCY_P99; } else if (series.stat.timeseries.function === _latency_aggregation_types.LatencyAggregationType.p95) { chartType = _get_timeseries_color.ChartType.LATENCY_P95; } else { chartType = _get_timeseries_color.ChartType.LATENCY_AVG; } break; case 'exit_span_latency': chartType = _get_timeseries_color.ChartType.LATENCY_AVG; break; case 'error_event_rate': chartType = _get_timeseries_color.ChartType.ERROR_OCCURRENCES; break; } return { title: series.id, type: 'line', color: (0, _get_timeseries_color.getTimeSeriesColor)(chartType).currentPeriodColor, data }; }); return /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false, key: groupId }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { direction: "column", gutterSize: "s" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiText, { size: "m" }, groupId), /*#__PURE__*/_react.default.createElement(_timeseries_chart.TimeseriesChart, { comparisonEnabled: false, fetchStatus: _use_fetcher.FETCH_STATUS.SUCCESS, id: groupId, timeZone: timeZone, timeseries: timeseries, yLabelFormat: yLabelFormat })))); })))); }); }