theme.eui.textColors.subdued};
+ color: ${({ theme }) => theme.eui.euiTextSubduedColor};
}
`;
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsList.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsList.tsx
index adbcf897669ae..cc41c254ffb50 100644
--- a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsList.tsx
+++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsList.tsx
@@ -20,7 +20,7 @@ export const ItemRow = styled('tr')`
`;
export const ItemTitle = styled('td')`
- color: ${({ theme }) => theme.eui.textColors.subdued};
+ color: ${({ theme }) => theme.eui.euiTextSubduedColor};
padding-right: 1rem;
`;
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscape_options.ts b/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscape_options.ts
index e2a54f6048682..f2f51496fcca8 100644
--- a/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscape_options.ts
+++ b/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscape_options.ts
@@ -129,7 +129,7 @@ const getStyle = (theme: EuiTheme): cytoscape.Stylesheet[] => {
color: (el: cytoscape.NodeSingular) =>
el.hasClass('primary') || el.selected()
? theme.eui.euiColorPrimaryText
- : theme.eui.textColors.text,
+ : theme.eui.euiTextColor,
// theme.euiFontFamily doesn't work here for some reason, so we're just
// specifying a subset of the fonts for the label text.
'font-family': 'Inter UI, Segoe UI, Helvetica, Arial, sans-serif',
diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx
index bebd5bdabbae3..309cde4dd9f65 100644
--- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx
@@ -33,11 +33,9 @@ import { unit } from '../../../../style/variables';
import { ChartContainer } from '../../../shared/charts/chart_container';
import { EmptyMessage } from '../../../shared/EmptyMessage';
-type TransactionDistributionAPIResponse = APIReturnType<'GET /api/apm/services/{serviceName}/transaction_groups/distribution'>;
+type TransactionDistributionAPIResponse = APIReturnType<'GET /api/apm/services/{serviceName}/transactions/charts/distribution'>;
-type DistributionApiResponse = APIReturnType<'GET /api/apm/services/{serviceName}/transaction_groups/distribution'>;
-
-type DistributionBucket = DistributionApiResponse['buckets'][0];
+type DistributionBucket = TransactionDistributionAPIResponse['buckets'][0];
interface IChartPoint {
x0: number;
diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/index.tsx
index d90fe393c94a4..a633341ba2bb4 100644
--- a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/index.tsx
@@ -27,7 +27,7 @@ import { MaybeViewTraceLink } from './MaybeViewTraceLink';
import { TransactionTabs } from './TransactionTabs';
import { IWaterfall } from './WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers';
-type DistributionApiResponse = APIReturnType<'GET /api/apm/services/{serviceName}/transaction_groups/distribution'>;
+type DistributionApiResponse = APIReturnType<'GET /api/apm/services/{serviceName}/transactions/charts/distribution'>;
type DistributionBucket = DistributionApiResponse['buckets'][0];
diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_transactions_table/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_transactions_table/index.tsx
index 6b02a44dcc2f4..e4260a2533d36 100644
--- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_transactions_table/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_transactions_table/index.tsx
@@ -36,7 +36,7 @@ import { ImpactBar } from '../../../shared/ImpactBar';
import { ServiceOverviewTable } from '../service_overview_table';
type ServiceTransactionGroupItem = ValuesType<
- APIReturnType<'GET /api/apm/services/{serviceName}/overview_transaction_groups'>['transactionGroups']
+ APIReturnType<'GET /api/apm/services/{serviceName}/transactions/groups/overview'>['transactionGroups']
>;
interface Props {
@@ -100,7 +100,7 @@ export function ServiceOverviewTransactionsTable(props: Props) {
return callApmApi({
endpoint:
- 'GET /api/apm/services/{serviceName}/overview_transaction_groups',
+ 'GET /api/apm/services/{serviceName}/transactions/groups/overview',
params: {
path: { serviceName },
query: {
diff --git a/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/TransactionList.stories.tsx b/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/TransactionList.stories.tsx
index c14c31afe0445..bc73a3acf4135 100644
--- a/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/TransactionList.stories.tsx
+++ b/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/TransactionList.stories.tsx
@@ -10,7 +10,7 @@ import { APIReturnType } from '../../../../services/rest/createCallApmApi';
import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context';
import { TransactionList } from './';
-type TransactionGroup = APIReturnType<'GET /api/apm/services/{serviceName}/transaction_groups'>['items'][0];
+type TransactionGroup = APIReturnType<'GET /api/apm/services/{serviceName}/transactions/groups'>['items'][0];
export default {
title: 'app/TransactionOverview/TransactionList',
diff --git a/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/index.tsx
index 9774538b2a7a7..ade0a0563b0dc 100644
--- a/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/index.tsx
@@ -20,7 +20,7 @@ import { LoadingStatePrompt } from '../../../shared/LoadingStatePrompt';
import { EmptyMessage } from '../../../shared/EmptyMessage';
import { TransactionDetailLink } from '../../../shared/Links/apm/TransactionDetailLink';
-type TransactionGroup = APIReturnType<'GET /api/apm/services/{serviceName}/transaction_groups'>['items'][0];
+type TransactionGroup = APIReturnType<'GET /api/apm/services/{serviceName}/transactions/groups'>['items'][0];
// Truncate both the link and the child span (the tooltip anchor.) The link so
// it doesn't overflow, and the anchor so we get the ellipsis.
diff --git a/x-pack/plugins/apm/public/components/app/transaction_overview/use_transaction_list.ts b/x-pack/plugins/apm/public/components/app/transaction_overview/use_transaction_list.ts
index 78883ec2cf0d3..0ca2867852f26 100644
--- a/x-pack/plugins/apm/public/components/app/transaction_overview/use_transaction_list.ts
+++ b/x-pack/plugins/apm/public/components/app/transaction_overview/use_transaction_list.ts
@@ -9,7 +9,7 @@ import { APIReturnType } from '../../../services/rest/createCallApmApi';
import { useFetcher } from '../../../hooks/use_fetcher';
import { useUrlParams } from '../../../context/url_params_context/use_url_params';
-type TransactionsAPIResponse = APIReturnType<'GET /api/apm/services/{serviceName}/transaction_groups'>;
+type TransactionsAPIResponse = APIReturnType<'GET /api/apm/services/{serviceName}/transactions/groups'>;
const DEFAULT_RESPONSE: Partial
= {
items: undefined,
@@ -25,7 +25,7 @@ export function useTransactionListFetcher() {
(callApmApi) => {
if (serviceName && start && end && transactionType) {
return callApmApi({
- endpoint: 'GET /api/apm/services/{serviceName}/transaction_groups',
+ endpoint: 'GET /api/apm/services/{serviceName}/transactions/groups',
params: {
path: { serviceName },
query: {
diff --git a/x-pack/plugins/apm/public/components/shared/Stacktrace/CauseStacktrace.tsx b/x-pack/plugins/apm/public/components/shared/Stacktrace/CauseStacktrace.tsx
index 50f87184f8ee7..a36980d49db3a 100644
--- a/x-pack/plugins/apm/public/components/shared/Stacktrace/CauseStacktrace.tsx
+++ b/x-pack/plugins/apm/public/components/shared/Stacktrace/CauseStacktrace.tsx
@@ -22,7 +22,7 @@ const CausedByContainer = styled('h5')`
`;
const CausedByHeading = styled('span')`
- color: ${({ theme }) => theme.eui.textColors.subdued};
+ color: ${({ theme }) => theme.eui.euiTextSubduedColor};
display: block;
font-size: ${({ theme }) => theme.eui.euiFontSizeXS};
font-weight: ${({ theme }) => theme.eui.euiFontWeightBold};
diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_breakdown_chart/use_transaction_breakdown.ts b/x-pack/plugins/apm/public/components/shared/charts/transaction_breakdown_chart/use_transaction_breakdown.ts
index ff744d763ecae..81840dc52c1ec 100644
--- a/x-pack/plugins/apm/public/components/shared/charts/transaction_breakdown_chart/use_transaction_breakdown.ts
+++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_breakdown_chart/use_transaction_breakdown.ts
@@ -20,7 +20,7 @@ export function useTransactionBreakdown() {
if (serviceName && start && end && transactionType) {
return callApmApi({
endpoint:
- 'GET /api/apm/services/{serviceName}/transaction_groups/breakdown',
+ 'GET /api/apm/services/{serviceName}/transaction/charts/breakdown',
params: {
path: { serviceName },
query: {
diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_error_rate_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/transaction_error_rate_chart/index.tsx
index 06a5e7baef79b..4a388b13d7d22 100644
--- a/x-pack/plugins/apm/public/components/shared/charts/transaction_error_rate_chart/index.tsx
+++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_error_rate_chart/index.tsx
@@ -45,7 +45,7 @@ export function TransactionErrorRateChart({
if (serviceName && start && end) {
return callApmApi({
endpoint:
- 'GET /api/apm/services/{serviceName}/transaction_groups/error_rate',
+ 'GET /api/apm/services/{serviceName}/transactions/charts/error_rate',
params: {
path: {
serviceName,
diff --git a/x-pack/plugins/apm/public/hooks/use_transaction_charts_fetcher.ts b/x-pack/plugins/apm/public/hooks/use_transaction_charts_fetcher.ts
index f5105e38b985e..406a1a4633577 100644
--- a/x-pack/plugins/apm/public/hooks/use_transaction_charts_fetcher.ts
+++ b/x-pack/plugins/apm/public/hooks/use_transaction_charts_fetcher.ts
@@ -21,8 +21,7 @@ export function useTransactionChartsFetcher() {
(callApmApi) => {
if (serviceName && start && end) {
return callApmApi({
- endpoint:
- 'GET /api/apm/services/{serviceName}/transaction_groups/charts',
+ endpoint: 'GET /api/apm/services/{serviceName}/transactions/charts',
params: {
path: { serviceName },
query: {
diff --git a/x-pack/plugins/apm/public/hooks/use_transaction_distribution_fetcher.ts b/x-pack/plugins/apm/public/hooks/use_transaction_distribution_fetcher.ts
index 74222e8ffe038..b8968031e6922 100644
--- a/x-pack/plugins/apm/public/hooks/use_transaction_distribution_fetcher.ts
+++ b/x-pack/plugins/apm/public/hooks/use_transaction_distribution_fetcher.ts
@@ -12,7 +12,7 @@ import { maybe } from '../../common/utils/maybe';
import { APIReturnType } from '../services/rest/createCallApmApi';
import { useUrlParams } from '../context/url_params_context/use_url_params';
-type APIResponse = APIReturnType<'GET /api/apm/services/{serviceName}/transaction_groups/distribution'>;
+type APIResponse = APIReturnType<'GET /api/apm/services/{serviceName}/transactions/charts/distribution'>;
const INITIAL_DATA = {
buckets: [] as APIResponse['buckets'],
@@ -38,7 +38,7 @@ export function useTransactionDistributionFetcher() {
if (serviceName && start && end && transactionType && transactionName) {
const response = await callApmApi({
endpoint:
- 'GET /api/apm/services/{serviceName}/transaction_groups/distribution',
+ 'GET /api/apm/services/{serviceName}/transactions/charts/distribution',
params: {
path: {
serviceName,
diff --git a/x-pack/plugins/apm/server/lib/errors/get_error_group.ts b/x-pack/plugins/apm/server/lib/errors/get_error_group_sample.ts
similarity index 92%
rename from x-pack/plugins/apm/server/lib/errors/get_error_group.ts
rename to x-pack/plugins/apm/server/lib/errors/get_error_group_sample.ts
index 965cc28952b7a..ff09855e63a8f 100644
--- a/x-pack/plugins/apm/server/lib/errors/get_error_group.ts
+++ b/x-pack/plugins/apm/server/lib/errors/get_error_group_sample.ts
@@ -14,8 +14,7 @@ import { rangeFilter } from '../../../common/utils/range_filter';
import { Setup, SetupTimeRange } from '../helpers/setup_request';
import { getTransaction } from '../transactions/get_transaction';
-// TODO: rename from "getErrorGroup" to "getErrorGroupSample" (since a single error is returned, not an errorGroup)
-export async function getErrorGroup({
+export async function getErrorGroupSample({
serviceName,
groupId,
setup,
diff --git a/x-pack/plugins/apm/server/lib/errors/queries.test.ts b/x-pack/plugins/apm/server/lib/errors/queries.test.ts
index fec59393726bf..92f0abcfb77e7 100644
--- a/x-pack/plugins/apm/server/lib/errors/queries.test.ts
+++ b/x-pack/plugins/apm/server/lib/errors/queries.test.ts
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { getErrorGroup } from './get_error_group';
+import { getErrorGroupSample } from './get_error_group_sample';
import { getErrorGroups } from './get_error_groups';
import {
SearchParamsMock,
@@ -20,7 +20,7 @@ describe('error queries', () => {
it('fetches a single error group', async () => {
mock = await inspectSearchParams((setup) =>
- getErrorGroup({
+ getErrorGroupSample({
groupId: 'groupId',
serviceName: 'serviceName',
setup,
diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_sample_for_group.ts b/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_sample_for_group.ts
deleted file mode 100644
index 7e1aad075fb16..0000000000000
--- a/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_sample_for_group.ts
+++ /dev/null
@@ -1,89 +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;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { maybe } from '../../../common/utils/maybe';
-import {
- SERVICE_NAME,
- TRANSACTION_NAME,
- TRANSACTION_SAMPLED,
-} from '../../../common/elasticsearch_fieldnames';
-import { ProcessorEvent } from '../../../common/processor_event';
-import { rangeFilter } from '../../../common/utils/range_filter';
-import { Setup, SetupTimeRange } from '../helpers/setup_request';
-
-export async function getTransactionSampleForGroup({
- serviceName,
- transactionName,
- setup,
-}: {
- serviceName: string;
- transactionName: string;
- setup: Setup & SetupTimeRange;
-}) {
- const { apmEventClient, start, end, esFilter } = setup;
-
- const filter = [
- {
- range: rangeFilter(start, end),
- },
- {
- term: {
- [SERVICE_NAME]: serviceName,
- },
- },
- {
- term: {
- [TRANSACTION_NAME]: transactionName,
- },
- },
- ...esFilter,
- ];
-
- const getSampledTransaction = async () => {
- const response = await apmEventClient.search({
- terminateAfter: 1,
- apm: {
- events: [ProcessorEvent.transaction],
- },
- body: {
- size: 1,
- query: {
- bool: {
- filter: [...filter, { term: { [TRANSACTION_SAMPLED]: true } }],
- },
- },
- },
- });
-
- return maybe(response.hits.hits[0]?._source);
- };
-
- const getUnsampledTransaction = async () => {
- const response = await apmEventClient.search({
- terminateAfter: 1,
- apm: {
- events: [ProcessorEvent.transaction],
- },
- body: {
- size: 1,
- query: {
- bool: {
- filter: [...filter, { term: { [TRANSACTION_SAMPLED]: false } }],
- },
- },
- },
- });
-
- return maybe(response.hits.hits[0]?._source);
- };
-
- const [sampledTransaction, unsampledTransaction] = await Promise.all([
- getSampledTransaction(),
- getUnsampledTransaction(),
- ]);
-
- return sampledTransaction || unsampledTransaction;
-}
diff --git a/x-pack/plugins/apm/server/routes/create_apm_api.ts b/x-pack/plugins/apm/server/routes/create_apm_api.ts
index 4f7f6320185bf..0e066a1959c49 100644
--- a/x-pack/plugins/apm/server/routes/create_apm_api.ts
+++ b/x-pack/plugins/apm/server/routes/create_apm_api.ts
@@ -23,7 +23,6 @@ import {
serviceAnnotationsCreateRoute,
serviceErrorGroupsRoute,
serviceThroughputRoute,
- serviceTransactionGroupsRoute,
} from './services';
import {
agentConfigurationRoute,
@@ -52,13 +51,13 @@ import {
correlationsForFailedTransactionsRoute,
} from './correlations';
import {
- transactionGroupsBreakdownRoute,
- transactionGroupsChartsRoute,
- transactionGroupsDistributionRoute,
+ transactionChartsBreakdownRoute,
+ transactionChartsRoute,
+ transactionChartsDistributionRoute,
+ transactionChartsErrorRateRoute,
transactionGroupsRoute,
- transactionSampleForGroupRoute,
- transactionGroupsErrorRateRoute,
-} from './transaction_groups';
+ transactionGroupsOverviewRoute,
+} from './transactions/transactions_routes';
import {
errorGroupsLocalFiltersRoute,
metricsLocalFiltersRoute,
@@ -122,7 +121,6 @@ const createApmApi = () => {
.add(serviceAnnotationsCreateRoute)
.add(serviceErrorGroupsRoute)
.add(serviceThroughputRoute)
- .add(serviceTransactionGroupsRoute)
// Agent configuration
.add(getSingleAgentConfigurationRoute)
@@ -152,13 +150,13 @@ const createApmApi = () => {
.add(tracesByIdRoute)
.add(rootTransactionByTraceIdRoute)
- // Transaction groups
- .add(transactionGroupsBreakdownRoute)
- .add(transactionGroupsChartsRoute)
- .add(transactionGroupsDistributionRoute)
+ // Transactions
+ .add(transactionChartsBreakdownRoute)
+ .add(transactionChartsRoute)
+ .add(transactionChartsDistributionRoute)
+ .add(transactionChartsErrorRateRoute)
.add(transactionGroupsRoute)
- .add(transactionSampleForGroupRoute)
- .add(transactionGroupsErrorRateRoute)
+ .add(transactionGroupsOverviewRoute)
// UI filters
.add(errorGroupsLocalFiltersRoute)
diff --git a/x-pack/plugins/apm/server/routes/errors.ts b/x-pack/plugins/apm/server/routes/errors.ts
index 64864ec2258ba..c4bc70a92d9ee 100644
--- a/x-pack/plugins/apm/server/routes/errors.ts
+++ b/x-pack/plugins/apm/server/routes/errors.ts
@@ -7,7 +7,7 @@
import * as t from 'io-ts';
import { createRoute } from './create_route';
import { getErrorDistribution } from '../lib/errors/distribution/get_distribution';
-import { getErrorGroup } from '../lib/errors/get_error_group';
+import { getErrorGroupSample } from '../lib/errors/get_error_group_sample';
import { getErrorGroups } from '../lib/errors/get_error_groups';
import { setupRequest } from '../lib/helpers/setup_request';
import { uiFiltersRt, rangeRt } from './default_api_types';
@@ -56,7 +56,7 @@ export const errorGroupsRoute = createRoute({
handler: async ({ context, request }) => {
const setup = await setupRequest(context, request);
const { serviceName, groupId } = context.params.path;
- return getErrorGroup({ serviceName, groupId, setup });
+ return getErrorGroupSample({ serviceName, groupId, setup });
},
});
diff --git a/x-pack/plugins/apm/server/routes/services.ts b/x-pack/plugins/apm/server/routes/services.ts
index 4c5738ecef581..a82f1b64d5537 100644
--- a/x-pack/plugins/apm/server/routes/services.ts
+++ b/x-pack/plugins/apm/server/routes/services.ts
@@ -19,7 +19,6 @@ import { dateAsStringRt } from '../../common/runtime_types/date_as_string_rt';
import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions';
import { getServiceErrorGroups } from '../lib/services/get_service_error_groups';
import { toNumberRt } from '../../common/runtime_types/to_number_rt';
-import { getServiceTransactionGroups } from '../lib/services/get_service_transaction_groups';
import { getThroughput } from '../lib/services/get_throughput';
export const servicesRoute = createRoute({
@@ -276,52 +275,3 @@ export const serviceThroughputRoute = createRoute({
});
},
});
-
-export const serviceTransactionGroupsRoute = createRoute({
- endpoint: 'GET /api/apm/services/{serviceName}/overview_transaction_groups',
- params: t.type({
- path: t.type({ serviceName: t.string }),
- query: t.intersection([
- rangeRt,
- uiFiltersRt,
- t.type({
- size: toNumberRt,
- numBuckets: toNumberRt,
- pageIndex: toNumberRt,
- sortDirection: t.union([t.literal('asc'), t.literal('desc')]),
- sortField: t.union([
- t.literal('latency'),
- t.literal('throughput'),
- t.literal('errorRate'),
- t.literal('impact'),
- ]),
- }),
- ]),
- }),
- options: {
- tags: ['access:apm'],
- },
- handler: async ({ context, request }) => {
- const setup = await setupRequest(context, request);
-
- const searchAggregatedTransactions = await getSearchAggregatedTransactions(
- setup
- );
-
- const {
- path: { serviceName },
- query: { size, numBuckets, pageIndex, sortDirection, sortField },
- } = context.params;
-
- return getServiceTransactionGroups({
- setup,
- serviceName,
- pageIndex,
- searchAggregatedTransactions,
- size,
- sortDirection,
- sortField,
- numBuckets,
- });
- },
-});
diff --git a/x-pack/plugins/apm/server/routes/transaction_groups.ts b/x-pack/plugins/apm/server/routes/transactions/transactions_routes.ts
similarity index 62%
rename from x-pack/plugins/apm/server/routes/transaction_groups.ts
rename to x-pack/plugins/apm/server/routes/transactions/transactions_routes.ts
index 58c1ce3451a29..11d247ccab84f 100644
--- a/x-pack/plugins/apm/server/routes/transaction_groups.ts
+++ b/x-pack/plugins/apm/server/routes/transactions/transactions_routes.ts
@@ -4,21 +4,26 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import * as t from 'io-ts';
import Boom from '@hapi/boom';
-import { setupRequest } from '../lib/helpers/setup_request';
-import { getTransactionCharts } from '../lib/transactions/charts';
-import { getTransactionDistribution } from '../lib/transactions/distribution';
-import { getTransactionBreakdown } from '../lib/transactions/breakdown';
-import { getTransactionGroupList } from '../lib/transaction_groups';
-import { createRoute } from './create_route';
-import { uiFiltersRt, rangeRt } from './default_api_types';
-import { getTransactionSampleForGroup } from '../lib/transaction_groups/get_transaction_sample_for_group';
-import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions';
-import { getErrorRate } from '../lib/transaction_groups/get_error_rate';
+import * as t from 'io-ts';
+import { toNumberRt } from '../../../common/runtime_types/to_number_rt';
+import { getSearchAggregatedTransactions } from '../../lib/helpers/aggregated_transactions';
+import { setupRequest } from '../../lib/helpers/setup_request';
+import { getServiceTransactionGroups } from '../../lib/services/get_service_transaction_groups';
+import { getTransactionBreakdown } from '../../lib/transactions/breakdown';
+import { getTransactionCharts } from '../../lib/transactions/charts';
+import { getTransactionDistribution } from '../../lib/transactions/distribution';
+import { getTransactionGroupList } from '../../lib/transaction_groups';
+import { getErrorRate } from '../../lib/transaction_groups/get_error_rate';
+import { createRoute } from '../create_route';
+import { rangeRt, uiFiltersRt } from '../default_api_types';
+/**
+ * Returns a list of transactions grouped by name
+ * //TODO: delete this once we moved away from the old table in the transaction overview page. It should be replaced by /transactions/groups/overview/
+ */
export const transactionGroupsRoute = createRoute({
- endpoint: 'GET /api/apm/services/{serviceName}/transaction_groups',
+ endpoint: 'GET /api/apm/services/{serviceName}/transactions/groups',
params: t.type({
path: t.type({
serviceName: t.string,
@@ -53,8 +58,64 @@ export const transactionGroupsRoute = createRoute({
},
});
-export const transactionGroupsChartsRoute = createRoute({
- endpoint: 'GET /api/apm/services/{serviceName}/transaction_groups/charts',
+export const transactionGroupsOverviewRoute = createRoute({
+ endpoint: 'GET /api/apm/services/{serviceName}/transactions/groups/overview',
+ params: t.type({
+ path: t.type({ serviceName: t.string }),
+ query: t.intersection([
+ rangeRt,
+ uiFiltersRt,
+ t.type({
+ size: toNumberRt,
+ numBuckets: toNumberRt,
+ pageIndex: toNumberRt,
+ sortDirection: t.union([t.literal('asc'), t.literal('desc')]),
+ sortField: t.union([
+ t.literal('latency'),
+ t.literal('throughput'),
+ t.literal('errorRate'),
+ t.literal('impact'),
+ ]),
+ }),
+ ]),
+ }),
+ options: {
+ tags: ['access:apm'],
+ },
+ handler: async ({ context, request }) => {
+ const setup = await setupRequest(context, request);
+
+ const searchAggregatedTransactions = await getSearchAggregatedTransactions(
+ setup
+ );
+
+ const {
+ path: { serviceName },
+ query: { size, numBuckets, pageIndex, sortDirection, sortField },
+ } = context.params;
+
+ return getServiceTransactionGroups({
+ setup,
+ serviceName,
+ pageIndex,
+ searchAggregatedTransactions,
+ size,
+ sortDirection,
+ sortField,
+ numBuckets,
+ });
+ },
+});
+
+/**
+ * Returns timeseries for latency, throughput and anomalies
+ * TODO: break it into 3 new APIs:
+ * - Latency: /transactions/charts/latency
+ * - Throughput: /transactions/charts/throughput
+ * - anomalies: /transactions/charts/anomaly
+ */
+export const transactionChartsRoute = createRoute({
+ endpoint: 'GET /api/apm/services/{serviceName}/transactions/charts',
params: t.type({
path: t.type({
serviceName: t.string,
@@ -98,9 +159,9 @@ export const transactionGroupsChartsRoute = createRoute({
},
});
-export const transactionGroupsDistributionRoute = createRoute({
+export const transactionChartsDistributionRoute = createRoute({
endpoint:
- 'GET /api/apm/services/{serviceName}/transaction_groups/distribution',
+ 'GET /api/apm/services/{serviceName}/transactions/charts/distribution',
params: t.type({
path: t.type({
serviceName: t.string,
@@ -145,8 +206,8 @@ export const transactionGroupsDistributionRoute = createRoute({
},
});
-export const transactionGroupsBreakdownRoute = createRoute({
- endpoint: 'GET /api/apm/services/{serviceName}/transaction_groups/breakdown',
+export const transactionChartsBreakdownRoute = createRoute({
+ endpoint: 'GET /api/apm/services/{serviceName}/transaction/charts/breakdown',
params: t.type({
path: t.type({
serviceName: t.string,
@@ -177,33 +238,9 @@ export const transactionGroupsBreakdownRoute = createRoute({
},
});
-export const transactionSampleForGroupRoute = createRoute({
- endpoint: `GET /api/apm/transaction_sample`,
- params: t.type({
- query: t.intersection([
- uiFiltersRt,
- rangeRt,
- t.type({ serviceName: t.string, transactionName: t.string }),
- ]),
- }),
- options: { tags: ['access:apm'] },
- handler: async ({ context, request }) => {
- const setup = await setupRequest(context, request);
-
- const { transactionName, serviceName } = context.params.query;
-
- return {
- transaction: await getTransactionSampleForGroup({
- setup,
- serviceName,
- transactionName,
- }),
- };
- },
-});
-
-export const transactionGroupsErrorRateRoute = createRoute({
- endpoint: 'GET /api/apm/services/{serviceName}/transaction_groups/error_rate',
+export const transactionChartsErrorRateRoute = createRoute({
+ endpoint:
+ 'GET /api/apm/services/{serviceName}/transactions/charts/error_rate',
params: t.type({
path: t.type({
serviceName: t.string,
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/filters/time_filter/components/__stories__/__snapshots__/time_filter.stories.storyshot b/x-pack/plugins/canvas/canvas_plugin_src/renderers/filters/time_filter/components/__stories__/__snapshots__/time_filter.stories.storyshot
index 3fba41069253e..59771973f2aa5 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/filters/time_filter/components/__stories__/__snapshots__/time_filter.stories.storyshot
+++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/filters/time_filter/components/__stories__/__snapshots__/time_filter.stories.storyshot
@@ -23,11 +23,6 @@ exports[`Storyshots renderers/TimeFilter default 1`] = `
-
-
-
-
- Select an option:
-
- , is selected
-
-
-
-
-
-
-
-
-
-
+ />
`;
diff --git a/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset.stories.storyshot b/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset.stories.storyshot
index 05339ca558562..8194d923f34a5 100644
--- a/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset.stories.storyshot
+++ b/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset.stories.storyshot
@@ -18,7 +18,7 @@ exports[`Storyshots components/Assets/Asset airplane 1`] = `
className="canvasAsset__thumb canvasCheckered"
>
diff --git a/x-pack/plugins/canvas/public/components/workpad_header/edit_menu/__stories__/__snapshots__/edit_menu.stories.storyshot b/x-pack/plugins/canvas/public/components/workpad_header/edit_menu/__stories__/__snapshots__/edit_menu.stories.storyshot
index 93f4db664d1db..a242747f74362 100644
--- a/x-pack/plugins/canvas/public/components/workpad_header/edit_menu/__stories__/__snapshots__/edit_menu.stories.storyshot
+++ b/x-pack/plugins/canvas/public/components/workpad_header/edit_menu/__stories__/__snapshots__/edit_menu.stories.storyshot
@@ -3,11 +3,6 @@
exports[`Storyshots components/WorkpadHeader/EditMenu 2 elements selected 1`] = `
-
-
-
-
- Select an option:
-
- , is selected
-
-
-
-
-
-
-
-
-
-
+ />
@@ -436,11 +375,6 @@ exports[`Storyshots arguments/ContainerStyle extended 1`] = `
-
-
-
-
- Select an option:
-
- , is selected
-
-
-
-
-
-
-
-
-
-
+ />
@@ -905,11 +778,6 @@ exports[`Storyshots arguments/ContainerStyle/components border form 1`] = `
-
-
-
-
- Select an option:
-
- , is selected
-
-
-
-
-
-
-
-
-
-
+ />
@@ -1386,11 +1193,6 @@ exports[`Storyshots arguments/ContainerStyle/components extended template 1`] =
;
export type CasesFindResponse = rt.TypeOf
;
export type CasePatchRequest = rt.TypeOf;
export type CasesPatchRequest = rt.TypeOf;
-export type Status = rt.TypeOf;
export type CaseExternalServiceRequest = rt.TypeOf;
export type ServiceConnectorCaseParams = rt.TypeOf;
export type ServiceConnectorCaseResponse = rt.TypeOf;
diff --git a/x-pack/plugins/case/common/api/cases/status.ts b/x-pack/plugins/case/common/api/cases/status.ts
index 984181da8cdee..b812126dc1eab 100644
--- a/x-pack/plugins/case/common/api/cases/status.ts
+++ b/x-pack/plugins/case/common/api/cases/status.ts
@@ -8,6 +8,7 @@ import * as rt from 'io-ts';
export const CasesStatusResponseRt = rt.type({
count_open_cases: rt.number,
+ count_in_progress_cases: rt.number,
count_closed_cases: rt.number,
});
diff --git a/x-pack/plugins/case/server/client/cases/create.test.ts b/x-pack/plugins/case/server/client/cases/create.test.ts
index d82979de2cb44..e09ce226b3125 100644
--- a/x-pack/plugins/case/server/client/cases/create.test.ts
+++ b/x-pack/plugins/case/server/client/cases/create.test.ts
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { ConnectorTypes, CasePostRequest } from '../../../common/api';
+import { ConnectorTypes, CasePostRequest, CaseStatuses } from '../../../common/api';
import {
createMockSavedObjectsRepository,
@@ -60,7 +60,7 @@ describe('create', () => {
description: 'This is a brand new case of a bad meanie defacing data',
external_service: null,
title: 'Super Bad Security Issue',
- status: 'open',
+ status: CaseStatuses.open,
tags: ['defacement'],
updated_at: null,
updated_by: null,
@@ -126,7 +126,7 @@ describe('create', () => {
description: 'This is a brand new case of a bad meanie defacing data',
external_service: null,
title: 'Super Bad Security Issue',
- status: 'open',
+ status: CaseStatuses.open,
tags: ['defacement'],
updated_at: null,
updated_by: null,
@@ -169,7 +169,7 @@ describe('create', () => {
description: 'This is a brand new case of a bad meanie defacing data',
external_service: null,
title: 'Super Bad Security Issue',
- status: 'open',
+ status: CaseStatuses.open,
tags: ['defacement'],
updated_at: null,
updated_by: null,
@@ -316,7 +316,7 @@ describe('create', () => {
title: 'a title',
description: 'This is a brand new case of a bad meanie defacing data',
tags: ['defacement'],
- status: 'closed',
+ status: CaseStatuses.closed,
connector: {
id: 'none',
name: 'none',
diff --git a/x-pack/plugins/case/server/client/cases/update.test.ts b/x-pack/plugins/case/server/client/cases/update.test.ts
index 10eebd1210a9e..ae701f16b2bcb 100644
--- a/x-pack/plugins/case/server/client/cases/update.test.ts
+++ b/x-pack/plugins/case/server/client/cases/update.test.ts
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { ConnectorTypes, CasesPatchRequest } from '../../../common/api';
+import { ConnectorTypes, CasesPatchRequest, CaseStatuses } from '../../../common/api';
import {
createMockSavedObjectsRepository,
mockCaseNoConnectorId,
@@ -27,7 +27,7 @@ describe('update', () => {
cases: [
{
id: 'mock-id-1',
- status: 'closed' as const,
+ status: CaseStatuses.closed,
version: 'WzAsMV0=',
},
],
@@ -56,7 +56,7 @@ describe('update', () => {
description: 'This is a brand new case of a bad meanie defacing data',
id: 'mock-id-1',
external_service: null,
- status: 'closed',
+ status: CaseStatuses.closed,
tags: ['defacement'],
title: 'Super Bad Security Issue',
totalComment: 0,
@@ -79,8 +79,8 @@ describe('update', () => {
username: 'awesome',
},
action_field: ['status'],
- new_value: 'closed',
- old_value: 'open',
+ new_value: CaseStatuses.closed,
+ old_value: CaseStatuses.open,
},
references: [
{
@@ -98,7 +98,7 @@ describe('update', () => {
cases: [
{
id: 'mock-id-1',
- status: 'open' as const,
+ status: CaseStatuses.open,
version: 'WzAsMV0=',
},
],
@@ -106,7 +106,10 @@ describe('update', () => {
const savedObjectsClient = createMockSavedObjectsRepository({
caseSavedObject: [
- { ...mockCases[0], attributes: { ...mockCases[0].attributes, status: 'closed' } },
+ {
+ ...mockCases[0],
+ attributes: { ...mockCases[0].attributes, status: CaseStatuses.closed },
+ },
...mockCases.slice(1),
],
});
@@ -130,7 +133,7 @@ describe('update', () => {
description: 'This is a brand new case of a bad meanie defacing data',
id: 'mock-id-1',
external_service: null,
- status: 'open',
+ status: CaseStatuses.open,
tags: ['defacement'],
title: 'Super Bad Security Issue',
totalComment: 0,
@@ -146,7 +149,7 @@ describe('update', () => {
cases: [
{
id: 'mock-no-connector_id',
- status: 'closed' as const,
+ status: CaseStatuses.closed,
version: 'WzAsMV0=',
},
],
@@ -177,7 +180,7 @@ describe('update', () => {
description: 'This is a brand new case of a bad meanie defacing data',
external_service: null,
title: 'Super Bad Security Issue',
- status: 'closed',
+ status: CaseStatuses.closed,
tags: ['defacement'],
updated_at: '2019-11-25T21:54:48.952Z',
updated_by: { email: 'd00d@awesome.com', full_name: 'Awesome D00d', username: 'awesome' },
@@ -231,7 +234,7 @@ describe('update', () => {
description: 'Oh no, a bad meanie going LOLBins all over the place!',
external_service: null,
title: 'Another bad one',
- status: 'open',
+ status: CaseStatuses.open,
tags: ['LOLBins'],
updated_at: '2019-11-25T21:54:48.952Z',
updated_by: {
@@ -314,7 +317,7 @@ describe('update', () => {
cases: [
{
id: 'mock-id-1',
- status: 'open' as const,
+ status: CaseStatuses.open,
version: 'WzAsMV0=',
},
],
diff --git a/x-pack/plugins/case/server/client/cases/update.ts b/x-pack/plugins/case/server/client/cases/update.ts
index a754ce27c5e41..406e43a74cccf 100644
--- a/x-pack/plugins/case/server/client/cases/update.ts
+++ b/x-pack/plugins/case/server/client/cases/update.ts
@@ -19,6 +19,7 @@ import {
ESCasePatchRequest,
CasePatchRequest,
CasesResponse,
+ CaseStatuses,
} from '../../../common/api';
import { buildCaseUserActions } from '../../services/user_actions/helpers';
import {
@@ -98,12 +99,15 @@ export const update = ({
cases: updateFilterCases.map((thisCase) => {
const { id: caseId, version, ...updateCaseAttributes } = thisCase;
let closedInfo = {};
- if (updateCaseAttributes.status && updateCaseAttributes.status === 'closed') {
+ if (updateCaseAttributes.status && updateCaseAttributes.status === CaseStatuses.closed) {
closedInfo = {
closed_at: updatedDt,
closed_by: { email, full_name, username },
};
- } else if (updateCaseAttributes.status && updateCaseAttributes.status === 'open') {
+ } else if (
+ updateCaseAttributes.status &&
+ updateCaseAttributes.status === CaseStatuses.open
+ ) {
closedInfo = {
closed_at: null,
closed_by: null,
diff --git a/x-pack/plugins/case/server/connectors/case/index.test.ts b/x-pack/plugins/case/server/connectors/case/index.test.ts
index 90bb1d604e733..adf94661216cb 100644
--- a/x-pack/plugins/case/server/connectors/case/index.test.ts
+++ b/x-pack/plugins/case/server/connectors/case/index.test.ts
@@ -9,7 +9,7 @@ import { Logger } from '../../../../../../src/core/server';
import { loggingSystemMock } from '../../../../../../src/core/server/mocks';
import { actionsMock } from '../../../../actions/server/mocks';
import { validateParams } from '../../../../actions/server/lib';
-import { ConnectorTypes, CommentType } from '../../../common/api';
+import { ConnectorTypes, CommentType, CaseStatuses } from '../../../common/api';
import {
createCaseServiceMock,
createConfigureServiceMock,
@@ -785,7 +785,7 @@ describe('case connector', () => {
tags: ['case', 'connector'],
description: 'Yo fields!!',
external_service: null,
- status: 'open' as const,
+ status: CaseStatuses.open,
updated_at: null,
updated_by: null,
version: 'WzksMV0=',
@@ -868,7 +868,7 @@ describe('case connector', () => {
description: 'This is a brand new case of a bad meanie defacing data',
id: 'mock-id-1',
external_service: null,
- status: 'open' as const,
+ status: CaseStatuses.open,
tags: ['defacement'],
title: 'Update title',
totalComment: 0,
@@ -937,7 +937,7 @@ describe('case connector', () => {
description: 'This is a brand new case of a bad meanie defacing data',
external_service: null,
title: 'Super Bad Security Issue',
- status: 'open' as const,
+ status: CaseStatuses.open,
tags: ['defacement'],
updated_at: null,
updated_by: null,
diff --git a/x-pack/plugins/case/server/routes/api/__fixtures__/mock_saved_objects.ts b/x-pack/plugins/case/server/routes/api/__fixtures__/mock_saved_objects.ts
index 4c0b5887ca998..95856dd75d0ae 100644
--- a/x-pack/plugins/case/server/routes/api/__fixtures__/mock_saved_objects.ts
+++ b/x-pack/plugins/case/server/routes/api/__fixtures__/mock_saved_objects.ts
@@ -11,6 +11,7 @@ import {
ESCaseAttributes,
ConnectorTypes,
CommentType,
+ CaseStatuses,
} from '../../../../common/api';
export const mockCases: Array> = [
@@ -35,7 +36,7 @@ export const mockCases: Array> = [
description: 'This is a brand new case of a bad meanie defacing data',
external_service: null,
title: 'Super Bad Security Issue',
- status: 'open',
+ status: CaseStatuses.open,
tags: ['defacement'],
updated_at: '2019-11-25T21:54:48.952Z',
updated_by: {
@@ -69,7 +70,7 @@ export const mockCases: Array> = [
description: 'Oh no, a bad meanie destroying data!',
external_service: null,
title: 'Damaging Data Destruction Detected',
- status: 'open',
+ status: CaseStatuses.open,
tags: ['Data Destruction'],
updated_at: '2019-11-25T22:32:00.900Z',
updated_by: {
@@ -107,7 +108,7 @@ export const mockCases: Array> = [
description: 'Oh no, a bad meanie going LOLBins all over the place!',
external_service: null,
title: 'Another bad one',
- status: 'open',
+ status: CaseStatuses.open,
tags: ['LOLBins'],
updated_at: '2019-11-25T22:32:17.947Z',
updated_by: {
@@ -148,7 +149,7 @@ export const mockCases: Array> = [
},
description: 'Oh no, a bad meanie going LOLBins all over the place!',
external_service: null,
- status: 'closed',
+ status: CaseStatuses.closed,
title: 'Another bad one',
tags: ['LOLBins'],
updated_at: '2019-11-25T22:32:17.947Z',
@@ -179,7 +180,7 @@ export const mockCaseNoConnectorId: SavedObject> = {
description: 'This is a brand new case of a bad meanie defacing data',
external_service: null,
title: 'Super Bad Security Issue',
- status: 'open',
+ status: CaseStatuses.open,
tags: ['defacement'],
updated_at: '2019-11-25T21:54:48.952Z',
updated_by: {
diff --git a/x-pack/plugins/case/server/routes/api/cases/find_cases.test.ts b/x-pack/plugins/case/server/routes/api/cases/find_cases.test.ts
index b2ba8b2fcb33a..dca94589bf72a 100644
--- a/x-pack/plugins/case/server/routes/api/cases/find_cases.test.ts
+++ b/x-pack/plugins/case/server/routes/api/cases/find_cases.test.ts
@@ -38,6 +38,10 @@ describe('FIND all cases', () => {
const response = await routeHandler(theContext, request, kibanaResponseFactory);
expect(response.status).toEqual(200);
expect(response.payload.cases).toHaveLength(4);
+ // mockSavedObjectsRepository do not support filters and returns all cases every time.
+ expect(response.payload.count_open_cases).toEqual(4);
+ expect(response.payload.count_closed_cases).toEqual(4);
+ expect(response.payload.count_in_progress_cases).toEqual(4);
});
it(`has proper connector id on cases with configured connector`, async () => {
diff --git a/x-pack/plugins/case/server/routes/api/cases/find_cases.ts b/x-pack/plugins/case/server/routes/api/cases/find_cases.ts
index e70225456d5a8..b034e86b4f0d4 100644
--- a/x-pack/plugins/case/server/routes/api/cases/find_cases.ts
+++ b/x-pack/plugins/case/server/routes/api/cases/find_cases.ts
@@ -11,7 +11,13 @@ import { fold } from 'fp-ts/lib/Either';
import { identity } from 'fp-ts/lib/function';
import { isEmpty } from 'lodash';
-import { CasesFindResponseRt, CasesFindRequestRt, throwErrors } from '../../../../common/api';
+import {
+ CasesFindResponseRt,
+ CasesFindRequestRt,
+ throwErrors,
+ CaseStatuses,
+ caseStatuses,
+} from '../../../../common/api';
import { transformCases, sortToSnake, wrapError, escapeHatch } from '../utils';
import { RouteDeps, TotalCommentByCase } from '../types';
import { CASE_SAVED_OBJECT } from '../../../saved_object_types';
@@ -20,7 +26,7 @@ import { CASES_URL } from '../../../../common/constants';
const combineFilters = (filters: string[], operator: 'OR' | 'AND'): string =>
filters?.filter((i) => i !== '').join(` ${operator} `);
-const getStatusFilter = (status: 'open' | 'closed', appendFilter?: string) =>
+const getStatusFilter = (status: CaseStatuses, appendFilter?: string) =>
`${CASE_SAVED_OBJECT}.attributes.status: ${status}${
!isEmpty(appendFilter) ? ` AND ${appendFilter}` : ''
}`;
@@ -75,30 +81,21 @@ export function initFindCasesApi({ caseService, caseConfigureService, router }:
client,
};
- const argsOpenCases = {
+ const statusArgs = caseStatuses.map((caseStatus) => ({
client,
options: {
fields: [],
page: 1,
perPage: 1,
- filter: getStatusFilter('open', myFilters),
+ filter: getStatusFilter(caseStatus, myFilters),
},
- };
+ }));
- const argsClosedCases = {
- client,
- options: {
- fields: [],
- page: 1,
- perPage: 1,
- filter: getStatusFilter('closed', myFilters),
- },
- };
- const [cases, openCases, closesCases] = await Promise.all([
+ const [cases, openCases, inProgressCases, closedCases] = await Promise.all([
caseService.findCases(args),
- caseService.findCases(argsOpenCases),
- caseService.findCases(argsClosedCases),
+ ...statusArgs.map((arg) => caseService.findCases(arg)),
]);
+
const totalCommentsFindByCases = await Promise.all(
cases.saved_objects.map((c) =>
caseService.getAllCaseComments({
@@ -133,7 +130,8 @@ export function initFindCasesApi({ caseService, caseConfigureService, router }:
transformCases(
cases,
openCases.total ?? 0,
- closesCases.total ?? 0,
+ inProgressCases.total ?? 0,
+ closedCases.total ?? 0,
totalCommentsByCases
)
),
diff --git a/x-pack/plugins/case/server/routes/api/cases/patch_cases.test.ts b/x-pack/plugins/case/server/routes/api/cases/patch_cases.test.ts
index ea69ee77c5802..053f9ec18ab0f 100644
--- a/x-pack/plugins/case/server/routes/api/cases/patch_cases.test.ts
+++ b/x-pack/plugins/case/server/routes/api/cases/patch_cases.test.ts
@@ -16,7 +16,7 @@ import {
} from '../__fixtures__';
import { initPatchCasesApi } from './patch_cases';
import { mockCaseConfigure, mockCaseNoConnectorId } from '../__fixtures__/mock_saved_objects';
-import { ConnectorTypes } from '../../../../common/api/connectors';
+import { ConnectorTypes, CaseStatuses } from '../../../../common/api';
describe('PATCH cases', () => {
let routeHandler: RequestHandler;
@@ -36,7 +36,7 @@ describe('PATCH cases', () => {
cases: [
{
id: 'mock-id-1',
- status: 'closed',
+ status: CaseStatuses.closed,
version: 'WzAsMV0=',
},
],
@@ -67,7 +67,7 @@ describe('PATCH cases', () => {
description: 'This is a brand new case of a bad meanie defacing data',
id: 'mock-id-1',
external_service: null,
- status: 'closed',
+ status: CaseStatuses.closed,
tags: ['defacement'],
title: 'Super Bad Security Issue',
totalComment: 0,
@@ -86,7 +86,7 @@ describe('PATCH cases', () => {
cases: [
{
id: 'mock-id-4',
- status: 'open',
+ status: CaseStatuses.open,
version: 'WzUsMV0=',
},
],
@@ -118,7 +118,7 @@ describe('PATCH cases', () => {
description: 'Oh no, a bad meanie going LOLBins all over the place!',
id: 'mock-id-4',
external_service: null,
- status: 'open',
+ status: CaseStatuses.open,
tags: ['LOLBins'],
title: 'Another bad one',
totalComment: 0,
@@ -129,6 +129,56 @@ describe('PATCH cases', () => {
]);
});
+ it(`Change case to in-progress`, async () => {
+ const request = httpServerMock.createKibanaRequest({
+ path: '/api/cases',
+ method: 'patch',
+ body: {
+ cases: [
+ {
+ id: 'mock-id-1',
+ status: CaseStatuses['in-progress'],
+ version: 'WzAsMV0=',
+ },
+ ],
+ },
+ });
+
+ const theContext = await createRouteContext(
+ createMockSavedObjectsRepository({
+ caseSavedObject: mockCases,
+ })
+ );
+
+ const response = await routeHandler(theContext, request, kibanaResponseFactory);
+ expect(response.status).toEqual(200);
+ expect(response.payload).toEqual([
+ {
+ closed_at: null,
+ closed_by: null,
+ comments: [],
+ connector: {
+ id: 'none',
+ name: 'none',
+ type: ConnectorTypes.none,
+ fields: null,
+ },
+ created_at: '2019-11-25T21:54:48.952Z',
+ created_by: { email: 'testemail@elastic.co', full_name: 'elastic', username: 'elastic' },
+ description: 'This is a brand new case of a bad meanie defacing data',
+ id: 'mock-id-1',
+ external_service: null,
+ status: CaseStatuses['in-progress'],
+ tags: ['defacement'],
+ title: 'Super Bad Security Issue',
+ totalComment: 0,
+ updated_at: '2019-11-25T21:54:48.952Z',
+ updated_by: { email: 'd00d@awesome.com', full_name: 'Awesome D00d', username: 'awesome' },
+ version: 'WzE3LDFd',
+ },
+ ]);
+ });
+
it(`Patches a case without a connector.id`, async () => {
const request = httpServerMock.createKibanaRequest({
path: '/api/cases',
@@ -137,7 +187,7 @@ describe('PATCH cases', () => {
cases: [
{
id: 'mock-no-connector_id',
- status: 'closed',
+ status: CaseStatuses.closed,
version: 'WzAsMV0=',
},
],
@@ -163,7 +213,7 @@ describe('PATCH cases', () => {
cases: [
{
id: 'mock-id-3',
- status: 'closed',
+ status: CaseStatuses.closed,
version: 'WzUsMV0=',
},
],
@@ -225,7 +275,7 @@ describe('PATCH cases', () => {
cases: [
{
id: 'mock-id-1',
- case: { status: 'closed' },
+ case: { status: CaseStatuses.closed },
version: 'badv=',
},
],
@@ -250,7 +300,7 @@ describe('PATCH cases', () => {
cases: [
{
id: 'mock-id-1',
- case: { status: 'open' },
+ case: { status: CaseStatuses.open },
version: 'WzAsMV0=',
},
],
@@ -276,7 +326,7 @@ describe('PATCH cases', () => {
cases: [
{
id: 'mock-id-does-not-exist',
- status: 'closed',
+ status: CaseStatuses.closed,
version: 'WzAsMV0=',
},
],
diff --git a/x-pack/plugins/case/server/routes/api/cases/post_case.test.ts b/x-pack/plugins/case/server/routes/api/cases/post_case.test.ts
index 1e1b19baa1c47..508684b422891 100644
--- a/x-pack/plugins/case/server/routes/api/cases/post_case.test.ts
+++ b/x-pack/plugins/case/server/routes/api/cases/post_case.test.ts
@@ -16,7 +16,7 @@ import {
import { initPostCaseApi } from './post_case';
import { CASES_URL } from '../../../../common/constants';
import { mockCaseConfigure } from '../__fixtures__/mock_saved_objects';
-import { ConnectorTypes } from '../../../../common/api/connectors';
+import { ConnectorTypes, CaseStatuses } from '../../../../common/api';
describe('POST cases', () => {
let routeHandler: RequestHandler;
@@ -54,6 +54,7 @@ describe('POST cases', () => {
const response = await routeHandler(theContext, request, kibanaResponseFactory);
expect(response.status).toEqual(200);
expect(response.payload.id).toEqual('mock-it');
+ expect(response.payload.status).toEqual('open');
expect(response.payload.created_by.username).toEqual('awesome');
expect(response.payload.connector).toEqual({
id: 'none',
@@ -104,7 +105,7 @@ describe('POST cases', () => {
body: {
description: 'This is a brand new case of a bad meanie defacing data',
title: 'Super Bad Security Issue',
- status: 'open',
+ status: CaseStatuses.open,
tags: ['defacement'],
connector: null,
},
@@ -191,7 +192,7 @@ describe('POST cases', () => {
description: 'This is a brand new case of a bad meanie defacing data',
external_service: null,
id: 'mock-it',
- status: 'open',
+ status: CaseStatuses.open,
tags: ['defacement'],
title: 'Super Bad Security Issue',
totalComment: 0,
diff --git a/x-pack/plugins/case/server/routes/api/cases/push_case.ts b/x-pack/plugins/case/server/routes/api/cases/push_case.ts
index 6ba2da111090f..6a6b09dc3f87a 100644
--- a/x-pack/plugins/case/server/routes/api/cases/push_case.ts
+++ b/x-pack/plugins/case/server/routes/api/cases/push_case.ts
@@ -18,7 +18,12 @@ import {
getCommentContextFromAttributes,
} from '../utils';
-import { CaseExternalServiceRequestRt, CaseResponseRt, throwErrors } from '../../../../common/api';
+import {
+ CaseExternalServiceRequestRt,
+ CaseResponseRt,
+ throwErrors,
+ CaseStatuses,
+} from '../../../../common/api';
import { buildCaseUserActionItem } from '../../../services/user_actions/helpers';
import { RouteDeps } from '../types';
import { CASE_DETAILS_URL } from '../../../../common/constants';
@@ -77,7 +82,7 @@ export function initPushCaseUserActionApi({
actionsClient.getAll(),
]);
- if (myCase.attributes.status === 'closed') {
+ if (myCase.attributes.status === CaseStatuses.closed) {
throw Boom.conflict(
`This case ${myCase.attributes.title} is closed. You can not pushed if the case is closed.`
);
@@ -117,7 +122,7 @@ export function initPushCaseUserActionApi({
...(myCaseConfigure.total > 0 &&
myCaseConfigure.saved_objects[0].attributes.closure_type === 'close-by-pushing'
? {
- status: 'closed',
+ status: CaseStatuses.closed,
closed_at: pushedDate,
closed_by: { email, full_name, username },
}
@@ -153,7 +158,7 @@ export function initPushCaseUserActionApi({
actionBy: { username, full_name, email },
caseId,
fields: ['status'],
- newValue: 'closed',
+ newValue: CaseStatuses.closed,
oldValue: myCase.attributes.status,
}),
]
diff --git a/x-pack/plugins/case/server/routes/api/cases/status/get_status.ts b/x-pack/plugins/case/server/routes/api/cases/status/get_status.ts
index 8f86dbc91f315..4379a6b56367c 100644
--- a/x-pack/plugins/case/server/routes/api/cases/status/get_status.ts
+++ b/x-pack/plugins/case/server/routes/api/cases/status/get_status.ts
@@ -7,7 +7,7 @@
import { RouteDeps } from '../../types';
import { wrapError } from '../../utils';
-import { CasesStatusResponseRt } from '../../../../../common/api';
+import { CasesStatusResponseRt, caseStatuses } from '../../../../../common/api';
import { CASE_SAVED_OBJECT } from '../../../../saved_object_types';
import { CASE_STATUS_URL } from '../../../../../common/constants';
@@ -20,34 +20,24 @@ export function initGetCasesStatusApi({ caseService, router }: RouteDeps) {
async (context, request, response) => {
try {
const client = context.core.savedObjects.client;
- const argsOpenCases = {
+ const args = caseStatuses.map((status) => ({
client,
options: {
fields: [],
page: 1,
perPage: 1,
- filter: `${CASE_SAVED_OBJECT}.attributes.status: open`,
+ filter: `${CASE_SAVED_OBJECT}.attributes.status: ${status}`,
},
- };
+ }));
- const argsClosedCases = {
- client,
- options: {
- fields: [],
- page: 1,
- perPage: 1,
- filter: `${CASE_SAVED_OBJECT}.attributes.status: closed`,
- },
- };
-
- const [openCases, closesCases] = await Promise.all([
- caseService.findCases(argsOpenCases),
- caseService.findCases(argsClosedCases),
- ]);
+ const [openCases, inProgressCases, closesCases] = await Promise.all(
+ args.map((arg) => caseService.findCases(arg))
+ );
return response.ok({
body: CasesStatusResponseRt.encode({
count_open_cases: openCases.total,
+ count_in_progress_cases: inProgressCases.total,
count_closed_cases: closesCases.total,
}),
});
diff --git a/x-pack/plugins/case/server/routes/api/utils.test.ts b/x-pack/plugins/case/server/routes/api/utils.test.ts
index a67bae5ed74dc..7654ae5ff0d1a 100644
--- a/x-pack/plugins/case/server/routes/api/utils.test.ts
+++ b/x-pack/plugins/case/server/routes/api/utils.test.ts
@@ -23,7 +23,7 @@ import {
mockCaseComments,
mockCaseNoConnectorId,
} from './__fixtures__/mock_saved_objects';
-import { ConnectorTypes, ESCaseConnector, CommentType } from '../../../common/api';
+import { ConnectorTypes, ESCaseConnector, CommentType, CaseStatuses } from '../../../common/api';
describe('Utils', () => {
describe('transformNewCase', () => {
@@ -57,7 +57,7 @@ describe('Utils', () => {
created_at: '2020-04-09T09:43:51.778Z',
created_by: { email: 'elastic@elastic.co', full_name: 'Elastic', username: 'elastic' },
external_service: null,
- status: 'open',
+ status: CaseStatuses.open,
updated_at: null,
updated_by: null,
});
@@ -80,7 +80,7 @@ describe('Utils', () => {
created_at: '2020-04-09T09:43:51.778Z',
created_by: { email: undefined, full_name: undefined, username: undefined },
external_service: null,
- status: 'open',
+ status: CaseStatuses.open,
updated_at: null,
updated_by: null,
});
@@ -106,7 +106,7 @@ describe('Utils', () => {
created_at: '2020-04-09T09:43:51.778Z',
created_by: { email: null, full_name: null, username: null },
external_service: null,
- status: 'open',
+ status: CaseStatuses.open,
updated_at: null,
updated_by: null,
});
@@ -247,6 +247,7 @@ describe('Utils', () => {
},
2,
2,
+ 2,
extraCaseData
);
expect(res).toEqual({
@@ -259,6 +260,7 @@ describe('Utils', () => {
),
count_open_cases: 2,
count_closed_cases: 2,
+ count_in_progress_cases: 2,
});
});
});
@@ -289,7 +291,7 @@ describe('Utils', () => {
description: 'This is a brand new case of a bad meanie defacing data',
external_service: null,
title: 'Super Bad Security Issue',
- status: 'open',
+ status: CaseStatuses.open,
tags: ['defacement'],
updated_at: '2019-11-25T21:54:48.952Z',
updated_by: {
@@ -328,7 +330,7 @@ describe('Utils', () => {
description: 'This is a brand new case of a bad meanie defacing data',
external_service: null,
title: 'Super Bad Security Issue',
- status: 'open',
+ status: CaseStatuses.open,
tags: ['defacement'],
updated_at: '2019-11-25T21:54:48.952Z',
updated_by: {
@@ -374,7 +376,7 @@ describe('Utils', () => {
description: 'This is a brand new case of a bad meanie defacing data',
external_service: null,
title: 'Super Bad Security Issue',
- status: 'open',
+ status: CaseStatuses.open,
tags: ['defacement'],
updated_at: '2019-11-25T21:54:48.952Z',
updated_by: {
@@ -484,7 +486,7 @@ describe('Utils', () => {
description: 'This is a brand new case of a bad meanie defacing data',
external_service: null,
title: 'Super Bad Security Issue',
- status: 'open',
+ status: CaseStatuses.open,
tags: ['defacement'],
updated_at: '2019-11-25T21:54:48.952Z',
updated_by: {
diff --git a/x-pack/plugins/case/server/routes/api/utils.ts b/x-pack/plugins/case/server/routes/api/utils.ts
index 589d7c02a7be6..c8753772648c2 100644
--- a/x-pack/plugins/case/server/routes/api/utils.ts
+++ b/x-pack/plugins/case/server/routes/api/utils.ts
@@ -33,6 +33,7 @@ import {
CommentType,
excess,
throwErrors,
+ CaseStatuses,
} from '../../../common/api';
import { transformESConnectorToCaseConnector } from './cases/helpers';
@@ -61,7 +62,7 @@ export const transformNewCase = ({
created_at: createdDate,
created_by: { email, full_name, username },
external_service: null,
- status: 'open',
+ status: CaseStatuses.open,
updated_at: null,
updated_by: null,
});
@@ -103,6 +104,7 @@ export function wrapError(error: any): CustomHttpResponseOptions
export const transformCases = (
cases: SavedObjectsFindResponse,
countOpenCases: number,
+ countInProgressCases: number,
countClosedCases: number,
totalCommentByCase: TotalCommentByCase[]
): CasesFindResponse => ({
@@ -111,6 +113,7 @@ export const transformCases = (
total: cases.total,
cases: flattenCaseSavedObjects(cases.saved_objects, totalCommentByCase),
count_open_cases: countOpenCases,
+ count_in_progress_cases: countInProgressCases,
count_closed_cases: countClosedCases,
});
diff --git a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_object_type_definition.test.ts b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_object_type_definition.test.ts
index f1e06a0cec03d..f528843cf9ea3 100644
--- a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_object_type_definition.test.ts
+++ b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_object_type_definition.test.ts
@@ -113,18 +113,3 @@ it('correctly determines attribute properties', () => {
}
}
});
-
-it('it correctly sets allowPredefinedID', () => {
- const defaultTypeDefinition = new EncryptedSavedObjectAttributesDefinition({
- type: 'so-type',
- attributesToEncrypt: new Set(['attr#1', 'attr#2']),
- });
- expect(defaultTypeDefinition.allowPredefinedID).toBe(false);
-
- const typeDefinitionWithPredefinedIDAllowed = new EncryptedSavedObjectAttributesDefinition({
- type: 'so-type',
- attributesToEncrypt: new Set(['attr#1', 'attr#2']),
- allowPredefinedID: true,
- });
- expect(typeDefinitionWithPredefinedIDAllowed.allowPredefinedID).toBe(true);
-});
diff --git a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_object_type_definition.ts b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_object_type_definition.ts
index 398a64585411a..849a2888b6e1a 100644
--- a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_object_type_definition.ts
+++ b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_object_type_definition.ts
@@ -15,7 +15,6 @@ export class EncryptedSavedObjectAttributesDefinition {
public readonly attributesToEncrypt: ReadonlySet;
private readonly attributesToExcludeFromAAD: ReadonlySet | undefined;
private readonly attributesToStrip: ReadonlySet;
- public readonly allowPredefinedID: boolean;
constructor(typeRegistration: EncryptedSavedObjectTypeRegistration) {
const attributesToEncrypt = new Set();
@@ -35,7 +34,6 @@ export class EncryptedSavedObjectAttributesDefinition {
this.attributesToEncrypt = attributesToEncrypt;
this.attributesToStrip = attributesToStrip;
this.attributesToExcludeFromAAD = typeRegistration.attributesToExcludeFromAAD;
- this.allowPredefinedID = !!typeRegistration.allowPredefinedID;
}
/**
diff --git a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.mocks.ts b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.mocks.ts
index 0138e929ca1ca..c692d8698771f 100644
--- a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.mocks.ts
+++ b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.mocks.ts
@@ -13,7 +13,6 @@ import {
function createEncryptedSavedObjectsServiceMock() {
return ({
isRegistered: jest.fn(),
- canSpecifyID: jest.fn(),
stripOrDecryptAttributes: jest.fn(),
encryptAttributes: jest.fn(),
decryptAttributes: jest.fn(),
@@ -53,12 +52,6 @@ export const encryptedSavedObjectsServiceMock = {
mock.isRegistered.mockImplementation(
(type) => registrations.findIndex((r) => r.type === type) >= 0
);
- mock.canSpecifyID.mockImplementation((type, version, overwrite) => {
- const registration = registrations.find((r) => r.type === type);
- return (
- registration === undefined || registration.allowPredefinedID || !!(version && overwrite)
- );
- });
mock.encryptAttributes.mockImplementation(async (descriptor, attrs) =>
processAttributes(
descriptor,
diff --git a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.test.ts b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.test.ts
index 6bc4a392064e4..88d57072697fe 100644
--- a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.test.ts
+++ b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.test.ts
@@ -89,45 +89,6 @@ describe('#isRegistered', () => {
});
});
-describe('#canSpecifyID', () => {
- it('returns true for unknown types', () => {
- expect(service.canSpecifyID('unknown-type')).toBe(true);
- });
-
- it('returns true for types registered setting allowPredefinedID to true', () => {
- service.registerType({
- type: 'known-type-1',
- attributesToEncrypt: new Set(['attr-1']),
- allowPredefinedID: true,
- });
- expect(service.canSpecifyID('known-type-1')).toBe(true);
- });
-
- it('returns true when overwriting a saved object with a version specified even when allowPredefinedID is not set', () => {
- service.registerType({
- type: 'known-type-1',
- attributesToEncrypt: new Set(['attr-1']),
- });
- expect(service.canSpecifyID('known-type-1', '2', true)).toBe(true);
- expect(service.canSpecifyID('known-type-1', '2', false)).toBe(false);
- expect(service.canSpecifyID('known-type-1', undefined, true)).toBe(false);
- });
-
- it('returns false for types registered without setting allowPredefinedID', () => {
- service.registerType({ type: 'known-type-1', attributesToEncrypt: new Set(['attr-1']) });
- expect(service.canSpecifyID('known-type-1')).toBe(false);
- });
-
- it('returns false for types registered setting allowPredefinedID to false', () => {
- service.registerType({
- type: 'known-type-1',
- attributesToEncrypt: new Set(['attr-1']),
- allowPredefinedID: false,
- });
- expect(service.canSpecifyID('known-type-1')).toBe(false);
- });
-});
-
describe('#stripOrDecryptAttributes', () => {
it('does not strip attributes from unknown types', async () => {
const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three' };
diff --git a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.ts b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.ts
index 8d2ebb575c35e..1f1093a179538 100644
--- a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.ts
+++ b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.ts
@@ -31,7 +31,6 @@ export interface EncryptedSavedObjectTypeRegistration {
readonly type: string;
readonly attributesToEncrypt: ReadonlySet;
readonly attributesToExcludeFromAAD?: ReadonlySet