diff --git a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_detail_dependencies_table.tsx b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_detail_dependencies_table.tsx index 2fb9d91becf669..ee71e4d8c8674d 100644 --- a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_detail_dependencies_table.tsx +++ b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_detail_dependencies_table.tsx @@ -9,7 +9,6 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { getNodeName, NodeType } from '../../../../common/connections'; import { useApmParams } from '../../../hooks/use_apm_params'; -import { useLegacyUrlParams } from '../../../context/url_params_context/use_url_params'; import { useFetcher } from '../../../hooks/use_fetcher'; import { getTimeRangeComparison } from '../../shared/time_comparison/get_time_range_comparison'; import { DependenciesTable } from '../../shared/dependencies_table'; @@ -18,11 +17,15 @@ import { useTimeRange } from '../../../hooks/use_time_range'; export function BackendDetailDependenciesTable() { const { - urlParams: { comparisonEnabled, comparisonType }, - } = useLegacyUrlParams(); - - const { - query: { backendName, rangeFrom, rangeTo, kuery, environment }, + query: { + backendName, + rangeFrom, + rangeTo, + kuery, + environment, + comparisonEnabled, + comparisonType, + }, } = useApmParams('/backends/overview'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); diff --git a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_error_rate_chart.tsx b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_error_rate_chart.tsx index 9fb53ab15d374f..5ecb41829f06c4 100644 --- a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_error_rate_chart.tsx +++ b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_error_rate_chart.tsx @@ -7,7 +7,6 @@ import React, { useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { asPercent } from '../../../../common/utils/formatters'; -import { useComparison } from '../../../hooks/use_comparison'; import { useFetcher } from '../../../hooks/use_fetcher'; import { useTimeRange } from '../../../hooks/use_time_range'; import { Coordinate, TimeSeries } from '../../../../typings/timeseries'; @@ -17,6 +16,10 @@ import { ChartType, getTimeSeriesColor, } from '../../shared/charts/helper/get_timeseries_color'; +import { + getComparisonChartTheme, + getTimeRangeComparison, +} from '../../shared/time_comparison/get_time_range_comparison'; function yLabelFormat(y?: number | null) { return asPercent(y || 0, 1); @@ -28,12 +31,26 @@ export function BackendFailedTransactionRateChart({ height: number; }) { const { - query: { backendName, kuery, environment, rangeFrom, rangeTo }, + query: { + backendName, + kuery, + environment, + rangeFrom, + rangeTo, + comparisonEnabled, + comparisonType, + }, } = useApmParams('/backends/overview'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - const { offset, comparisonChartTheme } = useComparison(); + const comparisonChartTheme = getComparisonChartTheme(); + const { offset } = getTimeRangeComparison({ + start, + end, + comparisonType, + comparisonEnabled, + }); const { data, status } = useFetcher( (callApmApi) => { diff --git a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_latency_chart.tsx b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_latency_chart.tsx index 9d95b58fe24de4..8289ac01b7b27d 100644 --- a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_latency_chart.tsx +++ b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_latency_chart.tsx @@ -7,7 +7,6 @@ import React, { useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { getDurationFormatter } from '../../../../common/utils/formatters'; -import { useComparison } from '../../../hooks/use_comparison'; import { useFetcher } from '../../../hooks/use_fetcher'; import { useTimeRange } from '../../../hooks/use_time_range'; import { Coordinate, TimeSeries } from '../../../../typings/timeseries'; @@ -21,15 +20,33 @@ import { ChartType, getTimeSeriesColor, } from '../../shared/charts/helper/get_timeseries_color'; +import { + getComparisonChartTheme, + getTimeRangeComparison, +} from '../../shared/time_comparison/get_time_range_comparison'; export function BackendLatencyChart({ height }: { height: number }) { const { - query: { backendName, rangeFrom, rangeTo, kuery, environment }, + query: { + backendName, + rangeFrom, + rangeTo, + kuery, + environment, + comparisonEnabled, + comparisonType, + }, } = useApmParams('/backends/overview'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - const { offset, comparisonChartTheme } = useComparison(); + const comparisonChartTheme = getComparisonChartTheme(); + const { offset } = getTimeRangeComparison({ + start, + end, + comparisonType, + comparisonEnabled, + }); const { data, status } = useFetcher( (callApmApi) => { diff --git a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_throughput_chart.tsx b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_throughput_chart.tsx index c293561f780b10..c8a37146d60a49 100644 --- a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_throughput_chart.tsx +++ b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_throughput_chart.tsx @@ -7,7 +7,6 @@ import React, { useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { asTransactionRate } from '../../../../common/utils/formatters'; -import { useComparison } from '../../../hooks/use_comparison'; import { useFetcher } from '../../../hooks/use_fetcher'; import { useTimeRange } from '../../../hooks/use_time_range'; import { Coordinate, TimeSeries } from '../../../../typings/timeseries'; @@ -17,15 +16,33 @@ import { ChartType, getTimeSeriesColor, } from '../../shared/charts/helper/get_timeseries_color'; +import { + getComparisonChartTheme, + getTimeRangeComparison, +} from '../../shared/time_comparison/get_time_range_comparison'; export function BackendThroughputChart({ height }: { height: number }) { const { - query: { backendName, rangeFrom, rangeTo, kuery, environment }, + query: { + backendName, + rangeFrom, + rangeTo, + kuery, + environment, + comparisonEnabled, + comparisonType, + }, } = useApmParams('/backends/overview'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - const { offset, comparisonChartTheme } = useComparison(); + const comparisonChartTheme = getComparisonChartTheme(); + const { offset } = getTimeRangeComparison({ + start, + end, + comparisonType, + comparisonEnabled, + }); const { data, status } = useFetcher( (callApmApi) => { diff --git a/x-pack/plugins/apm/public/components/app/backend_inventory/backend_inventory_dependencies_table/index.tsx b/x-pack/plugins/apm/public/components/app/backend_inventory/backend_inventory_dependencies_table/index.tsx index 71970e00f6d263..fa7cf4a3ba2421 100644 --- a/x-pack/plugins/apm/public/components/app/backend_inventory/backend_inventory_dependencies_table/index.tsx +++ b/x-pack/plugins/apm/public/components/app/backend_inventory/backend_inventory_dependencies_table/index.tsx @@ -10,7 +10,6 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { useUiTracker } from '../../../../../../observability/public'; import { getNodeName, NodeType } from '../../../../../common/connections'; -import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; import { useApmParams } from '../../../../hooks/use_apm_params'; import { useFetcher } from '../../../../hooks/use_fetcher'; import { useTimeRange } from '../../../../hooks/use_time_range'; @@ -20,11 +19,14 @@ import { getTimeRangeComparison } from '../../../shared/time_comparison/get_time export function BackendInventoryDependenciesTable() { const { - urlParams: { comparisonEnabled, comparisonType }, - } = useLegacyUrlParams(); - - const { - query: { rangeFrom, rangeTo, environment, kuery }, + query: { + rangeFrom, + rangeTo, + environment, + kuery, + comparisonEnabled, + comparisonType, + }, } = useApmParams('/backends'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx b/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx index 46b963d13e5106..7d90ee6824de95 100644 --- a/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx @@ -68,7 +68,6 @@ export function ErrorGroupOverview() { comparisonType, comparisonEnabled, }); - const { errorDistributionData, status } = useErrorGroupDistributionFetcher({ serviceName, groupId: undefined, diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx index 024e83a3c9883a..c26ae5a273b4ee 100644 --- a/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx @@ -10,16 +10,15 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import uuid from 'uuid'; import { useAnomalyDetectionJobsContext } from '../../../context/anomaly_detection_jobs/use_anomaly_detection_jobs_context'; -import { useLegacyUrlParams } from '../../../context/url_params_context/use_url_params'; import { useLocalStorage } from '../../../hooks/use_local_storage'; import { useApmParams } from '../../../hooks/use_apm_params'; import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher'; import { useTimeRange } from '../../../hooks/use_time_range'; import { SearchBar } from '../../shared/search_bar'; -import { getTimeRangeComparison } from '../../shared/time_comparison/get_time_range_comparison'; import { ServiceList } from './service_list'; import { MLCallout, shouldDisplayMlCallout } from '../../shared/ml_callout'; import { joinByKey } from '../../../../common/utils/join_by_key'; +import { getTimeRangeComparison } from '../../shared/time_comparison/get_time_range_comparison'; const initialData = { requestId: '', @@ -30,11 +29,15 @@ const initialData = { function useServicesFetcher() { const { - urlParams: { comparisonEnabled, comparisonType }, - } = useLegacyUrlParams(); - - const { - query: { rangeFrom, rangeTo, environment, kuery, serviceGroup }, + query: { + rangeFrom, + rangeTo, + environment, + kuery, + serviceGroup, + comparisonEnabled, + comparisonType, + }, } = useApmParams('/services'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx index 20f31fa9b272e2..88498f4186457b 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx @@ -11,7 +11,6 @@ import React, { ReactNode } from 'react'; import { useUiTracker } from '../../../../../../observability/public'; import { getNodeName, NodeType } from '../../../../../common/connections'; import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context'; -import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; import { useApmParams } from '../../../../hooks/use_apm_params'; import { useFetcher } from '../../../../hooks/use_fetcher'; import { useTimeRange } from '../../../../hooks/use_time_range'; @@ -34,11 +33,16 @@ export function ServiceOverviewDependenciesTable({ hidePerPageOptions = false, }: ServiceOverviewDependenciesTableProps) { const { - urlParams: { comparisonEnabled, comparisonType, latencyAggregationType }, - } = useLegacyUrlParams(); - - const { - query: { environment, kuery, rangeFrom, rangeTo, serviceGroup }, + query: { + environment, + kuery, + rangeFrom, + rangeTo, + serviceGroup, + comparisonEnabled, + comparisonType, + latencyAggregationType, + }, } = useApmParams('/services/{serviceName}/*'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx index 5e0aa95340e81b..dfea13eaaf476b 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx @@ -10,7 +10,6 @@ import { orderBy } from 'lodash'; import React, { useState } from 'react'; import uuid from 'uuid'; import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; -import { useLegacyUrlParams } from '../../../context/url_params_context/use_url_params'; import { useApmParams } from '../../../hooks/use_apm_params'; import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher'; import { useTimeRange } from '../../../hooks/use_time_range'; @@ -21,6 +20,7 @@ import { ServiceOverviewInstancesTable, TableOptions, } from './service_overview_instances_table'; +import { LatencyAggregationType } from '../../../../common/latency_aggregation_types'; interface ServiceOverviewInstancesChartAndTableProps { chartHeight: number; @@ -73,13 +73,17 @@ export function ServiceOverviewInstancesChartAndTable({ const { direction, field } = sort; const { - query: { environment, kuery, rangeFrom, rangeTo }, + query: { + environment, + kuery, + rangeFrom, + rangeTo, + comparisonEnabled, + comparisonType, + latencyAggregationType, + }, } = useApmParams('/services/{serviceName}/overview'); - const { - urlParams: { latencyAggregationType, comparisonType, comparisonEnabled }, - } = useLegacyUrlParams(); - const { start, end } = useTimeRange({ rangeFrom, rangeTo }); const { comparisonStart, comparisonEnd } = getTimeRangeComparison({ @@ -108,7 +112,8 @@ export function ServiceOverviewInstancesChartAndTable({ query: { environment, kuery, - latencyAggregationType, + latencyAggregationType: + latencyAggregationType as LatencyAggregationType, start, end, transactionType, @@ -190,7 +195,8 @@ export function ServiceOverviewInstancesChartAndTable({ query: { environment, kuery, - latencyAggregationType, + latencyAggregationType: + latencyAggregationType as LatencyAggregationType, start, end, numBuckets: 20, diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/index.tsx index c41ad329ea8639..03f036e44b4c13 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/index.tsx @@ -14,7 +14,6 @@ import { import { i18n } from '@kbn/i18n'; import React, { ReactNode, useEffect, useState } from 'react'; import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context'; -import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; import { FETCH_STATUS } from '../../../../hooks/use_fetcher'; import { APIReturnType } from '../../../../services/rest/create_call_apm_api'; import { @@ -27,6 +26,7 @@ import { getColumns } from './get_columns'; import { InstanceDetails } from './intance_details'; import { useApmParams } from '../../../../hooks/use_apm_params'; import { useBreakpoints } from '../../../../hooks/use_breakpoints'; +import { LatencyAggregationType } from '../../../../../common/latency_aggregation_types'; type ServiceInstanceMainStatistics = APIReturnType<'GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics'>; @@ -71,13 +71,9 @@ export function ServiceOverviewInstancesTable({ const { agentName } = useApmServiceContext(); const { - query: { kuery }, + query: { kuery, latencyAggregationType, comparisonEnabled }, } = useApmParams('/services/{serviceName}'); - const { - urlParams: { latencyAggregationType, comparisonEnabled }, - } = useLegacyUrlParams(); - const [itemIdToOpenActionMenuRowMap, setItemIdToOpenActionMenuRowMap] = useState>({}); @@ -127,7 +123,7 @@ export function ServiceOverviewInstancesTable({ agentName, serviceName, kuery, - latencyAggregationType, + latencyAggregationType: latencyAggregationType as LatencyAggregationType, detailedStatsData, comparisonEnabled, toggleRowDetails, diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx index dbbb925fe634be..a0a8f7babe640d 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx @@ -18,7 +18,6 @@ import { ApmMlDetectorType } from '../../../../common/anomaly_detection/apm_ml_d import { asExactTransactionRate } from '../../../../common/utils/formatters'; import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; import { useEnvironmentsContext } from '../../../context/environments_context/use_environments_context'; -import { useLegacyUrlParams } from '../../../context/url_params_context/use_url_params'; import { useApmParams } from '../../../hooks/use_apm_params'; import { useFetcher } from '../../../hooks/use_fetcher'; import { usePreferredServiceAnomalyTimeseries } from '../../../hooks/use_preferred_service_anomaly_timeseries'; @@ -48,11 +47,7 @@ export function ServiceOverviewThroughputChart({ transactionName?: string; }) { const { - urlParams: { comparisonEnabled, comparisonType }, - } = useLegacyUrlParams(); - - const { - query: { rangeFrom, rangeTo }, + query: { rangeFrom, rangeTo, comparisonEnabled, comparisonType }, } = useApmParams('/services/{serviceName}'); const { environment } = useEnvironmentsContext(); diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/maybe_view_trace_link.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/maybe_view_trace_link.tsx index dfc89f78e4b3b7..855f5c037fdd16 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/maybe_view_trace_link.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/maybe_view_trace_link.tsx @@ -9,11 +9,11 @@ import { EuiButton, EuiFlexItem, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { getNextEnvironmentUrlParam } from '../../../../../common/environment_filter_values'; -import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; import { Transaction as ITransaction } from '../../../../../typings/es_schemas/ui/transaction'; import { TransactionDetailLink } from '../../../shared/links/apm/transaction_detail_link'; import { IWaterfall } from './waterfall_container/waterfall/waterfall_helpers/waterfall_helpers'; import { Environment } from '../../../../../common/environment_rt'; +import { useApmParams } from '../../../../hooks/use_apm_params'; export function MaybeViewTraceLink({ transaction, @@ -25,8 +25,8 @@ export function MaybeViewTraceLink({ environment: Environment; }) { const { - urlParams: { latencyAggregationType, comparisonEnabled, comparisonType }, - } = useLegacyUrlParams(); + query: { latencyAggregationType, comparisonEnabled, comparisonType }, + } = useApmParams('/services/{serviceName}/transactions/view'); const viewFullTraceButtonLabel = i18n.translate( 'xpack.apm.transactionDetails.viewFullTraceButtonLabel', diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/flyout_top_level_properties.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/flyout_top_level_properties.tsx index 20e278000266a9..ead54b3e9d6d91 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/flyout_top_level_properties.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/flyout_top_level_properties.tsx @@ -13,7 +13,6 @@ import { } from '../../../../../../../common/elasticsearch_fieldnames'; import { getNextEnvironmentUrlParam } from '../../../../../../../common/environment_filter_values'; import { Transaction } from '../../../../../../../typings/es_schemas/ui/transaction'; -import { useLegacyUrlParams } from '../../../../../../context/url_params_context/use_url_params'; import { useApmParams } from '../../../../../../hooks/use_apm_params'; import { TransactionDetailLink } from '../../../../../shared/links/apm/transaction_detail_link'; import { ServiceLink } from '../../../../../shared/service_link'; @@ -24,11 +23,10 @@ interface Props { } export function FlyoutTopLevelProperties({ transaction }: Props) { - const { - urlParams: { latencyAggregationType, comparisonEnabled, comparisonType }, - } = useLegacyUrlParams(); const { query } = useApmParams('/services/{serviceName}/transactions/view'); + const { latencyAggregationType, comparisonEnabled, comparisonType } = query; + if (!transaction) { return null; } diff --git a/x-pack/plugins/apm/public/components/routing/service_detail/index.tsx b/x-pack/plugins/apm/public/components/routing/service_detail/index.tsx index 79b46f98a520b1..a4c2b84d57b355 100644 --- a/x-pack/plugins/apm/public/components/routing/service_detail/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/service_detail/index.tsx @@ -28,6 +28,7 @@ import { ServiceProfiling } from '../../app/service_profiling'; import { ServiceDependencies } from '../../app/service_dependencies'; import { ServiceLogs } from '../../app/service_logs'; import { InfraOverview } from '../../app/infra_overview'; +import { LatencyAggregationType } from '../../../../common/latency_aggregation_types'; function page({ title, @@ -94,6 +95,7 @@ export const serviceDetail = { kuery: '', environment: ENVIRONMENT_ALL.value, serviceGroup: '', + latencyAggregationType: LatencyAggregationType.avg, }, }, children: { diff --git a/x-pack/plugins/apm/public/components/shared/charts/failed_transaction_rate_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/failed_transaction_rate_chart/index.tsx index 2efbae85d91c26..a968bf31860862 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/failed_transaction_rate_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/failed_transaction_rate_chart/index.tsx @@ -57,11 +57,11 @@ export function FailedTransactionRateChart({ kuery, }: Props) { const { - urlParams: { transactionName, comparisonEnabled, comparisonType }, + urlParams: { transactionName }, } = useLegacyUrlParams(); const { - query: { rangeFrom, rangeTo }, + query: { rangeFrom, rangeTo, comparisonEnabled, comparisonType }, } = useApmParams('/services/{serviceName}'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); @@ -74,7 +74,7 @@ export function FailedTransactionRateChart({ const { serviceName, transactionType, alerts } = useApmServiceContext(); - const comparisonChartThem = getComparisonChartTheme(); + const comparisonChartTheme = getComparisonChartTheme(); const { comparisonStart, comparisonEnd } = getTimeRangeComparison({ start, end, @@ -165,7 +165,7 @@ export function FailedTransactionRateChart({ timeseries={timeseries} yLabelFormat={yLabelFormat} yDomain={{ min: 0, max: 1 }} - customTheme={comparisonChartThem} + customTheme={comparisonChartTheme} anomalyTimeseries={preferredAnomalyTimeseries} alerts={alerts.filter( (alert) => diff --git a/x-pack/plugins/apm/public/components/shared/charts/latency_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/latency_chart/index.tsx index 6991a7aa7e200c..880879119be986 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/latency_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/latency_chart/index.tsx @@ -15,7 +15,6 @@ import { useApmServiceContext } from '../../../../context/apm_service/use_apm_se import { LatencyAggregationType } from '../../../../../common/latency_aggregation_types'; import { getDurationFormatter } from '../../../../../common/utils/formatters'; import { useLicenseContext } from '../../../../context/license/use_license_context'; -import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; import { useTransactionLatencyChartsFetcher } from '../../../../hooks/use_transaction_latency_chart_fetcher'; import { TimeseriesChart } from '../../../shared/charts/timeseries_chart'; import { @@ -28,6 +27,7 @@ import { getComparisonChartTheme } from '../../time_comparison/get_time_range_co import { useEnvironmentsContext } from '../../../../context/environments_context/use_environments_context'; import { ApmMlDetectorType } from '../../../../../common/anomaly_detection/apm_ml_detectors'; import { usePreferredServiceAnomalyTimeseries } from '../../../../hooks/use_preferred_service_anomaly_timeseries'; +import { useAnyOfApmParams } from '../../../../hooks/use_apm_params'; interface Props { height?: number; @@ -48,10 +48,16 @@ export function LatencyChart({ height, kuery }: Props) { const history = useHistory(); const comparisonChartTheme = getComparisonChartTheme(); - const { urlParams } = useLegacyUrlParams(); - const { latencyAggregationType, comparisonEnabled } = urlParams; const license = useLicenseContext(); + const { + query: { comparisonEnabled, latencyAggregationType }, + } = useAnyOfApmParams( + '/services/{serviceName}/overview', + '/services/{serviceName}/transactions', + '/services/{serviceName}/transactions/view' + ); + const { environment } = useEnvironmentsContext(); const { latencyChartsData, latencyChartsStatus } = diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx index 2b99562b67172f..b6558bea79d3ed 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx @@ -74,7 +74,7 @@ export function TransactionColdstartRateChart({ const { start, end } = useTimeRange({ rangeFrom, rangeTo }); const { serviceName, transactionType } = useApmServiceContext(); - const comparisonChartThem = getComparisonChartTheme(); + const comparisonChartTheme = getComparisonChartTheme(); const { comparisonStart, comparisonEnd } = getTimeRangeComparison({ start, end, @@ -177,7 +177,7 @@ export function TransactionColdstartRateChart({ timeseries={timeseries} yLabelFormat={yLabelFormat} yDomain={{ min: 0, max: 1 }} - customTheme={comparisonChartThem} + customTheme={comparisonChartTheme} /> ); diff --git a/x-pack/plugins/apm/public/components/shared/time_comparison/comparison.test.ts b/x-pack/plugins/apm/public/components/shared/time_comparison/comparison.test.ts new file mode 100644 index 00000000000000..30da5078f5decf --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/time_comparison/comparison.test.ts @@ -0,0 +1,477 @@ +/* + * 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 { TimeRangeComparisonEnum } from '../../../../common/runtime_types/comparison_type_rt'; +import { getTimeRangeComparison } from './get_time_range_comparison'; +import { getDateRange } from '../../../context/url_params_context/helpers'; +import { getComparisonOptions } from './get_comparison_options'; +import moment from 'moment'; + +function getExpectedTimesAndComparisons({ + rangeFrom, + rangeTo, +}: { + rangeFrom: string; + rangeTo: string; +}) { + const { start, end } = getDateRange({ rangeFrom, rangeTo }); + const comparisonOptions = getComparisonOptions({ start, end }); + + const comparisons = comparisonOptions.map(({ value, text }) => { + const { comparisonStart, comparisonEnd, offset } = getTimeRangeComparison({ + comparisonEnabled: true, + comparisonType: value, + start, + end, + }); + + return { + value, + text, + comparisonStart, + comparisonEnd, + offset, + }; + }); + + return { + start, + end, + comparisons, + }; +} + +describe('Comparison test suite', () => { + let dateNowSpy: jest.SpyInstance; + + beforeAll(() => { + const mockDateNow = '2022-01-14T18:30:15.500Z'; + dateNowSpy = jest + .spyOn(Date, 'now') + .mockReturnValue(new Date(mockDateNow).getTime()); + }); + + afterAll(() => { + dateNowSpy.mockRestore(); + }); + + describe('When the time difference is less than 25 hours', () => { + let expectation: ReturnType; + + beforeAll(() => { + expectation = getExpectedTimesAndComparisons({ + rangeFrom: '2022-01-15T18:00:00.000Z', + rangeTo: '2022-01-16T18:30:00.000Z', + }); + }); + + it('should return the correct start and end date', () => { + expect(expectation.start).toBe('2022-01-15T18:00:00.000Z'); + expect(expectation.end).toBe('2022-01-16T18:30:00.000Z'); + }); + + it('should return comparison by day and week', () => { + expect(expectation.comparisons).toEqual([ + { + value: TimeRangeComparisonEnum.DayBefore, + text: 'Day before', + comparisonStart: '2022-01-14T18:00:00.000Z', + comparisonEnd: '2022-01-15T18:30:00.000Z', + offset: '1d', + }, + { + value: TimeRangeComparisonEnum.WeekBefore, + text: 'Week before', + comparisonStart: '2022-01-08T18:00:00.000Z', + comparisonEnd: '2022-01-09T18:30:00.000Z', + offset: '1w', + }, + ]); + }); + }); + + describe('When the time difference is more than 25 hours', () => { + let expectation: ReturnType; + + beforeAll(() => { + expectation = getExpectedTimesAndComparisons({ + rangeFrom: '2022-01-15T18:00:00.000Z', + rangeTo: '2022-01-16T19:00:00.000Z', + }); + }); + + it('should return the correct start and end date', () => { + expect(expectation.start).toBe('2022-01-15T18:00:00.000Z'); + expect(expectation.end).toBe('2022-01-16T19:00:00.000Z'); + }); + + it('should only return comparison by week', () => { + expect(expectation.comparisons).toEqual([ + { + value: TimeRangeComparisonEnum.WeekBefore, + text: 'Week before', + comparisonStart: '2022-01-08T18:00:00.000Z', + comparisonEnd: '2022-01-09T19:00:00.000Z', + offset: '1w', + }, + ]); + }); + }); + + describe('When the time difference is more than 25 hours and less than 8 days', () => { + let expectation: ReturnType; + + beforeAll(() => { + expectation = getExpectedTimesAndComparisons({ + rangeFrom: '2022-01-15T18:00:00.000Z', + rangeTo: '2022-01-22T21:00:00.000Z', + }); + }); + + it('should return the correct start and end date', () => { + expect(expectation.start).toBe('2022-01-15T18:00:00.000Z'); + expect(expectation.end).toBe('2022-01-22T21:00:00.000Z'); + }); + + it('should only return comparison by week', () => { + expect(expectation.comparisons).toEqual([ + { + value: TimeRangeComparisonEnum.WeekBefore, + text: 'Week before', + comparisonStart: '2022-01-08T18:00:00.000Z', + comparisonEnd: '2022-01-15T21:00:00.000Z', + offset: '1w', + }, + ]); + }); + }); + + describe('When the time difference is 8 days', () => { + let expectation: ReturnType; + + beforeAll(() => { + expectation = getExpectedTimesAndComparisons({ + rangeFrom: '2022-01-15T18:00:00.000Z', + rangeTo: '2022-01-23T18:00:00.000Z', + }); + }); + + it('should return the correct start and end date', () => { + expect(expectation.start).toBe('2022-01-15T18:00:00.000Z'); + expect(expectation.end).toBe('2022-01-23T18:00:00.000Z'); + }); + + it('should only return comparison by period and format text as DD/MM HH:mm when range years are the same', () => { + expect(expectation.comparisons).toEqual([ + { + value: TimeRangeComparisonEnum.PeriodBefore, + text: '07/01 18:00 - 15/01 18:00', + comparisonStart: '2022-01-07T18:00:00.000Z', + comparisonEnd: '2022-01-15T18:00:00.000Z', + offset: '691200000ms', + }, + ]); + }); + + it('should have the same offset for start / end and comparisonStart / comparisonEnd', () => { + const { start, end, comparisons } = expectation; + const diffInMs = moment(end).diff(moment(start)); + expect(`${diffInMs}ms`).toBe(comparisons[0].offset); + }); + }); + + describe('When the time difference is more than 8 days', () => { + let expectation: ReturnType; + + beforeAll(() => { + expectation = getExpectedTimesAndComparisons({ + rangeFrom: '2022-01-15T18:00:00.000Z||/d', + rangeTo: '2022-01-23T18:00:00.000Z', + }); + }); + + it('should return the correct start and end date', () => { + expect(expectation.start).toBe('2022-01-15T00:00:00.000Z'); + expect(expectation.end).toBe('2022-01-23T18:00:00.000Z'); + }); + + it('should only return comparison by period and format text as DD/MM HH:mm when range years are the same', () => { + expect(expectation.comparisons).toEqual([ + { + value: TimeRangeComparisonEnum.PeriodBefore, + text: '06/01 06:00 - 15/01 00:00', + comparisonStart: '2022-01-06T06:00:00.000Z', + comparisonEnd: '2022-01-15T00:00:00.000Z', + offset: '756000000ms', + }, + ]); + }); + + it('should have the same offset for start / end and comparisonStart / comparisonEnd', () => { + const { start, end, comparisons } = expectation; + const diffInMs = moment(end).diff(moment(start)); + expect(`${diffInMs}ms`).toBe(comparisons[0].offset); + }); + }); + + describe('When "Today" is selected', () => { + let expectation: ReturnType; + + beforeAll(() => { + expectation = getExpectedTimesAndComparisons({ + rangeFrom: 'now/d', + rangeTo: 'now/d', + }); + }); + + it('should return the correct start and end date', () => { + expect(expectation.start).toBe('2022-01-14T00:00:00.000Z'); + expect(expectation.end).toBe('2022-01-14T23:59:59.999Z'); + }); + + it('should return comparison by day and week', () => { + expect(expectation.comparisons).toEqual([ + { + value: TimeRangeComparisonEnum.DayBefore, + text: 'Day before', + comparisonStart: '2022-01-13T00:00:00.000Z', + comparisonEnd: '2022-01-13T23:59:59.999Z', + offset: '1d', + }, + { + value: TimeRangeComparisonEnum.WeekBefore, + text: 'Week before', + comparisonStart: '2022-01-07T00:00:00.000Z', + comparisonEnd: '2022-01-07T23:59:59.999Z', + offset: '1w', + }, + ]); + }); + }); + + describe('When "This week" is selected', () => { + let expectation: ReturnType; + + beforeAll(() => { + expectation = getExpectedTimesAndComparisons({ + rangeFrom: 'now/w', + rangeTo: 'now/w', + }); + }); + + it('should return the correct start and end date', () => { + expect(expectation.start).toBe('2022-01-09T00:00:00.000Z'); + expect(expectation.end).toBe('2022-01-15T23:59:59.999Z'); + }); + + it('should only return comparison by week', () => { + expect(expectation.comparisons).toEqual([ + { + value: TimeRangeComparisonEnum.WeekBefore, + text: 'Week before', + comparisonStart: '2022-01-02T00:00:00.000Z', + comparisonEnd: '2022-01-08T23:59:59.999Z', + offset: '1w', + }, + ]); + }); + }); + + describe('When "Last 24 hours" is selected with no rounding', () => { + let expectation: ReturnType; + + beforeAll(() => { + expectation = getExpectedTimesAndComparisons({ + rangeFrom: 'now-24h', + rangeTo: 'now', + }); + }); + + it('should return the correct start and end date', () => { + expect(expectation.start).toBe('2022-01-13T18:30:15.500Z'); + expect(expectation.end).toBe('2022-01-14T18:30:15.500Z'); + }); + + it('should return comparison by day and week', () => { + expect(expectation.comparisons).toEqual([ + { + value: TimeRangeComparisonEnum.DayBefore, + text: 'Day before', + comparisonStart: '2022-01-12T18:30:15.500Z', + comparisonEnd: '2022-01-13T18:30:15.500Z', + offset: '1d', + }, + { + value: TimeRangeComparisonEnum.WeekBefore, + text: 'Week before', + comparisonStart: '2022-01-06T18:30:15.500Z', + comparisonEnd: '2022-01-07T18:30:15.500Z', + offset: '1w', + }, + ]); + }); + }); + + describe('When "Last 24 hours" is selected with rounding', () => { + let expectation: ReturnType; + + beforeAll(() => { + expectation = getExpectedTimesAndComparisons({ + rangeFrom: 'now-24h/h', + rangeTo: 'now', + }); + }); + + it('should return the correct start and end date', () => { + expect(expectation.start).toBe('2022-01-13T18:00:00.000Z'); + expect(expectation.end).toBe('2022-01-14T18:30:15.500Z'); + }); + + it('should return comparison by day and week', () => { + expect(expectation.comparisons).toEqual([ + { + value: TimeRangeComparisonEnum.DayBefore, + text: 'Day before', + comparisonStart: '2022-01-12T18:00:00.000Z', + comparisonEnd: '2022-01-13T18:30:15.500Z', + offset: '1d', + }, + { + value: TimeRangeComparisonEnum.WeekBefore, + text: 'Week before', + comparisonStart: '2022-01-06T18:00:00.000Z', + comparisonEnd: '2022-01-07T18:30:15.500Z', + offset: '1w', + }, + ]); + }); + }); + + describe('When "Last 7 days" is selected with no rounding', () => { + let expectation: ReturnType; + + beforeAll(() => { + expectation = getExpectedTimesAndComparisons({ + rangeFrom: 'now-7d', + rangeTo: 'now', + }); + }); + + it('should return the correct start and end date', () => { + expect(expectation.start).toBe('2022-01-07T18:30:15.500Z'); + expect(expectation.end).toBe('2022-01-14T18:30:15.500Z'); + }); + + it('should only return comparison by week', () => { + expect(expectation.comparisons).toEqual([ + { + value: TimeRangeComparisonEnum.WeekBefore, + text: 'Week before', + comparisonStart: '2021-12-31T18:30:15.500Z', + comparisonEnd: '2022-01-07T18:30:15.500Z', + offset: '1w', + }, + ]); + }); + }); + + describe('When "Last 7 days" is selected with rounding', () => { + let expectation: ReturnType; + + beforeAll(() => { + expectation = getExpectedTimesAndComparisons({ + rangeFrom: 'now-7d/d', + rangeTo: 'now', + }); + }); + + it('should return the correct start and end date', () => { + expect(expectation.start).toBe('2022-01-07T00:00:00.000Z'); + expect(expectation.end).toBe('2022-01-14T18:30:15.500Z'); + }); + + it('should only return comparison by week', () => { + expect(expectation.comparisons).toEqual([ + { + value: TimeRangeComparisonEnum.WeekBefore, + text: 'Week before', + comparisonStart: '2021-12-31T00:00:00.000Z', + comparisonEnd: '2022-01-07T18:30:15.500Z', + offset: '1w', + }, + ]); + }); + }); + + describe('When "Last 30 days" is selected with no rounding', () => { + let expectation: ReturnType; + + beforeAll(() => { + expectation = getExpectedTimesAndComparisons({ + rangeFrom: 'now-30d', + rangeTo: 'now', + }); + }); + + it('should return the correct start and end date', () => { + expect(expectation.start).toBe('2021-12-15T18:30:15.500Z'); + expect(expectation.end).toBe('2022-01-14T18:30:15.500Z'); + }); + + it('should only return comparison by period and format text as DD/MM/YY HH:mm when range years are different', () => { + expect(expectation.comparisons).toEqual([ + { + value: TimeRangeComparisonEnum.PeriodBefore, + text: '15/11/21 18:30 - 15/12/21 18:30', + comparisonStart: '2021-11-15T18:30:15.500Z', + comparisonEnd: '2021-12-15T18:30:15.500Z', + offset: '2592000000ms', + }, + ]); + }); + + it('should have the same offset for start / end and comparisonStart / comparisonEnd', () => { + const { start, end, comparisons } = expectation; + const diffInMs = moment(end).diff(moment(start)); + expect(`${diffInMs}ms`).toBe(comparisons[0].offset); + }); + }); + + describe('When "Last 30 days" is selected with rounding', () => { + let expectation: ReturnType; + + beforeAll(() => { + expectation = getExpectedTimesAndComparisons({ + rangeFrom: 'now-30d/d', + rangeTo: 'now', + }); + }); + + it('should return the correct start and end date', () => { + expect(expectation.start).toBe('2021-12-15T00:00:00.000Z'); + expect(expectation.end).toBe('2022-01-14T18:30:15.500Z'); + }); + + it('should only return comparison by period and format text as DD/MM/YY HH:mm when range years are different', () => { + expect(expectation.comparisons).toEqual([ + { + value: TimeRangeComparisonEnum.PeriodBefore, + text: '14/11/21 05:29 - 15/12/21 00:00', + comparisonStart: '2021-11-14T05:29:44.500Z', + comparisonEnd: '2021-12-15T00:00:00.000Z', + offset: '2658615500ms', + }, + ]); + }); + + it('should have the same offset for start / end and comparisonStart / comparisonEnd', () => { + const { start, end, comparisons } = expectation; + const diffInMs = moment(end).diff(moment(start)); + expect(`${diffInMs}ms`).toBe(comparisons[0].offset); + }); + }); +}); diff --git a/x-pack/plugins/apm/public/components/shared/time_comparison/get_comparison_options.ts b/x-pack/plugins/apm/public/components/shared/time_comparison/get_comparison_options.ts new file mode 100644 index 00000000000000..9400f668a18f0f --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/time_comparison/get_comparison_options.ts @@ -0,0 +1,126 @@ +/* + * 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 moment from 'moment'; +import { i18n } from '@kbn/i18n'; +import { TimeRangeComparisonEnum } from '../../../../common/runtime_types/comparison_type_rt'; +import { getTimeRangeComparison } from './get_time_range_comparison'; + +const eightDaysInHours = moment.duration(8, 'd').asHours(); + +function getDateFormat({ + previousPeriodStart, + currentPeriodEnd, +}: { + previousPeriodStart?: string; + currentPeriodEnd?: string; +}) { + const momentPreviousPeriodStart = moment(previousPeriodStart); + const momentCurrentPeriodEnd = moment(currentPeriodEnd); + const isDifferentYears = + momentPreviousPeriodStart.get('year') !== + momentCurrentPeriodEnd.get('year'); + return isDifferentYears ? 'DD/MM/YY HH:mm' : 'DD/MM HH:mm'; +} + +function formatDate({ + dateFormat, + previousPeriodStart, + previousPeriodEnd, +}: { + dateFormat: string; + previousPeriodStart?: string; + previousPeriodEnd?: string; +}) { + const momentStart = moment(previousPeriodStart); + const momentEnd = moment(previousPeriodEnd); + return `${momentStart.format(dateFormat)} - ${momentEnd.format(dateFormat)}`; +} + +function getSelectOptions({ + comparisonTypes, + start, + end, +}: { + comparisonTypes: TimeRangeComparisonEnum[]; + start?: string; + end?: string; +}) { + return comparisonTypes.map((value) => { + switch (value) { + case TimeRangeComparisonEnum.DayBefore: { + return { + value, + text: i18n.translate('xpack.apm.timeComparison.select.dayBefore', { + defaultMessage: 'Day before', + }), + }; + } + case TimeRangeComparisonEnum.WeekBefore: { + return { + value, + text: i18n.translate('xpack.apm.timeComparison.select.weekBefore', { + defaultMessage: 'Week before', + }), + }; + } + case TimeRangeComparisonEnum.PeriodBefore: { + const { comparisonStart, comparisonEnd } = getTimeRangeComparison({ + comparisonType: TimeRangeComparisonEnum.PeriodBefore, + start, + end, + comparisonEnabled: true, + }); + + const dateFormat = getDateFormat({ + previousPeriodStart: comparisonStart, + currentPeriodEnd: end, + }); + + return { + value, + text: formatDate({ + dateFormat, + previousPeriodStart: comparisonStart, + previousPeriodEnd: comparisonEnd, + }), + }; + } + } + }); +} + +export function getComparisonOptions({ + start, + end, +}: { + start?: string; + end?: string; +}) { + const momentStart = moment(start); + const momentEnd = moment(end); + const hourDiff = momentEnd.diff(momentStart, 'h', true); + + let comparisonTypes: TimeRangeComparisonEnum[]; + + if (hourDiff < 25) { + // Less than 25 hours. This is because relative times may be rounded when + // asking for a day, which can result in a duration > 24h. (e.g. rangeFrom: 'now-24h/h, rangeTo: 'now') + comparisonTypes = [ + TimeRangeComparisonEnum.DayBefore, + TimeRangeComparisonEnum.WeekBefore, + ]; + } else if (hourDiff < eightDaysInHours) { + // Less than 8 days. This is because relative times may be rounded when + // asking for a week, which can result in a duration > 7d. (e.g. rangeFrom: 'now-7d/d, rangeTo: 'now') + comparisonTypes = [TimeRangeComparisonEnum.WeekBefore]; + } else { + comparisonTypes = [TimeRangeComparisonEnum.PeriodBefore]; + } + + return getSelectOptions({ comparisonTypes, start, end }); +} diff --git a/x-pack/plugins/apm/public/components/shared/time_comparison/get_comparison_types.ts b/x-pack/plugins/apm/public/components/shared/time_comparison/get_comparison_types.ts deleted file mode 100644 index 97754cd91fd3e5..00000000000000 --- a/x-pack/plugins/apm/public/components/shared/time_comparison/get_comparison_types.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 moment from 'moment'; -import { TimeRangeComparisonEnum } from '../../../../common/runtime_types/comparison_type_rt'; -import { getDateDifference } from '../../../../common/utils/formatters'; - -export function getComparisonTypes({ - start, - end, -}: { - start?: string; - end?: string; -}) { - const momentStart = moment(start).startOf('second'); - const momentEnd = moment(end).startOf('second'); - - const dateDiff = getDateDifference({ - start: momentStart, - end: momentEnd, - precise: true, - unitOfTime: 'days', - }); - - // Less than or equals to one day - if (dateDiff <= 1) { - return [ - TimeRangeComparisonEnum.DayBefore, - TimeRangeComparisonEnum.WeekBefore, - ]; - } - - // Less than or equals to one week - if (dateDiff <= 7) { - return [TimeRangeComparisonEnum.WeekBefore]; - } - // } - - // above one week or when rangeTo is not "now" - return [TimeRangeComparisonEnum.PeriodBefore]; -} diff --git a/x-pack/plugins/apm/public/components/shared/time_comparison/get_time_range_comparison.test.ts b/x-pack/plugins/apm/public/components/shared/time_comparison/get_time_range_comparison.test.ts index 7e67d76c2ada24..c6619ad6d35f33 100644 --- a/x-pack/plugins/apm/public/components/shared/time_comparison/get_time_range_comparison.test.ts +++ b/x-pack/plugins/apm/public/components/shared/time_comparison/get_time_range_comparison.test.ts @@ -41,102 +41,4 @@ describe('getTimeRangeComparison', () => { expect(result).toEqual({}); }); }); - - describe('Time range is between 0 - 24 hours', () => { - describe('when day before is selected', () => { - it('returns the correct time range - 15 min', () => { - const start = '2021-01-28T14:45:00.000Z'; - const end = '2021-01-28T15:00:00.000Z'; - const result = getTimeRangeComparison({ - comparisonType: TimeRangeComparisonEnum.DayBefore, - comparisonEnabled: true, - start, - end, - }); - expect(result.comparisonStart).toEqual('2021-01-27T14:45:00.000Z'); - expect(result.comparisonEnd).toEqual('2021-01-27T15:00:00.000Z'); - expect(result.offset).toEqual('1d'); - }); - }); - describe('when a week before is selected', () => { - it('returns the correct time range - 15 min', () => { - const start = '2021-01-28T14:45:00.000Z'; - const end = '2021-01-28T15:00:00.000Z'; - const result = getTimeRangeComparison({ - comparisonType: TimeRangeComparisonEnum.WeekBefore, - comparisonEnabled: true, - start, - end, - }); - expect(result.comparisonStart).toEqual('2021-01-21T14:45:00.000Z'); - expect(result.comparisonEnd).toEqual('2021-01-21T15:00:00.000Z'); - expect(result.offset).toEqual('1w'); - }); - }); - describe('when previous period is selected', () => { - it('returns the correct time range - 15 min', () => { - const start = '2021-02-09T14:40:01.087Z'; - const end = '2021-02-09T14:56:00.000Z'; - const result = getTimeRangeComparison({ - start, - end, - comparisonType: TimeRangeComparisonEnum.PeriodBefore, - comparisonEnabled: true, - }); - expect(result).toEqual({ - comparisonStart: '2021-02-09T14:24:02.174Z', - comparisonEnd: '2021-02-09T14:40:01.087Z', - offset: '958913ms', - }); - }); - }); - }); - - describe('Time range is between 24 hours - 1 week', () => { - describe('when a week before is selected', () => { - it('returns the correct time range - 2 days', () => { - const start = '2021-01-26T15:00:00.000Z'; - const end = '2021-01-28T15:00:00.000Z'; - const result = getTimeRangeComparison({ - comparisonType: TimeRangeComparisonEnum.WeekBefore, - comparisonEnabled: true, - start, - end, - }); - expect(result.comparisonStart).toEqual('2021-01-19T15:00:00.000Z'); - expect(result.comparisonEnd).toEqual('2021-01-21T15:00:00.000Z'); - expect(result.offset).toEqual('1w'); - }); - }); - }); - - describe('Time range is greater than 7 days', () => { - it('uses the date difference to calculate the time range - 8 days', () => { - const start = '2021-01-10T15:00:00.000Z'; - const end = '2021-01-18T15:00:00.000Z'; - const result = getTimeRangeComparison({ - comparisonType: TimeRangeComparisonEnum.PeriodBefore, - comparisonEnabled: true, - start, - end, - }); - expect(result.comparisonStart).toEqual('2021-01-02T15:00:00.000Z'); - expect(result.comparisonEnd).toEqual('2021-01-10T15:00:00.000Z'); - expect(result.offset).toEqual('691200000ms'); - }); - - it('uses the date difference to calculate the time range - 30 days', () => { - const start = '2021-01-01T15:00:00.000Z'; - const end = '2021-01-31T15:00:00.000Z'; - const result = getTimeRangeComparison({ - comparisonType: TimeRangeComparisonEnum.PeriodBefore, - comparisonEnabled: true, - start, - end, - }); - expect(result.comparisonStart).toEqual('2020-12-02T15:00:00.000Z'); - expect(result.comparisonEnd).toEqual('2021-01-01T15:00:00.000Z'); - expect(result.offset).toEqual('2592000000ms'); - }); - }); }); diff --git a/x-pack/plugins/apm/public/components/shared/time_comparison/get_time_range_comparison.ts b/x-pack/plugins/apm/public/components/shared/time_comparison/get_time_range_comparison.ts index 92611d88aa0cc3..6a1f7b1978ca0c 100644 --- a/x-pack/plugins/apm/public/components/shared/time_comparison/get_time_range_comparison.ts +++ b/x-pack/plugins/apm/public/components/shared/time_comparison/get_time_range_comparison.ts @@ -11,7 +11,6 @@ import { TimeRangeComparisonType, TimeRangeComparisonEnum, } from '../../../../common/runtime_types/comparison_type_rt'; -import { getDateDifference } from '../../../../common/utils/formatters'; export function getComparisonChartTheme(): PartialTheme { return { @@ -48,13 +47,9 @@ export function getTimeRangeComparison({ if (!comparisonEnabled || !comparisonType || !start || !end) { return {}; } - const startMoment = moment(start); const endMoment = moment(end); - const startEpoch = startMoment.valueOf(); - const endEpoch = endMoment.valueOf(); - let diff: number; let offset: string; @@ -63,29 +58,21 @@ export function getTimeRangeComparison({ diff = oneDayInMilliseconds; offset = '1d'; break; - case TimeRangeComparisonEnum.WeekBefore: diff = oneWeekInMilliseconds; offset = '1w'; break; - case TimeRangeComparisonEnum.PeriodBefore: - diff = getDateDifference({ - start: startMoment, - end: endMoment, - unitOfTime: 'milliseconds', - precise: true, - }); + diff = endMoment.diff(startMoment); offset = `${diff}ms`; break; - default: throw new Error('Unknown comparisonType'); } return { - comparisonStart: new Date(startEpoch - diff).toISOString(), - comparisonEnd: new Date(endEpoch - diff).toISOString(), + comparisonStart: startMoment.subtract(diff, 'ms').toISOString(), + comparisonEnd: endMoment.subtract(diff, 'ms').toISOString(), offset, }; } diff --git a/x-pack/plugins/apm/public/components/shared/time_comparison/index.test.tsx b/x-pack/plugins/apm/public/components/shared/time_comparison/index.test.tsx index d811fbb5d03578..83d2962316aa20 100644 --- a/x-pack/plugins/apm/public/components/shared/time_comparison/index.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/time_comparison/index.test.tsx @@ -13,10 +13,9 @@ import { expectTextsInDocument, expectTextsNotInDocument, } from '../../../utils/test_helpers'; -import { getSelectOptions, TimeComparison } from './'; +import { TimeComparison } from './'; import * as urlHelpers from '../../shared/links/url_helpers'; import moment from 'moment'; -import { getComparisonTypes } from './get_comparison_types'; import { MockApmPluginContextWrapper } from '../../../context/apm_plugin/mock_apm_plugin_context'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; import { @@ -26,14 +25,14 @@ import { import { MockUrlParamsContextProvider } from '../../../context/url_params_context/mock_url_params_context_provider'; function getWrapper({ - exactStart, - exactEnd, + rangeFrom, + rangeTo, comparisonType, comparisonEnabled, environment = ENVIRONMENT_ALL.value, }: { - exactStart: string; - exactEnd: string; + rangeFrom: string; + rangeTo: string; comparisonType?: TimeRangeComparisonType; comparisonEnabled?: boolean; environment?: string; @@ -42,7 +41,7 @@ function getWrapper({ return ( { +describe('TimeComparison component', () => { beforeAll(() => { moment.tz.setDefault('Europe/Amsterdam'); }); afterAll(() => moment.tz.setDefault('')); - describe('getComparisonTypes', () => { - it('shows week and day before when 15 minutes is selected', () => { - expect( - getComparisonTypes({ - start: '2021-06-04T16:17:02.335Z', - end: '2021-06-04T16:32:02.335Z', - }) - ).toEqual([ - TimeRangeComparisonEnum.DayBefore.valueOf(), - TimeRangeComparisonEnum.WeekBefore.valueOf(), - ]); - }); - - it('shows week and day before when Today is selected', () => { - expect( - getComparisonTypes({ - start: '2021-06-04T04:00:00.000Z', - end: '2021-06-05T03:59:59.999Z', - }) - ).toEqual([ - TimeRangeComparisonEnum.DayBefore.valueOf(), - TimeRangeComparisonEnum.WeekBefore.valueOf(), - ]); - }); - - it('shows week and day before when 24 hours is selected', () => { - expect( - getComparisonTypes({ - start: '2021-06-03T16:31:35.748Z', - end: '2021-06-04T16:31:35.748Z', - }) - ).toEqual([ - TimeRangeComparisonEnum.DayBefore.valueOf(), - TimeRangeComparisonEnum.WeekBefore.valueOf(), - ]); - }); + const spy = jest.spyOn(urlHelpers, 'replace'); + beforeEach(() => { + jest.resetAllMocks(); + }); - it('shows week and day before when 24 hours is selected but milliseconds are different', () => { - expect( - getComparisonTypes({ - start: '2021-10-15T00:52:59.554Z', - end: '2021-10-14T00:52:59.553Z', - }) - ).toEqual([ - TimeRangeComparisonEnum.DayBefore.valueOf(), - TimeRangeComparisonEnum.WeekBefore.valueOf(), - ]); + describe('Time range is between 0 - 25 hours', () => { + it('sets default values', () => { + const Wrapper = getWrapper({ + rangeFrom: '2021-06-04T16:17:02.335Z', + rangeTo: '2021-06-04T16:32:02.335Z', + }); + render(, { wrapper: Wrapper }); + expect(spy).toHaveBeenCalledWith(expect.anything(), { + query: { + comparisonEnabled: 'true', + comparisonType: TimeRangeComparisonEnum.DayBefore, + }, + }); }); - it('shows week before when 25 hours is selected', () => { + it('selects day before and enables comparison', () => { + const Wrapper = getWrapper({ + rangeFrom: '2021-06-04T16:17:02.335Z', + rangeTo: '2021-06-04T16:32:02.335Z', + comparisonEnabled: true, + comparisonType: TimeRangeComparisonEnum.DayBefore, + }); + const component = render(, { wrapper: Wrapper }); + expectTextsInDocument(component, ['Day before', 'Week before']); expect( - getComparisonTypes({ - start: '2021-06-02T12:32:00.000Z', - end: '2021-06-03T13:32:09.079Z', - }) - ).toEqual([TimeRangeComparisonEnum.WeekBefore.valueOf()]); + (component.getByTestId('comparisonSelect') as HTMLSelectElement) + .selectedIndex + ).toEqual(0); }); - it('shows week before when 7 days is selected', () => { - expect( - getComparisonTypes({ - start: '2021-05-28T16:32:17.520Z', - end: '2021-06-04T16:32:17.520Z', - }) - ).toEqual([TimeRangeComparisonEnum.WeekBefore.valueOf()]); - }); - it('shows period before when 8 days is selected', () => { + it('enables day before option when date difference is equal to 24 hours', () => { + const Wrapper = getWrapper({ + rangeFrom: '2021-06-03T16:31:35.748Z', + rangeTo: '2021-06-04T16:31:35.748Z', + comparisonEnabled: true, + comparisonType: TimeRangeComparisonEnum.DayBefore, + }); + const component = render(, { wrapper: Wrapper }); + expectTextsInDocument(component, ['Day before', 'Week before']); expect( - getComparisonTypes({ - start: '2021-05-27T16:32:46.747Z', - end: '2021-06-04T16:32:46.747Z', - }) - ).toEqual([TimeRangeComparisonEnum.PeriodBefore.valueOf()]); + (component.getByTestId('comparisonSelect') as HTMLSelectElement) + .selectedIndex + ).toEqual(0); }); }); - describe('getSelectOptions', () => { - it('returns formatted text based on comparison type', () => { - expect( - getSelectOptions({ - comparisonTypes: [ - TimeRangeComparisonEnum.DayBefore, - TimeRangeComparisonEnum.WeekBefore, - TimeRangeComparisonEnum.PeriodBefore, - ], - start: '2021-05-27T16:32:46.747Z', - end: '2021-06-04T16:32:46.747Z', - }) - ).toEqual([ - { - value: TimeRangeComparisonEnum.DayBefore.valueOf(), - text: 'Day before', - }, - { - value: TimeRangeComparisonEnum.WeekBefore.valueOf(), - text: 'Week before', - }, - { - value: TimeRangeComparisonEnum.PeriodBefore.valueOf(), - text: '19/05 18:32 - 27/05 18:32', - }, - ]); + describe('Time range is between 25 hours - 8 days', () => { + it("doesn't show day before option when date difference is greater than 25 hours", () => { + const Wrapper = getWrapper({ + rangeFrom: '2021-06-02T12:32:00.000Z', + rangeTo: '2021-06-03T13:32:09.079Z', + comparisonEnabled: true, + comparisonType: TimeRangeComparisonEnum.WeekBefore, + }); + const component = render(, { + wrapper: Wrapper, + }); + expectTextsNotInDocument(component, ['Day before']); + expectTextsInDocument(component, ['Week before']); }); - it('formats period before as DD/MM/YY HH:mm when range years are different', () => { - expect( - getSelectOptions({ - comparisonTypes: [TimeRangeComparisonEnum.PeriodBefore], - start: '2020-05-27T16:32:46.747Z', - end: '2021-06-04T16:32:46.747Z', - }) - ).toEqual([ - { - value: TimeRangeComparisonEnum.PeriodBefore.valueOf(), - text: '20/05/19 18:32 - 27/05/20 18:32', + it('sets default values', () => { + const Wrapper = getWrapper({ + rangeFrom: '2021-06-02T12:32:00.000Z', + rangeTo: '2021-06-03T13:32:09.079Z', + }); + render(, { + wrapper: Wrapper, + }); + expect(spy).toHaveBeenCalledWith(expect.anything(), { + query: { + comparisonEnabled: 'true', + comparisonType: TimeRangeComparisonEnum.WeekBefore, }, - ]); + }); }); - }); - describe('TimeComparison component', () => { - const spy = jest.spyOn(urlHelpers, 'replace'); - beforeEach(() => { - jest.resetAllMocks(); - }); - describe('Time range is between 0 - 24 hours', () => { - it('sets default values', () => { - const Wrapper = getWrapper({ - exactStart: '2021-06-04T16:17:02.335Z', - exactEnd: '2021-06-04T16:32:02.335Z', - }); - render(, { wrapper: Wrapper }); - expect(spy).toHaveBeenCalledWith(expect.anything(), { - query: { - comparisonEnabled: 'true', - comparisonType: TimeRangeComparisonEnum.DayBefore, - }, - }); + it('selects week before and enables comparison', () => { + const Wrapper = getWrapper({ + rangeFrom: '2021-06-02T12:32:00.000Z', + rangeTo: '2021-06-03T13:32:09.079Z', + comparisonEnabled: true, + comparisonType: TimeRangeComparisonEnum.WeekBefore, }); - it('selects day before and enables comparison', () => { - const Wrapper = getWrapper({ - exactStart: '2021-06-04T16:17:02.335Z', - exactEnd: '2021-06-04T16:32:02.335Z', - comparisonEnabled: true, - comparisonType: TimeRangeComparisonEnum.DayBefore, - }); - const component = render(, { wrapper: Wrapper }); - expectTextsInDocument(component, ['Day before', 'Week before']); - expect( - (component.getByTestId('comparisonSelect') as HTMLSelectElement) - .selectedIndex - ).toEqual(0); - }); - - it('enables day before option when date difference is equal to 24 hours', () => { - const Wrapper = getWrapper({ - exactStart: '2021-06-03T16:31:35.748Z', - exactEnd: '2021-06-04T16:31:35.748Z', - comparisonEnabled: true, - comparisonType: TimeRangeComparisonEnum.DayBefore, - }); - const component = render(, { wrapper: Wrapper }); - expectTextsInDocument(component, ['Day before', 'Week before']); - expect( - (component.getByTestId('comparisonSelect') as HTMLSelectElement) - .selectedIndex - ).toEqual(0); + const component = render(, { + wrapper: Wrapper, }); + expectTextsNotInDocument(component, ['Day before']); + expectTextsInDocument(component, ['Week before']); + expect( + (component.getByTestId('comparisonSelect') as HTMLSelectElement) + .selectedIndex + ).toEqual(0); }); + }); - describe('Time range is between 24 hours - 1 week', () => { - it("doesn't show day before option when date difference is greater than 24 hours", () => { - const Wrapper = getWrapper({ - exactStart: '2021-06-02T12:32:00.000Z', - exactEnd: '2021-06-03T13:32:09.079Z', - comparisonEnabled: true, - comparisonType: TimeRangeComparisonEnum.WeekBefore, - }); - const component = render(, { - wrapper: Wrapper, - }); - expectTextsNotInDocument(component, ['Day before']); - expectTextsInDocument(component, ['Week before']); + describe('Time range is greater than 8 days', () => { + it('Shows absolute times without year when within the same year', () => { + const Wrapper = getWrapper({ + rangeFrom: '2021-05-27T16:32:46.747Z', + rangeTo: '2021-06-04T16:32:46.747Z', + comparisonEnabled: true, + comparisonType: TimeRangeComparisonEnum.PeriodBefore, }); - it('sets default values', () => { - const Wrapper = getWrapper({ - exactStart: '2021-06-02T12:32:00.000Z', - exactEnd: '2021-06-03T13:32:09.079Z', - }); - render(, { - wrapper: Wrapper, - }); - expect(spy).toHaveBeenCalledWith(expect.anything(), { - query: { - comparisonEnabled: 'true', - comparisonType: TimeRangeComparisonEnum.WeekBefore, - }, - }); - }); - it('selects week before and enables comparison', () => { - const Wrapper = getWrapper({ - exactStart: '2021-06-02T12:32:00.000Z', - exactEnd: '2021-06-03T13:32:09.079Z', - comparisonEnabled: true, - comparisonType: TimeRangeComparisonEnum.WeekBefore, - }); - const component = render(, { - wrapper: Wrapper, - }); - expectTextsNotInDocument(component, ['Day before']); - expectTextsInDocument(component, ['Week before']); - expect( - (component.getByTestId('comparisonSelect') as HTMLSelectElement) - .selectedIndex - ).toEqual(0); + const component = render(, { + wrapper: Wrapper, }); + expect(spy).not.toHaveBeenCalled(); + expectTextsInDocument(component, ['19/05 18:32 - 27/05 18:32']); + expect( + (component.getByTestId('comparisonSelect') as HTMLSelectElement) + .selectedIndex + ).toEqual(0); }); - describe('Time range is greater than 7 days', () => { - it('Shows absolute times without year when within the same year', () => { - const Wrapper = getWrapper({ - exactStart: '2021-05-27T16:32:46.747Z', - exactEnd: '2021-06-04T16:32:46.747Z', - comparisonEnabled: true, - comparisonType: TimeRangeComparisonEnum.PeriodBefore, - }); - const component = render(, { - wrapper: Wrapper, - }); - expect(spy).not.toHaveBeenCalled(); - expectTextsInDocument(component, ['19/05 18:32 - 27/05 18:32']); - expect( - (component.getByTestId('comparisonSelect') as HTMLSelectElement) - .selectedIndex - ).toEqual(0); + it('Shows absolute times with year when on different year', () => { + const Wrapper = getWrapper({ + rangeFrom: '2020-05-27T16:32:46.747Z', + rangeTo: '2021-06-04T16:32:46.747Z', + comparisonEnabled: true, + comparisonType: TimeRangeComparisonEnum.PeriodBefore, }); - - it('Shows absolute times with year when on different year', () => { - const Wrapper = getWrapper({ - exactStart: '2020-05-27T16:32:46.747Z', - exactEnd: '2021-06-04T16:32:46.747Z', - comparisonEnabled: true, - comparisonType: TimeRangeComparisonEnum.PeriodBefore, - }); - const component = render(, { - wrapper: Wrapper, - }); - expect(spy).not.toHaveBeenCalled(); - expectTextsInDocument(component, ['20/05/19 18:32 - 27/05/20 18:32']); - expect( - (component.getByTestId('comparisonSelect') as HTMLSelectElement) - .selectedIndex - ).toEqual(0); + const component = render(, { + wrapper: Wrapper, }); + expect(spy).not.toHaveBeenCalled(); + expectTextsInDocument(component, ['20/05/19 18:32 - 27/05/20 18:32']); + expect( + (component.getByTestId('comparisonSelect') as HTMLSelectElement) + .selectedIndex + ).toEqual(0); }); }); }); diff --git a/x-pack/plugins/apm/public/components/shared/time_comparison/index.tsx b/x-pack/plugins/apm/public/components/shared/time_comparison/index.tsx index e61ffbbbc5bab1..cb0bc870354c49 100644 --- a/x-pack/plugins/apm/public/components/shared/time_comparison/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/time_comparison/index.tsx @@ -7,12 +7,10 @@ import { EuiCheckbox, EuiSelect } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import moment from 'moment'; import React from 'react'; import { useHistory } from 'react-router-dom'; import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common'; import { useUiTracker } from '../../../../../observability/public'; -import { TimeRangeComparisonEnum } from '../../../../common/runtime_types/comparison_type_rt'; import { useLegacyUrlParams } from '../../../context/url_params_context/use_url_params'; import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; import { useAnyOfApmParams } from '../../../hooks/use_apm_params'; @@ -20,8 +18,7 @@ import { useBreakpoints } from '../../../hooks/use_breakpoints'; import { useTimeRange } from '../../../hooks/use_time_range'; import * as urlHelpers from '../../shared/links/url_helpers'; import { getComparisonEnabled } from './get_comparison_enabled'; -import { getComparisonTypes } from './get_comparison_types'; -import { getTimeRangeComparison } from './get_time_range_comparison'; +import { getComparisonOptions } from './get_comparison_options'; const PrependContainer = euiStyled.div` display: flex; @@ -32,88 +29,6 @@ const PrependContainer = euiStyled.div` padding: 0 ${({ theme }) => theme.eui.paddingSizes.m}; `; -function getDateFormat({ - previousPeriodStart, - currentPeriodEnd, -}: { - previousPeriodStart?: string; - currentPeriodEnd?: string; -}) { - const momentPreviousPeriodStart = moment(previousPeriodStart); - const momentCurrentPeriodEnd = moment(currentPeriodEnd); - const isDifferentYears = - momentPreviousPeriodStart.get('year') !== - momentCurrentPeriodEnd.get('year'); - return isDifferentYears ? 'DD/MM/YY HH:mm' : 'DD/MM HH:mm'; -} - -function formatDate({ - dateFormat, - previousPeriodStart, - previousPeriodEnd, -}: { - dateFormat: string; - previousPeriodStart?: string; - previousPeriodEnd?: string; -}) { - const momentStart = moment(previousPeriodStart); - const momentEnd = moment(previousPeriodEnd); - return `${momentStart.format(dateFormat)} - ${momentEnd.format(dateFormat)}`; -} - -export function getSelectOptions({ - comparisonTypes, - start, - end, -}: { - comparisonTypes: TimeRangeComparisonEnum[]; - start?: string; - end?: string; -}) { - return comparisonTypes.map((value) => { - switch (value) { - case TimeRangeComparisonEnum.DayBefore: { - return { - value, - text: i18n.translate('xpack.apm.timeComparison.select.dayBefore', { - defaultMessage: 'Day before', - }), - }; - } - case TimeRangeComparisonEnum.WeekBefore: { - return { - value, - text: i18n.translate('xpack.apm.timeComparison.select.weekBefore', { - defaultMessage: 'Week before', - }), - }; - } - case TimeRangeComparisonEnum.PeriodBefore: { - const { comparisonStart, comparisonEnd } = getTimeRangeComparison({ - comparisonType: TimeRangeComparisonEnum.PeriodBefore, - start, - end, - comparisonEnabled: true, - }); - - const dateFormat = getDateFormat({ - previousPeriodStart: comparisonStart, - currentPeriodEnd: end, - }); - - return { - value, - text: formatDate({ - dateFormat, - previousPeriodStart: comparisonStart, - previousPeriodEnd: comparisonEnd, - }), - }; - } - } - }); -} - export function TimeComparison() { const { core } = useApmPluginContext(); const trackApmEvent = useUiTracker({ app: 'apm' }); @@ -123,19 +38,13 @@ export function TimeComparison() { query: { rangeFrom, rangeTo }, } = useAnyOfApmParams('/services', '/backends/*', '/services/{serviceName}'); - const { exactStart, exactEnd } = useTimeRange({ - rangeFrom, - rangeTo, - }); + const { start, end } = useTimeRange({ rangeFrom, rangeTo }); const { urlParams: { comparisonEnabled, comparisonType }, } = useLegacyUrlParams(); - const comparisonTypes = getComparisonTypes({ - start: exactStart, - end: exactEnd, - }); + const comparisonOptions = getComparisonOptions({ start, end }); // Sets default values if (comparisonEnabled === undefined || comparisonType === undefined) { @@ -148,26 +57,22 @@ export function TimeComparison() { }) === false ? 'false' : 'true', - comparisonType: comparisonType ? comparisonType : comparisonTypes[0], + comparisonType: comparisonType + ? comparisonType + : comparisonOptions[0].value, }, }); return null; } - const selectOptions = getSelectOptions({ - comparisonTypes, - start: exactStart, - end: exactEnd, - }); - - const isSelectedComparisonTypeAvailable = selectOptions.some( + const isSelectedComparisonTypeAvailable = comparisonOptions.some( ({ value }) => value === comparisonType ); // Replaces type when current one is no longer available in the select options - if (selectOptions.length !== 0 && !isSelectedComparisonTypeAvailable) { + if (comparisonOptions.length !== 0 && !isSelectedComparisonTypeAvailable) { urlHelpers.replace(history, { - query: { comparisonType: selectOptions[0].value }, + query: { comparisonType: comparisonOptions[0].value }, }); return null; } @@ -177,7 +82,7 @@ export function TimeComparison() { fullWidth={isSmall} data-test-subj="comparisonSelect" disabled={!comparisonEnabled} - options={selectOptions} + options={comparisonOptions} value={comparisonType} prepend={ diff --git a/x-pack/plugins/apm/public/components/shared/transactions_table/index.tsx b/x-pack/plugins/apm/public/components/shared/transactions_table/index.tsx index 4c1063173d9292..bf6e2b70d390e2 100644 --- a/x-pack/plugins/apm/public/components/shared/transactions_table/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/transactions_table/index.tsx @@ -15,7 +15,6 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { EuiCode } from '@elastic/eui'; import { APIReturnType } from '../../../services/rest/create_call_apm_api'; import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; -import { useLegacyUrlParams } from '../../../context/url_params_context/use_url_params'; import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher'; import { TransactionOverviewLink } from '../links/apm/transaction_overview_link'; import { getTimeRangeComparison } from '../time_comparison/get_time_range_comparison'; @@ -24,6 +23,8 @@ import { getColumns } from './get_columns'; import { ElasticDocsLink } from '../links/elastic_docs_link'; import { useBreakpoints } from '../../../hooks/use_breakpoints'; import { ManagedTable } from '../managed_table'; +import { useAnyOfApmParams } from '../../../hooks/use_apm_params'; +import { LatencyAggregationType } from '../../../../common/latency_aggregation_types'; type ApiResponse = APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics'>; @@ -97,8 +98,11 @@ export function TransactionsTable({ const { transactionType, serviceName } = useApmServiceContext(); const { - urlParams: { latencyAggregationType, comparisonType, comparisonEnabled }, - } = useLegacyUrlParams(); + query: { comparisonEnabled, comparisonType, latencyAggregationType }, + } = useAnyOfApmParams( + '/services/{serviceName}/transactions', + '/services/{serviceName}/overview' + ); const { comparisonStart, comparisonEnd } = getTimeRangeComparison({ start, @@ -123,7 +127,8 @@ export function TransactionsTable({ start, end, transactionType, - latencyAggregationType, + latencyAggregationType: + latencyAggregationType as LatencyAggregationType, }, }, } @@ -198,7 +203,8 @@ export function TransactionsTable({ end, numBuckets: 20, transactionType, - latencyAggregationType, + latencyAggregationType: + latencyAggregationType as LatencyAggregationType, transactionNames: JSON.stringify( transactionGroups.map(({ name }) => name).sort() ), @@ -218,7 +224,7 @@ export function TransactionsTable({ const columns = getColumns({ serviceName, - latencyAggregationType, + latencyAggregationType: latencyAggregationType as LatencyAggregationType, transactionGroupDetailedStatistics, comparisonEnabled, shouldShowSparkPlots, diff --git a/x-pack/plugins/apm/public/context/url_params_context/helpers.test.ts b/x-pack/plugins/apm/public/context/url_params_context/helpers.test.ts index 784b10b3f3ee1e..9ab0948fd75aac 100644 --- a/x-pack/plugins/apm/public/context/url_params_context/helpers.test.ts +++ b/x-pack/plugins/apm/public/context/url_params_context/helpers.test.ts @@ -14,58 +14,6 @@ describe('url_params_context helpers', () => { jest.restoreAllMocks(); }); describe('getDateRange', () => { - describe('with non-rounded dates', () => { - describe('one minute', () => { - it('rounds the start value to minute', () => { - expect( - helpers.getDateRange({ - state: {}, - rangeFrom: '2021-01-28T05:47:52.134Z', - rangeTo: '2021-01-28T05:48:55.304Z', - }) - ).toEqual({ - start: '2021-01-28T05:47:00.000Z', - end: '2021-01-28T05:48:55.304Z', - exactStart: '2021-01-28T05:47:52.134Z', - exactEnd: '2021-01-28T05:48:55.304Z', - }); - }); - }); - describe('one day', () => { - it('rounds the start value to minute', () => { - expect( - helpers.getDateRange({ - state: {}, - rangeFrom: '2021-01-27T05:46:07.377Z', - rangeTo: '2021-01-28T05:46:13.367Z', - }) - ).toEqual({ - start: '2021-01-27T05:46:00.000Z', - end: '2021-01-28T05:46:13.367Z', - exactStart: '2021-01-27T05:46:07.377Z', - exactEnd: '2021-01-28T05:46:13.367Z', - }); - }); - }); - - describe('one year', () => { - it('rounds the start value to minute', () => { - expect( - helpers.getDateRange({ - state: {}, - rangeFrom: '2020-01-28T05:52:36.290Z', - rangeTo: '2021-01-28T05:52:39.741Z', - }) - ).toEqual({ - start: '2020-01-28T05:52:00.000Z', - end: '2021-01-28T05:52:39.741Z', - exactStart: '2020-01-28T05:52:36.290Z', - exactEnd: '2021-01-28T05:52:39.741Z', - }); - }); - }); - }); - describe('when rangeFrom and rangeTo are not changed', () => { it('returns the previous state', () => { expect( @@ -75,8 +23,6 @@ describe('url_params_context helpers', () => { rangeTo: 'now', start: '1970-01-01T00:00:00.000Z', end: '1971-01-01T00:00:00.000Z', - exactStart: '1970-01-01T00:00:00.000Z', - exactEnd: '1971-01-01T00:00:00.000Z', }, rangeFrom: 'now-1m', rangeTo: 'now', @@ -84,8 +30,6 @@ describe('url_params_context helpers', () => { ).toEqual({ start: '1970-01-01T00:00:00.000Z', end: '1971-01-01T00:00:00.000Z', - exactStart: '1970-01-01T00:00:00.000Z', - exactEnd: '1971-01-01T00:00:00.000Z', }); }); }); @@ -107,8 +51,6 @@ describe('url_params_context helpers', () => { ).toEqual({ start: '1972-01-01T00:00:00.000Z', end: '1973-01-01T00:00:00.000Z', - exactStart: undefined, - exactEnd: undefined, }); }); }); @@ -119,32 +61,27 @@ describe('url_params_context helpers', () => { jest .spyOn(datemath, 'parse') .mockReturnValueOnce(undefined) - .mockReturnValueOnce(endDate) - .mockReturnValueOnce(undefined) .mockReturnValueOnce(endDate); + expect( helpers.getDateRange({ state: { start: '1972-01-01T00:00:00.000Z', end: '1973-01-01T00:00:00.000Z', - exactStart: '1972-01-01T00:00:00.000Z', - exactEnd: '1973-01-01T00:00:00.000Z', }, rangeFrom: 'nope', rangeTo: 'now', }) ).toEqual({ start: '1972-01-01T00:00:00.000Z', - exactStart: '1972-01-01T00:00:00.000Z', end: '1973-01-01T00:00:00.000Z', - exactEnd: '1973-01-01T00:00:00.000Z', }); }); }); describe('when rangeFrom or rangeTo have changed', () => { it('returns new state', () => { - jest.spyOn(datemath, 'parse').mockReturnValue(moment(0).utc()); + jest.spyOn(Date, 'now').mockReturnValue(moment(0).unix()); expect( helpers.getDateRange({ @@ -158,40 +95,10 @@ describe('url_params_context helpers', () => { rangeTo: 'now', }) ).toEqual({ - start: '1970-01-01T00:00:00.000Z', + start: '1969-12-31T23:58:00.000Z', end: '1970-01-01T00:00:00.000Z', - exactStart: '1970-01-01T00:00:00.000Z', - exactEnd: '1970-01-01T00:00:00.000Z', }); }); }); }); - - describe('getExactDate', () => { - it('returns date when it is not not relative', () => { - expect(helpers.getExactDate('2021-01-28T05:47:52.134Z')).toEqual( - new Date('2021-01-28T05:47:52.134Z') - ); - }); - - ['s', 'm', 'h', 'd', 'w'].map((roundingOption) => - it(`removes /${roundingOption} rounding option from relative time`, () => { - const spy = jest.spyOn(datemath, 'parse'); - helpers.getExactDate(`now/${roundingOption}`); - expect(spy).toHaveBeenCalledWith('now', {}); - }) - ); - - it('removes rounding option but keeps subtracting time', () => { - const spy = jest.spyOn(datemath, 'parse'); - helpers.getExactDate('now-24h/h'); - expect(spy).toHaveBeenCalledWith('now-24h', {}); - }); - - it('removes rounding option but keeps adding time', () => { - const spy = jest.spyOn(datemath, 'parse'); - helpers.getExactDate('now+15m/h'); - expect(spy).toHaveBeenCalledWith('now+15m', {}); - }); - }); }); diff --git a/x-pack/plugins/apm/public/context/url_params_context/helpers.ts b/x-pack/plugins/apm/public/context/url_params_context/helpers.ts index ee6ac43c1aeab4..6856c0e7d25067 100644 --- a/x-pack/plugins/apm/public/context/url_params_context/helpers.ts +++ b/x-pack/plugins/apm/public/context/url_params_context/helpers.ts @@ -6,8 +6,7 @@ */ import datemath from '@elastic/datemath'; -import { compact, pickBy } from 'lodash'; -import moment from 'moment'; +import { pickBy } from 'lodash'; import { UrlParams } from './types'; function getParsedDate(rawDate?: string, options = {}) { @@ -19,25 +18,12 @@ function getParsedDate(rawDate?: string, options = {}) { } } -export function getExactDate(rawDate: string) { - const isRelativeDate = rawDate.startsWith('now'); - if (isRelativeDate) { - // remove rounding from relative dates "Today" (now/d) and "This week" (now/w) - const rawDateWithouRounding = rawDate.replace(/\/([smhdw])$/, ''); - return getParsedDate(rawDateWithouRounding); - } - return getParsedDate(rawDate); -} - export function getDateRange({ state = {}, rangeFrom, rangeTo, }: { - state?: Pick< - UrlParams, - 'rangeFrom' | 'rangeTo' | 'start' | 'end' | 'exactStart' | 'exactEnd' - >; + state?: Pick; rangeFrom?: string; rangeTo?: string; }) { @@ -46,35 +32,23 @@ export function getDateRange({ return { start: state.start, end: state.end, - exactStart: state.exactStart, - exactEnd: state.exactEnd, }; } const start = getParsedDate(rangeFrom); const end = getParsedDate(rangeTo, { roundUp: true }); - const exactStart = rangeFrom ? getExactDate(rangeFrom) : undefined; - const exactEnd = rangeTo ? getExactDate(rangeTo) : undefined; - // `getParsedDate` will return undefined for invalid or empty dates. We return // the previous state if either date is undefined. if (!start || !end) { return { start: state.start, end: state.end, - exactStart: state.exactStart, - exactEnd: state.exactEnd, }; } - // rounds down start to minute - const roundedStart = moment(start).startOf('minute'); - return { - start: roundedStart.toISOString(), + start: start.toISOString(), end: end.toISOString(), - exactStart: exactStart?.toISOString(), - exactEnd: exactEnd?.toISOString(), }; } @@ -95,10 +69,6 @@ export function toBoolean(value?: string) { return value === 'true'; } -export function getPathAsArray(pathname: string = '') { - return compact(pathname.split('/')); -} - export function removeUndefinedProps(obj: T): Partial { return pickBy(obj, (value) => value !== undefined); } diff --git a/x-pack/plugins/apm/public/context/url_params_context/resolve_url_params.ts b/x-pack/plugins/apm/public/context/url_params_context/resolve_url_params.ts index eb231741ad77eb..5bb3a46c3aea46 100644 --- a/x-pack/plugins/apm/public/context/url_params_context/resolve_url_params.ts +++ b/x-pack/plugins/apm/public/context/url_params_context/resolve_url_params.ts @@ -19,10 +19,7 @@ import { } from './helpers'; import { UrlParams } from './types'; -type TimeUrlParams = Pick< - UrlParams, - 'start' | 'end' | 'rangeFrom' | 'rangeTo' | 'exactStart' | 'exactEnd' ->; +type TimeUrlParams = Pick; export function resolveUrlParams(location: Location, state: TimeUrlParams) { const query = toQuery(location.search); diff --git a/x-pack/plugins/apm/public/context/url_params_context/types.ts b/x-pack/plugins/apm/public/context/url_params_context/types.ts index aaad2fac2da227..6c0f10f78e7c8e 100644 --- a/x-pack/plugins/apm/public/context/url_params_context/types.ts +++ b/x-pack/plugins/apm/public/context/url_params_context/types.ts @@ -16,8 +16,6 @@ export interface UrlParams { environment?: string; rangeFrom?: string; rangeTo?: string; - exactStart?: string; - exactEnd?: string; refreshInterval?: number; refreshPaused?: boolean; sortDirection?: string; diff --git a/x-pack/plugins/apm/public/context/url_params_context/url_params_context.tsx b/x-pack/plugins/apm/public/context/url_params_context/url_params_context.tsx index a128db6c2cd7a7..80a99d1a4274b9 100644 --- a/x-pack/plugins/apm/public/context/url_params_context/url_params_context.tsx +++ b/x-pack/plugins/apm/public/context/url_params_context/url_params_context.tsx @@ -34,8 +34,7 @@ const UrlParamsProvider: React.ComponentClass<{}> = withRouter( ({ location, children }) => { const refUrlParams = useRef(resolveUrlParams(location, {})); - const { start, end, rangeFrom, rangeTo, exactStart, exactEnd } = - refUrlParams.current; + const { start, end, rangeFrom, rangeTo } = refUrlParams.current; // Counter to force an update in useFetcher when the refresh button is clicked. const [rangeId, setRangeId] = useState(0); @@ -47,10 +46,8 @@ const UrlParamsProvider: React.ComponentClass<{}> = withRouter( end, rangeFrom, rangeTo, - exactStart, - exactEnd, }), - [location, start, end, rangeFrom, rangeTo, exactStart, exactEnd] + [location, start, end, rangeFrom, rangeTo] ); refUrlParams.current = urlParams; diff --git a/x-pack/plugins/apm/public/hooks/use_comparison.ts b/x-pack/plugins/apm/public/hooks/use_comparison.ts deleted file mode 100644 index 93d0e31969c50f..00000000000000 --- a/x-pack/plugins/apm/public/hooks/use_comparison.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 { - getComparisonChartTheme, - getTimeRangeComparison, -} from '../components/shared/time_comparison/get_time_range_comparison'; -import { useLegacyUrlParams } from '../context/url_params_context/use_url_params'; -import { useApmParams } from './use_apm_params'; -import { useTimeRange } from './use_time_range'; - -export function useComparison() { - const comparisonChartTheme = getComparisonChartTheme(); - const { query } = useApmParams('/*'); - - if (!('rangeFrom' in query && 'rangeTo' in query)) { - throw new Error('rangeFrom or rangeTo not defined in query'); - } - - const { start, end } = useTimeRange({ - rangeFrom: query.rangeFrom, - rangeTo: query.rangeTo, - }); - - const { - urlParams: { comparisonType, comparisonEnabled }, - } = useLegacyUrlParams(); - - const { offset } = getTimeRangeComparison({ - start, - end, - comparisonType, - comparisonEnabled, - }); - - return { - offset, - comparisonChartTheme, - }; -} diff --git a/x-pack/plugins/apm/public/hooks/use_error_group_distribution_fetcher.tsx b/x-pack/plugins/apm/public/hooks/use_error_group_distribution_fetcher.tsx index d843067b48e918..62e2ab92c4fcc1 100644 --- a/x-pack/plugins/apm/public/hooks/use_error_group_distribution_fetcher.tsx +++ b/x-pack/plugins/apm/public/hooks/use_error_group_distribution_fetcher.tsx @@ -31,7 +31,6 @@ export function useErrorGroupDistributionFetcher({ comparisonType, comparisonEnabled, }); - const { data, status } = useFetcher( (callApmApi) => { if (start && end) { diff --git a/x-pack/plugins/apm/public/hooks/use_time_range.ts b/x-pack/plugins/apm/public/hooks/use_time_range.ts index 79ca70130a4422..26333062dfa3cb 100644 --- a/x-pack/plugins/apm/public/hooks/use_time_range.ts +++ b/x-pack/plugins/apm/public/hooks/use_time_range.ts @@ -12,14 +12,12 @@ import { getDateRange } from '../context/url_params_context/helpers'; interface TimeRange { start: string; end: string; - exactStart: string; - exactEnd: string; refreshTimeRange: () => void; timeRangeId: number; } type PartialTimeRange = Pick & - Pick, 'start' | 'end' | 'exactStart' | 'exactEnd'>; + Pick, 'start' | 'end'>; export function useTimeRange(range: { rangeFrom?: string; @@ -43,7 +41,7 @@ export function useTimeRange({ }): TimeRange | PartialTimeRange { const { incrementTimeRangeId, timeRangeId } = useTimeRangeId(); - const { start, end, exactStart, exactEnd } = useMemo(() => { + const { start, end } = useMemo(() => { return getDateRange({ state: {}, rangeFrom, @@ -52,15 +50,13 @@ export function useTimeRange({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [rangeFrom, rangeTo, timeRangeId]); - if ((!start || !end || !exactStart || !exactEnd) && !optional) { + if ((!start || !end) && !optional) { throw new Error('start and/or end were unexpectedly not set'); } return { start, end, - exactStart, - exactEnd, refreshTimeRange: incrementTimeRangeId, timeRangeId, }; diff --git a/x-pack/plugins/apm/public/hooks/use_transaction_latency_chart_fetcher.ts b/x-pack/plugins/apm/public/hooks/use_transaction_latency_chart_fetcher.ts index 33bb9095665d85..8dbc1f3a475052 100644 --- a/x-pack/plugins/apm/public/hooks/use_transaction_latency_chart_fetcher.ts +++ b/x-pack/plugins/apm/public/hooks/use_transaction_latency_chart_fetcher.ts @@ -23,16 +23,11 @@ export function useTransactionLatencyChartsFetcher({ }) { const { transactionType, serviceName } = useApmServiceContext(); const { - urlParams: { - transactionName, - latencyAggregationType, - comparisonType, - comparisonEnabled, - }, + urlParams: { transactionName, latencyAggregationType }, } = useLegacyUrlParams(); const { - query: { rangeFrom, rangeTo }, + query: { rangeFrom, rangeTo, comparisonType, comparisonEnabled }, } = useApmParams('/services/{serviceName}'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); @@ -43,7 +38,6 @@ export function useTransactionLatencyChartsFetcher({ comparisonType, comparisonEnabled, }); - const { data, error, status } = useFetcher( (callApmApi) => { if (