[APM] Use apmEventClient for querying APM event indices (#73449)
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
dbb603f979
commit
c66ea65ec1
|
@ -8,4 +8,18 @@ export enum ProcessorEvent {
|
|||
transaction = 'transaction',
|
||||
error = 'error',
|
||||
metric = 'metric',
|
||||
span = 'span',
|
||||
onboarding = 'onboarding',
|
||||
sourcemap = 'sourcemap',
|
||||
}
|
||||
/**
|
||||
* Processor events that are searchable in the UI via the query bar.
|
||||
*
|
||||
* Some client-sideroutes will define 1 or more processor events that
|
||||
* will be used to fetch the dynamic index pattern for the query bar.
|
||||
*/
|
||||
|
||||
export type UIProcessorEvent =
|
||||
| ProcessorEvent.transaction
|
||||
| ProcessorEvent.error
|
||||
| ProcessorEvent.metric;
|
||||
|
|
16
x-pack/plugins/apm/common/projections.ts
Normal file
16
x-pack/plugins/apm/common/projections.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export enum Projection {
|
||||
services = 'services',
|
||||
transactionGroups = 'transactionGroups',
|
||||
traces = 'traces',
|
||||
transactions = 'transactions',
|
||||
metrics = 'metrics',
|
||||
errorGroups = 'errorGroups',
|
||||
serviceNodes = 'serviceNodes',
|
||||
rumOverview = 'rumOverview',
|
||||
}
|
|
@ -1,64 +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 {
|
||||
Setup,
|
||||
SetupUIFilters,
|
||||
SetupTimeRange,
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
} from '../../server/lib/helpers/setup_request';
|
||||
import { SERVICE_NAME, PROCESSOR_EVENT } from '../elasticsearch_fieldnames';
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { rangeFilter } from '../utils/range_filter';
|
||||
|
||||
export function getServicesProjection({
|
||||
setup,
|
||||
noEvents,
|
||||
}: {
|
||||
setup: Setup & SetupTimeRange & SetupUIFilters;
|
||||
noEvents?: boolean;
|
||||
}) {
|
||||
const { start, end, uiFiltersES, indices } = setup;
|
||||
|
||||
return {
|
||||
...(noEvents
|
||||
? {}
|
||||
: {
|
||||
index: [
|
||||
indices['apm_oss.metricsIndices'],
|
||||
indices['apm_oss.errorIndices'],
|
||||
indices['apm_oss.transactionIndices'],
|
||||
],
|
||||
}),
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
...(noEvents
|
||||
? []
|
||||
: [
|
||||
{
|
||||
terms: {
|
||||
[PROCESSOR_EVENT]: ['transaction', 'error', 'metric'],
|
||||
},
|
||||
},
|
||||
]),
|
||||
{ range: rangeFilter(start, end) },
|
||||
...uiFiltersES,
|
||||
],
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
services: {
|
||||
terms: {
|
||||
field: SERVICE_NAME,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
|
@ -14,7 +14,7 @@ import {
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useTrackPageview } from '../../../../../observability/public';
|
||||
import { PROJECTION } from '../../../../common/projections/typings';
|
||||
import { Projection } from '../../../../common/projections';
|
||||
import { useFetcher } from '../../../hooks/useFetcher';
|
||||
import { useUrlParams } from '../../../hooks/useUrlParams';
|
||||
import { callApmApi } from '../../../services/rest/createCallApmApi';
|
||||
|
@ -79,7 +79,7 @@ function ErrorGroupOverview() {
|
|||
params: {
|
||||
serviceName,
|
||||
},
|
||||
projection: PROJECTION.ERROR_GROUPS,
|
||||
projection: Projection.errorGroups,
|
||||
};
|
||||
|
||||
return config;
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { useTrackPageview } from '../../../../../observability/public';
|
||||
import { LocalUIFilters } from '../../shared/LocalUIFilters';
|
||||
import { PROJECTION } from '../../../../common/projections/typings';
|
||||
import { Projection } from '../../../../common/projections';
|
||||
import { RumDashboard } from './RumDashboard';
|
||||
import { ServiceNameFilter } from '../../shared/LocalUIFilters/ServiceNameFilter';
|
||||
import { useUrlParams } from '../../../hooks/useUrlParams';
|
||||
|
@ -28,7 +28,7 @@ export function RumOverview() {
|
|||
const localUIFiltersConfig = useMemo(() => {
|
||||
const config: React.ComponentProps<typeof LocalUIFilters> = {
|
||||
filterNames: ['transactionUrl', 'location', 'device', 'os', 'browser'],
|
||||
projection: PROJECTION.RUM_OVERVIEW,
|
||||
projection: Projection.rumOverview,
|
||||
};
|
||||
|
||||
return config;
|
||||
|
|
|
@ -16,7 +16,7 @@ import { useServiceMetricCharts } from '../../../hooks/useServiceMetricCharts';
|
|||
import { MetricsChart } from '../../shared/charts/MetricsChart';
|
||||
import { useUrlParams } from '../../../hooks/useUrlParams';
|
||||
import { ChartsSyncContextProvider } from '../../../context/ChartsSyncContext';
|
||||
import { PROJECTION } from '../../../../common/projections/typings';
|
||||
import { Projection } from '../../../../common/projections';
|
||||
import { LocalUIFilters } from '../../shared/LocalUIFilters';
|
||||
|
||||
interface ServiceMetricsProps {
|
||||
|
@ -36,7 +36,7 @@ export function ServiceMetrics({ agentName }: ServiceMetricsProps) {
|
|||
serviceName,
|
||||
serviceNodeName,
|
||||
},
|
||||
projection: PROJECTION.METRICS,
|
||||
projection: Projection.metrics,
|
||||
showCount: false,
|
||||
}),
|
||||
[serviceName, serviceNodeName]
|
||||
|
|
|
@ -15,7 +15,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import styled from 'styled-components';
|
||||
import { UNIDENTIFIED_SERVICE_NODES_LABEL } from '../../../../common/i18n';
|
||||
import { SERVICE_NODE_NAME_MISSING } from '../../../../common/service_nodes';
|
||||
import { PROJECTION } from '../../../../common/projections/typings';
|
||||
import { Projection } from '../../../../common/projections';
|
||||
import { LocalUIFilters } from '../../shared/LocalUIFilters';
|
||||
import { useUrlParams } from '../../../hooks/useUrlParams';
|
||||
import { ManagedTable, ITableColumn } from '../../shared/ManagedTable';
|
||||
|
@ -46,7 +46,7 @@ function ServiceNodeOverview() {
|
|||
params: {
|
||||
serviceName,
|
||||
},
|
||||
projection: PROJECTION.SERVICE_NODES,
|
||||
projection: Projection.serviceNodes,
|
||||
}),
|
||||
[serviceName]
|
||||
);
|
||||
|
|
|
@ -15,7 +15,7 @@ import { NoServicesMessage } from './NoServicesMessage';
|
|||
import { ServiceList } from './ServiceList';
|
||||
import { useUrlParams } from '../../../hooks/useUrlParams';
|
||||
import { useTrackPageview } from '../../../../../observability/public';
|
||||
import { PROJECTION } from '../../../../common/projections/typings';
|
||||
import { Projection } from '../../../../common/projections';
|
||||
import { LocalUIFilters } from '../../shared/LocalUIFilters';
|
||||
import { useApmPluginContext } from '../../../hooks/useApmPluginContext';
|
||||
|
||||
|
@ -88,7 +88,7 @@ export function ServiceOverview() {
|
|||
const localFiltersConfig: React.ComponentProps<typeof LocalUIFilters> = useMemo(
|
||||
() => ({
|
||||
filterNames: ['host', 'agentName'],
|
||||
projection: PROJECTION.SERVICES,
|
||||
projection: Projection.services,
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
|
|
@ -11,7 +11,7 @@ import { TraceList } from './TraceList';
|
|||
import { useUrlParams } from '../../../hooks/useUrlParams';
|
||||
import { useTrackPageview } from '../../../../../observability/public';
|
||||
import { LocalUIFilters } from '../../shared/LocalUIFilters';
|
||||
import { PROJECTION } from '../../../../common/projections/typings';
|
||||
import { Projection } from '../../../../common/projections';
|
||||
import { APIReturnType } from '../../../services/rest/createCallApmApi';
|
||||
|
||||
type TracesAPIResponse = APIReturnType<'/api/apm/traces'>;
|
||||
|
@ -48,7 +48,7 @@ export function TraceOverview() {
|
|||
const localUIFiltersConfig = useMemo(() => {
|
||||
const config: React.ComponentProps<typeof LocalUIFilters> = {
|
||||
filterNames: ['transactionResult', 'host', 'containerId', 'podName'],
|
||||
projection: PROJECTION.TRACES,
|
||||
projection: Projection.traces,
|
||||
};
|
||||
|
||||
return config;
|
||||
|
|
|
@ -27,7 +27,7 @@ import { FETCH_STATUS } from '../../../hooks/useFetcher';
|
|||
import { TransactionBreakdown } from '../../shared/TransactionBreakdown';
|
||||
import { ChartsSyncContextProvider } from '../../../context/ChartsSyncContext';
|
||||
import { useTrackPageview } from '../../../../../observability/public';
|
||||
import { PROJECTION } from '../../../../common/projections/typings';
|
||||
import { Projection } from '../../../../common/projections';
|
||||
import { LocalUIFilters } from '../../shared/LocalUIFilters';
|
||||
import { HeightRetainer } from '../../shared/HeightRetainer';
|
||||
import { ErroneousTransactionsRateChart } from '../../shared/charts/ErroneousTransactionsRateChart';
|
||||
|
@ -52,7 +52,7 @@ export function TransactionDetails() {
|
|||
const localUIFiltersConfig = useMemo(() => {
|
||||
const config: React.ComponentProps<typeof LocalUIFilters> = {
|
||||
filterNames: ['transactionResult', 'serviceVersion'],
|
||||
projection: PROJECTION.TRANSACTIONS,
|
||||
projection: Projection.transactions,
|
||||
params: {
|
||||
transactionName,
|
||||
transactionType,
|
||||
|
|
|
@ -35,7 +35,7 @@ import { ChartsSyncContextProvider } from '../../../context/ChartsSyncContext';
|
|||
import { useTrackPageview } from '../../../../../observability/public';
|
||||
import { fromQuery, toQuery } from '../../shared/Links/url_helpers';
|
||||
import { LocalUIFilters } from '../../shared/LocalUIFilters';
|
||||
import { PROJECTION } from '../../../../common/projections/typings';
|
||||
import { Projection } from '../../../../common/projections';
|
||||
import { useUrlParams } from '../../../hooks/useUrlParams';
|
||||
import { useServiceTransactionTypes } from '../../../hooks/useServiceTransactionTypes';
|
||||
import { TransactionTypeFilter } from '../../shared/LocalUIFilters/TransactionTypeFilter';
|
||||
|
@ -103,7 +103,7 @@ export function TransactionOverview() {
|
|||
serviceName,
|
||||
transactionType,
|
||||
},
|
||||
projection: PROJECTION.TRANSACTION_GROUPS,
|
||||
projection: Projection.transactionGroups,
|
||||
}),
|
||||
[serviceName, transactionType]
|
||||
);
|
||||
|
|
|
@ -9,7 +9,7 @@ import { uniqueId, startsWith } from 'lodash';
|
|||
import styled from 'styled-components';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { fromQuery, toQuery } from '../Links/url_helpers';
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
import { Typeahead } from './Typeahead';
|
||||
import { getBoolFilter } from './get_bool_filter';
|
||||
import { useLocation } from '../../../hooks/useLocation';
|
||||
|
|
|
@ -17,10 +17,10 @@ import styled from 'styled-components';
|
|||
import { LocalUIFilterName } from '../../../../server/lib/ui_filters/local_ui_filters/config';
|
||||
import { Filter } from './Filter';
|
||||
import { useLocalUIFilters } from '../../../hooks/useLocalUIFilters';
|
||||
import { PROJECTION } from '../../../../common/projections/typings';
|
||||
import { Projection } from '../../../../common/projections';
|
||||
|
||||
interface Props {
|
||||
projection: PROJECTION;
|
||||
projection: Projection;
|
||||
filterNames: LocalUIFilterName[];
|
||||
params?: Record<string, string | number | boolean | undefined>;
|
||||
showCount?: boolean;
|
||||
|
|
|
@ -7,7 +7,7 @@ import { EuiTitle } from '@elastic/eui';
|
|||
import React from 'react';
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { GenericMetricsChart } from '../../../../../server/lib/metrics/transform_metrics_chart';
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
import CustomPlot from '../CustomPlot';
|
||||
import {
|
||||
asDecimal,
|
||||
|
|
|
@ -7,10 +7,13 @@
|
|||
import { compact, pickBy } from 'lodash';
|
||||
import datemath from '@elastic/datemath';
|
||||
import { IUrlParams } from './types';
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import {
|
||||
ProcessorEvent,
|
||||
UIProcessorEvent,
|
||||
} from '../../../common/processor_event';
|
||||
|
||||
interface PathParams {
|
||||
processorEvent?: ProcessorEvent;
|
||||
processorEvent?: UIProcessorEvent;
|
||||
serviceName?: string;
|
||||
errorGroupId?: string;
|
||||
serviceNodeName?: string;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { LocalUIFilterName } from '../../../server/lib/ui_filters/local_ui_filters/config';
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import { UIProcessorEvent } from '../../../common/processor_event';
|
||||
|
||||
export type IUrlParams = {
|
||||
detailTab?: string;
|
||||
|
@ -32,6 +32,6 @@ export type IUrlParams = {
|
|||
pageSize?: number;
|
||||
serviceNodeName?: string;
|
||||
searchTerm?: string;
|
||||
processorEvent?: ProcessorEvent;
|
||||
processorEvent?: UIProcessorEvent;
|
||||
traceIdLink?: string;
|
||||
} & Partial<Record<LocalUIFilterName, string>>;
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
*/
|
||||
|
||||
import { useFetcher } from './useFetcher';
|
||||
import { ProcessorEvent } from '../../common/processor_event';
|
||||
import { UIProcessorEvent } from '../../common/processor_event';
|
||||
|
||||
export function useDynamicIndexPattern(
|
||||
processorEvent: ProcessorEvent | undefined
|
||||
processorEvent: UIProcessorEvent | undefined
|
||||
) {
|
||||
const { data, status } = useFetcher(
|
||||
(callApmApi) => {
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
import { history } from '../utils/history';
|
||||
import { toQuery, fromQuery } from '../components/shared/Links/url_helpers';
|
||||
import { removeUndefinedProps } from '../context/UrlParamsContext/helpers';
|
||||
import { PROJECTION } from '../../common/projections/typings';
|
||||
import { Projection } from '../../common/projections';
|
||||
import { pickKeys } from '../../common/utils/pick_keys';
|
||||
import { useCallApi } from './useCallApi';
|
||||
|
||||
|
@ -35,7 +35,7 @@ export function useLocalUIFilters({
|
|||
filterNames,
|
||||
params,
|
||||
}: {
|
||||
projection: PROJECTION;
|
||||
projection: Projection;
|
||||
filterNames: LocalUIFilterName[];
|
||||
params?: Record<string, string | number | boolean | undefined>;
|
||||
}) {
|
||||
|
|
|
@ -99,10 +99,9 @@ export function expectTextsInDocument(output: any, texts: string[]) {
|
|||
}
|
||||
|
||||
interface MockSetup {
|
||||
dynamicIndexPattern: any;
|
||||
start: number;
|
||||
end: number;
|
||||
client: any;
|
||||
apmEventClient: any;
|
||||
internalClient: any;
|
||||
config: APMConfig;
|
||||
uiFiltersES: ESFilter[];
|
||||
|
@ -148,7 +147,7 @@ export async function inspectSearchParams(
|
|||
const mockSetup = {
|
||||
start: 1528113600000,
|
||||
end: 1528977600000,
|
||||
client: { search: spy } as any,
|
||||
apmEventClient: { search: spy } as any,
|
||||
internalClient: { search: spy } as any,
|
||||
config: new Proxy({}, { get: () => 'myIndex' }) as APMConfig,
|
||||
uiFiltersES: [{ term: { 'my.custom.ui.filter': 'foo-bar' } }],
|
||||
|
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
exports[`getAllEnvironments fetches all environments 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
"error",
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"environments": Object {
|
||||
|
@ -15,15 +22,6 @@ Object {
|
|||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"terms": Object {
|
||||
"processor.event": Array [
|
||||
"transaction",
|
||||
"error",
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"service.name": "test",
|
||||
|
@ -34,16 +32,18 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": Array [
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`getAllEnvironments fetches all environments with includeMissing 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
"error",
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"environments": Object {
|
||||
|
@ -57,15 +57,6 @@ Object {
|
|||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"terms": Object {
|
||||
"processor.event": Array [
|
||||
"transaction",
|
||||
"error",
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"service.name": "test",
|
||||
|
@ -76,10 +67,5 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": Array [
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import { Setup } from '../helpers/setup_request';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
SERVICE_ENVIRONMENT,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
|
@ -21,7 +21,7 @@ export async function getAllEnvironments({
|
|||
setup: Setup;
|
||||
includeMissing?: boolean;
|
||||
}) {
|
||||
const { client, indices } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
// omit filter for service.name if "All" option is selected
|
||||
const serviceNameFilter = serviceName
|
||||
|
@ -29,21 +29,18 @@ export async function getAllEnvironments({
|
|||
: [];
|
||||
|
||||
const params = {
|
||||
index: [
|
||||
indices['apm_oss.metricsIndices'],
|
||||
indices['apm_oss.errorIndices'],
|
||||
indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [
|
||||
ProcessorEvent.transaction,
|
||||
ProcessorEvent.error,
|
||||
ProcessorEvent.metric,
|
||||
],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
terms: { [PROCESSOR_EVENT]: ['transaction', 'error', 'metric'] },
|
||||
},
|
||||
...serviceNameFilter,
|
||||
],
|
||||
filter: [...serviceNameFilter],
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
|
@ -58,7 +55,7 @@ export async function getAllEnvironments({
|
|||
},
|
||||
};
|
||||
|
||||
const resp = await client.search(params);
|
||||
const resp = await apmEventClient.search(params);
|
||||
const environments =
|
||||
resp.aggregations?.environments.buckets.map(
|
||||
(bucket) => bucket.key as string
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
exports[`error queries fetches a single error group 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"error",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
|
@ -11,11 +16,6 @@ Object {
|
|||
"service.name": "serviceName",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "error",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"error.grouping_key": "groupId",
|
||||
|
@ -57,12 +57,16 @@ Object {
|
|||
},
|
||||
],
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`error queries fetches multiple error groups 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"error",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"error_groups": Object {
|
||||
|
@ -104,11 +108,6 @@ Object {
|
|||
"service.name": "serviceName",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "error",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -128,12 +127,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`error queries fetches multiple error groups when sortField = latestOccurrenceAt 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"error",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"error_groups": Object {
|
||||
|
@ -180,11 +183,6 @@ Object {
|
|||
"service.name": "serviceName",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "error",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -204,6 +202,5 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
exports[`error distribution queries fetches an error distribution 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"error",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"distribution": Object {
|
||||
|
@ -19,11 +24,6 @@ Object {
|
|||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "error",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"service.name": "serviceName",
|
||||
|
@ -48,12 +48,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`error distribution queries fetches an error distribution with a group id 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"error",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"distribution": Object {
|
||||
|
@ -71,11 +75,6 @@ Object {
|
|||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "error",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"service.name": "serviceName",
|
||||
|
@ -105,6 +104,5 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -4,6 +4,11 @@ exports[`timeseriesFetcher should make the correct query 1`] = `
|
|||
Array [
|
||||
Array [
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"error",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"distribution": Object {
|
||||
|
@ -21,11 +26,6 @@ Array [
|
|||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "error",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"service.name": "myServiceName",
|
||||
|
@ -50,7 +50,6 @@ Array [
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "apm-*",
|
||||
},
|
||||
],
|
||||
]
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { PROCESSOR_EVENT } from '../../../../../common/elasticsearch_fieldnames';
|
||||
import { getBuckets } from '../get_buckets';
|
||||
import { APMConfig } from '../../../..';
|
||||
import { ProcessorEvent } from '../../../../../common/processor_event';
|
||||
|
||||
describe('timeseriesFetcher', () => {
|
||||
let clientSpy: jest.Mock;
|
||||
|
@ -29,7 +29,7 @@ describe('timeseriesFetcher', () => {
|
|||
setup: {
|
||||
start: 1528113600000,
|
||||
end: 1528977600000,
|
||||
client: {
|
||||
apmEventClient: {
|
||||
search: clientSpy,
|
||||
} as any,
|
||||
internalClient: {
|
||||
|
@ -66,8 +66,6 @@ describe('timeseriesFetcher', () => {
|
|||
|
||||
it('should limit query results to error documents', () => {
|
||||
const query = clientSpy.mock.calls[0][0];
|
||||
expect(query.body.query.bool.filter).toEqual(
|
||||
expect.arrayContaining([{ term: { [PROCESSOR_EVENT]: 'error' } }])
|
||||
);
|
||||
expect(query.apm.events).toEqual([ProcessorEvent.error]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ProcessorEvent } from '../../../../common/processor_event';
|
||||
import { ESFilter } from '../../../../typings/elasticsearch';
|
||||
import {
|
||||
ERROR_GROUP_ID,
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
} from '../../../../common/elasticsearch_fieldnames';
|
||||
import { rangeFilter } from '../../../../common/utils/range_filter';
|
||||
|
@ -28,9 +28,8 @@ export async function getBuckets({
|
|||
bucketSize: number;
|
||||
setup: Setup & SetupTimeRange & SetupUIFilters;
|
||||
}) {
|
||||
const { start, end, uiFiltersES, client, indices } = setup;
|
||||
const { start, end, uiFiltersES, apmEventClient } = setup;
|
||||
const filter: ESFilter[] = [
|
||||
{ term: { [PROCESSOR_EVENT]: 'error' } },
|
||||
{ term: { [SERVICE_NAME]: serviceName } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
...uiFiltersES,
|
||||
|
@ -41,7 +40,9 @@ export async function getBuckets({
|
|||
}
|
||||
|
||||
const params = {
|
||||
index: indices['apm_oss.errorIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.error],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
|
@ -65,7 +66,7 @@ export async function getBuckets({
|
|||
},
|
||||
};
|
||||
|
||||
const resp = await client.search(params);
|
||||
const resp = await apmEventClient.search(params);
|
||||
|
||||
const buckets = (resp.aggregations?.distribution.buckets || []).map(
|
||||
(bucket) => ({
|
||||
|
|
|
@ -4,14 +4,13 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import {
|
||||
ERROR_GROUP_ID,
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
TRANSACTION_SAMPLED,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
import { PromiseReturnType } from '../../../typings/common';
|
||||
import { APMError } from '../../../typings/es_schemas/ui/apm_error';
|
||||
import { rangeFilter } from '../../../common/utils/range_filter';
|
||||
import {
|
||||
Setup,
|
||||
|
@ -32,17 +31,18 @@ export async function getErrorGroup({
|
|||
groupId: string;
|
||||
setup: Setup & SetupTimeRange & SetupUIFilters;
|
||||
}) {
|
||||
const { start, end, uiFiltersES, client, indices } = setup;
|
||||
const { start, end, uiFiltersES, apmEventClient } = setup;
|
||||
|
||||
const params = {
|
||||
index: indices['apm_oss.errorIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.error as const],
|
||||
},
|
||||
body: {
|
||||
size: 1,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ term: { [SERVICE_NAME]: serviceName } },
|
||||
{ term: { [PROCESSOR_EVENT]: 'error' } },
|
||||
{ term: { [ERROR_GROUP_ID]: groupId } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
...uiFiltersES,
|
||||
|
@ -57,7 +57,7 @@ export async function getErrorGroup({
|
|||
},
|
||||
};
|
||||
|
||||
const resp = await client.search<APMError>(params);
|
||||
const resp = await apmEventClient.search(params);
|
||||
const error = resp.hits.hits[0]?._source;
|
||||
const transactionId = error?.transaction?.id;
|
||||
const traceId = error?.trace?.id;
|
||||
|
|
|
@ -13,14 +13,13 @@ import {
|
|||
ERROR_LOG_MESSAGE,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
import { PromiseReturnType } from '../../../typings/common';
|
||||
import { APMError } from '../../../typings/es_schemas/ui/apm_error';
|
||||
import {
|
||||
Setup,
|
||||
SetupTimeRange,
|
||||
SetupUIFilters,
|
||||
} from '../helpers/setup_request';
|
||||
import { getErrorGroupsProjection } from '../../../common/projections/errors';
|
||||
import { mergeProjection } from '../../../common/projections/util/merge_projection';
|
||||
import { getErrorGroupsProjection } from '../../projections/errors';
|
||||
import { mergeProjection } from '../../projections/util/merge_projection';
|
||||
import { SortOptions } from '../../../typings/elasticsearch/aggregations';
|
||||
|
||||
export type ErrorGroupListAPIResponse = PromiseReturnType<
|
||||
|
@ -38,7 +37,7 @@ export async function getErrorGroups({
|
|||
sortDirection?: 'asc' | 'desc';
|
||||
setup: Setup & SetupTimeRange & SetupUIFilters;
|
||||
}) {
|
||||
const { client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
// sort buckets by last occurrence of error
|
||||
const sortByLatestOccurrence = sortField === 'latestOccurrenceAt';
|
||||
|
@ -92,23 +91,7 @@ export async function getErrorGroups({
|
|||
},
|
||||
});
|
||||
|
||||
interface SampleError {
|
||||
'@timestamp': APMError['@timestamp'];
|
||||
error: {
|
||||
log?: {
|
||||
message: string;
|
||||
};
|
||||
exception?: Array<{
|
||||
handled?: boolean;
|
||||
message?: string;
|
||||
type?: string;
|
||||
}>;
|
||||
culprit: APMError['error']['culprit'];
|
||||
grouping_key: APMError['error']['grouping_key'];
|
||||
};
|
||||
}
|
||||
|
||||
const resp = await client.search<SampleError, typeof params>(params);
|
||||
const resp = await apmEventClient.search(params);
|
||||
|
||||
// aggregations can be undefined when no matching indices are found.
|
||||
// this is an exception rather than the rule so the ES type does not account for this.
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import chalk from 'chalk';
|
||||
import {
|
||||
LegacyAPICaller,
|
||||
KibanaRequest,
|
||||
} from '../../../../../../../src/core/server';
|
||||
|
||||
function formatObj(obj: Record<string, any>) {
|
||||
return JSON.stringify(obj, null, 2);
|
||||
}
|
||||
|
||||
export async function callClientWithDebug({
|
||||
apiCaller,
|
||||
operationName,
|
||||
params,
|
||||
debug,
|
||||
request,
|
||||
}: {
|
||||
apiCaller: LegacyAPICaller;
|
||||
operationName: string;
|
||||
params: Record<string, any>;
|
||||
debug: boolean;
|
||||
request: KibanaRequest;
|
||||
}) {
|
||||
const startTime = process.hrtime();
|
||||
|
||||
let res: any;
|
||||
let esError = null;
|
||||
try {
|
||||
res = apiCaller(operationName, params);
|
||||
} catch (e) {
|
||||
// catch error and throw after outputting debug info
|
||||
esError = e;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
const highlightColor = esError ? 'bgRed' : 'inverse';
|
||||
const diff = process.hrtime(startTime);
|
||||
const duration = `${Math.round(diff[0] * 1000 + diff[1] / 1e6)}ms`;
|
||||
const routeInfo = `${request.route.method.toUpperCase()} ${
|
||||
request.route.path
|
||||
}`;
|
||||
|
||||
console.log(
|
||||
chalk.bold[highlightColor](`=== Debug: ${routeInfo} (${duration}) ===`)
|
||||
);
|
||||
|
||||
if (operationName === 'search') {
|
||||
console.log(`GET ${params.index}/_${operationName}`);
|
||||
console.log(formatObj(params.body));
|
||||
} else {
|
||||
console.log(chalk.bold('ES operation:'), operationName);
|
||||
|
||||
console.log(chalk.bold('ES query:'));
|
||||
console.log(formatObj(params));
|
||||
}
|
||||
console.log(`\n`);
|
||||
}
|
||||
|
||||
if (esError) {
|
||||
throw esError;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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 { cloneDeep } from 'lodash';
|
||||
import { OBSERVER_VERSION_MAJOR } from '../../../../../common/elasticsearch_fieldnames';
|
||||
import {
|
||||
ESSearchRequest,
|
||||
ESFilter,
|
||||
} from '../../../../../typings/elasticsearch';
|
||||
|
||||
/*
|
||||
Adds a range query to the ES request to exclude legacy data
|
||||
*/
|
||||
|
||||
export function addFilterToExcludeLegacyData(
|
||||
params: ESSearchRequest & {
|
||||
body: { query: { bool: { filter: ESFilter[] } } };
|
||||
}
|
||||
) {
|
||||
const nextParams = cloneDeep(params);
|
||||
|
||||
// add filter for omitting pre-7.x data
|
||||
nextParams.body.query.bool.filter.push({
|
||||
range: { [OBSERVER_VERSION_MAJOR]: { gte: 7 } },
|
||||
});
|
||||
|
||||
return nextParams;
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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 { ValuesType } from 'utility-types';
|
||||
import { APMBaseDoc } from '../../../../../typings/es_schemas/raw/apm_base_doc';
|
||||
import { APMError } from '../../../../../typings/es_schemas/ui/apm_error';
|
||||
import { KibanaRequest } from '../../../../../../../../src/core/server';
|
||||
import { ProcessorEvent } from '../../../../../common/processor_event';
|
||||
import {
|
||||
ESSearchRequest,
|
||||
ESSearchResponse,
|
||||
} from '../../../../../typings/elasticsearch';
|
||||
import { ApmIndicesConfig } from '../../../settings/apm_indices/get_apm_indices';
|
||||
import { APMRequestHandlerContext } from '../../../../routes/typings';
|
||||
import { addFilterToExcludeLegacyData } from './add_filter_to_exclude_legacy_data';
|
||||
import { callClientWithDebug } from '../call_client_with_debug';
|
||||
import { Transaction } from '../../../../../typings/es_schemas/ui/transaction';
|
||||
import { Span } from '../../../../../typings/es_schemas/ui/span';
|
||||
import { unpackProcessorEvents } from './unpack_processor_events';
|
||||
|
||||
export type APMEventESSearchRequest = Omit<ESSearchRequest, 'index'> & {
|
||||
apm: {
|
||||
events: ProcessorEvent[];
|
||||
};
|
||||
};
|
||||
|
||||
type TypeOfProcessorEvent<T extends ProcessorEvent> = {
|
||||
[ProcessorEvent.error]: APMError;
|
||||
[ProcessorEvent.transaction]: Transaction;
|
||||
[ProcessorEvent.span]: Span;
|
||||
[ProcessorEvent.metric]: APMBaseDoc;
|
||||
[ProcessorEvent.onboarding]: unknown;
|
||||
[ProcessorEvent.sourcemap]: unknown;
|
||||
}[T];
|
||||
|
||||
type ESSearchRequestOf<TParams extends APMEventESSearchRequest> = Omit<
|
||||
TParams,
|
||||
'apm'
|
||||
> & { index: string[] | string };
|
||||
|
||||
type TypedSearchResponse<
|
||||
TParams extends APMEventESSearchRequest
|
||||
> = ESSearchResponse<
|
||||
TypeOfProcessorEvent<ValuesType<TParams['apm']['events']>>,
|
||||
ESSearchRequestOf<TParams>
|
||||
>;
|
||||
|
||||
export type APMEventClient = ReturnType<typeof createApmEventClient>;
|
||||
|
||||
export function createApmEventClient({
|
||||
context,
|
||||
request,
|
||||
indices,
|
||||
options: { includeFrozen } = { includeFrozen: false },
|
||||
}: {
|
||||
context: APMRequestHandlerContext;
|
||||
request: KibanaRequest;
|
||||
indices: ApmIndicesConfig;
|
||||
options: {
|
||||
includeFrozen: boolean;
|
||||
};
|
||||
}) {
|
||||
const client = context.core.elasticsearch.legacy.client;
|
||||
|
||||
return {
|
||||
search<TParams extends APMEventESSearchRequest>(
|
||||
params: TParams,
|
||||
{ includeLegacyData } = { includeLegacyData: false }
|
||||
): Promise<TypedSearchResponse<TParams>> {
|
||||
const withProcessorEventFilter = unpackProcessorEvents(params, indices);
|
||||
|
||||
const withPossibleLegacyDataFilter = !includeLegacyData
|
||||
? addFilterToExcludeLegacyData(withProcessorEventFilter)
|
||||
: withProcessorEventFilter;
|
||||
|
||||
return callClientWithDebug({
|
||||
apiCaller: client.callAsCurrentUser,
|
||||
operationName: 'search',
|
||||
params: {
|
||||
...withPossibleLegacyDataFilter,
|
||||
ignore_throttled: !includeFrozen,
|
||||
},
|
||||
request,
|
||||
debug: context.params.query._debug,
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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 { uniq, defaultsDeep, cloneDeep } from 'lodash';
|
||||
import { PROCESSOR_EVENT } from '../../../../../common/elasticsearch_fieldnames';
|
||||
import { ProcessorEvent } from '../../../../../common/processor_event';
|
||||
import {
|
||||
ESSearchRequest,
|
||||
ESFilter,
|
||||
} from '../../../../../typings/elasticsearch';
|
||||
import { APMEventESSearchRequest } from '.';
|
||||
import {
|
||||
ApmIndicesConfig,
|
||||
ApmIndicesName,
|
||||
} from '../../../settings/apm_indices/get_apm_indices';
|
||||
|
||||
export const processorEventIndexMap: Record<ProcessorEvent, ApmIndicesName> = {
|
||||
[ProcessorEvent.transaction]: 'apm_oss.transactionIndices',
|
||||
[ProcessorEvent.span]: 'apm_oss.spanIndices',
|
||||
[ProcessorEvent.metric]: 'apm_oss.metricsIndices',
|
||||
[ProcessorEvent.error]: 'apm_oss.errorIndices',
|
||||
[ProcessorEvent.sourcemap]: 'apm_oss.sourcemapIndices',
|
||||
[ProcessorEvent.onboarding]: 'apm_oss.onboardingIndices',
|
||||
};
|
||||
|
||||
export function unpackProcessorEvents(
|
||||
request: APMEventESSearchRequest,
|
||||
indices: ApmIndicesConfig
|
||||
) {
|
||||
const { apm, ...params } = request;
|
||||
|
||||
const index = uniq(
|
||||
apm.events.map((event) => indices[processorEventIndexMap[event]])
|
||||
);
|
||||
|
||||
const withFilterForProcessorEvent: ESSearchRequest & {
|
||||
body: { query: { bool: { filter: ESFilter[] } } };
|
||||
} = defaultsDeep(cloneDeep(params), {
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
filter: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
withFilterForProcessorEvent.body.query.bool.filter.push({
|
||||
terms: {
|
||||
[PROCESSOR_EVENT]: apm.events,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
index,
|
||||
...withFilterForProcessorEvent,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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 {
|
||||
IndexDocumentParams,
|
||||
IndicesCreateParams,
|
||||
DeleteDocumentResponse,
|
||||
DeleteDocumentParams,
|
||||
} from 'elasticsearch';
|
||||
import { KibanaRequest } from 'src/core/server';
|
||||
import { APMRequestHandlerContext } from '../../../../routes/typings';
|
||||
import {
|
||||
ESSearchResponse,
|
||||
ESSearchRequest,
|
||||
} from '../../../../../typings/elasticsearch';
|
||||
import { callClientWithDebug } from '../call_client_with_debug';
|
||||
|
||||
// `type` was deprecated in 7.0
|
||||
export type APMIndexDocumentParams<T> = Omit<IndexDocumentParams<T>, 'type'>;
|
||||
|
||||
export type APMInternalClient = ReturnType<typeof createInternalESClient>;
|
||||
|
||||
export function createInternalESClient({
|
||||
context,
|
||||
request,
|
||||
}: {
|
||||
context: APMRequestHandlerContext;
|
||||
request: KibanaRequest;
|
||||
}) {
|
||||
const { callAsInternalUser } = context.core.elasticsearch.legacy.client;
|
||||
|
||||
const callEs = (operationName: string, params: Record<string, any>) => {
|
||||
return callClientWithDebug({
|
||||
apiCaller: callAsInternalUser,
|
||||
operationName,
|
||||
params,
|
||||
request,
|
||||
debug: context.params.query._debug,
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
search: async <
|
||||
TDocument = unknown,
|
||||
TSearchRequest extends ESSearchRequest = ESSearchRequest
|
||||
>(
|
||||
params: TSearchRequest
|
||||
): Promise<ESSearchResponse<TDocument, TSearchRequest>> => {
|
||||
return callEs('search', params);
|
||||
},
|
||||
index: <Body>(params: APMIndexDocumentParams<Body>) => {
|
||||
return callEs('index', params);
|
||||
},
|
||||
delete: (
|
||||
params: Omit<DeleteDocumentParams, 'type'>
|
||||
): Promise<DeleteDocumentResponse> => {
|
||||
return callEs('delete', params);
|
||||
},
|
||||
indicesCreate: (params: IndicesCreateParams) => {
|
||||
return callEs('indices.create', params);
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,48 +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 { isApmIndex } from './es_client';
|
||||
|
||||
describe('isApmIndex', () => {
|
||||
const apmIndices = [
|
||||
'apm-*-metric-*',
|
||||
'apm-*-onboarding-*',
|
||||
'apm-*-span-*',
|
||||
'apm-*-transaction-*',
|
||||
'apm-*-error-*',
|
||||
];
|
||||
describe('when indexParam is a string', () => {
|
||||
it('should return true if it matches any of the items in apmIndices', () => {
|
||||
const indexParam = 'apm-*-transaction-*';
|
||||
expect(isApmIndex(apmIndices, indexParam)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if it does not match any of the items in `apmIndices`', () => {
|
||||
const indexParam = '.ml-anomalies-*';
|
||||
expect(isApmIndex(apmIndices, indexParam)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when indexParam is an array', () => {
|
||||
it('should return true if all values in `indexParam` matches values in `apmIndices`', () => {
|
||||
const indexParam = ['apm-*-transaction-*', 'apm-*-span-*'];
|
||||
expect(isApmIndex(apmIndices, indexParam)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false if some of the values don't match with `apmIndices`", () => {
|
||||
const indexParam = ['apm-*-transaction-*', '.ml-anomalies-*'];
|
||||
expect(isApmIndex(apmIndices, indexParam)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when indexParam is neither a string or an array', () => {
|
||||
it('should return false', () => {
|
||||
[true, false, undefined].forEach((indexParam) => {
|
||||
expect(isApmIndex(apmIndices, indexParam)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,228 +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.
|
||||
*/
|
||||
|
||||
/* eslint-disable no-console */
|
||||
import {
|
||||
IndexDocumentParams,
|
||||
SearchParams,
|
||||
IndicesCreateParams,
|
||||
DeleteDocumentResponse,
|
||||
DeleteDocumentParams,
|
||||
} from 'elasticsearch';
|
||||
import { cloneDeep, isString, merge } from 'lodash';
|
||||
import { KibanaRequest } from 'src/core/server';
|
||||
import chalk from 'chalk';
|
||||
import {
|
||||
ESSearchRequest,
|
||||
ESSearchResponse,
|
||||
} from '../../../typings/elasticsearch';
|
||||
import { OBSERVER_VERSION_MAJOR } from '../../../common/elasticsearch_fieldnames';
|
||||
import { pickKeys } from '../../../common/utils/pick_keys';
|
||||
import { APMRequestHandlerContext } from '../../routes/typings';
|
||||
import { ApmIndicesConfig } from '../settings/apm_indices/get_apm_indices';
|
||||
|
||||
// `type` was deprecated in 7.0
|
||||
export type APMIndexDocumentParams<T> = Omit<IndexDocumentParams<T>, 'type'>;
|
||||
|
||||
export interface IndexPrivileges {
|
||||
has_all_requested: boolean;
|
||||
index: Record<string, { read: boolean }>;
|
||||
}
|
||||
|
||||
interface IndexPrivilegesParams {
|
||||
index: Array<{
|
||||
names: string[] | string;
|
||||
privileges: string[];
|
||||
}>;
|
||||
}
|
||||
|
||||
export function isApmIndex(
|
||||
apmIndices: string[],
|
||||
indexParam: SearchParams['index']
|
||||
) {
|
||||
if (isString(indexParam)) {
|
||||
return apmIndices.includes(indexParam);
|
||||
} else if (Array.isArray(indexParam)) {
|
||||
// return false if at least one of the indices is not an APM index
|
||||
return indexParam.every((index) => apmIndices.includes(index));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function addFilterForLegacyData(
|
||||
apmIndices: string[],
|
||||
params: ESSearchRequest,
|
||||
{ includeLegacyData = false } = {}
|
||||
): SearchParams {
|
||||
// search across all data (including data)
|
||||
if (includeLegacyData || !isApmIndex(apmIndices, params.index)) {
|
||||
return params;
|
||||
}
|
||||
|
||||
const nextParams = merge(
|
||||
{
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
filter: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cloneDeep(params)
|
||||
);
|
||||
|
||||
// add filter for omitting pre-7.x data
|
||||
nextParams.body.query.bool.filter.push({
|
||||
range: { [OBSERVER_VERSION_MAJOR]: { gte: 7 } },
|
||||
});
|
||||
|
||||
return nextParams;
|
||||
}
|
||||
|
||||
// add additional params for search (aka: read) requests
|
||||
function getParamsForSearchRequest({
|
||||
context,
|
||||
params,
|
||||
indices,
|
||||
includeFrozen,
|
||||
includeLegacyData,
|
||||
}: {
|
||||
context: APMRequestHandlerContext;
|
||||
params: ESSearchRequest;
|
||||
indices: ApmIndicesConfig;
|
||||
includeFrozen: boolean;
|
||||
includeLegacyData?: boolean;
|
||||
}) {
|
||||
// Get indices for legacy data filter (only those which apply)
|
||||
const apmIndices = Object.values(
|
||||
pickKeys(
|
||||
indices,
|
||||
'apm_oss.sourcemapIndices',
|
||||
'apm_oss.errorIndices',
|
||||
'apm_oss.onboardingIndices',
|
||||
'apm_oss.spanIndices',
|
||||
'apm_oss.transactionIndices',
|
||||
'apm_oss.metricsIndices'
|
||||
)
|
||||
);
|
||||
return {
|
||||
...addFilterForLegacyData(apmIndices, params, { includeLegacyData }), // filter out pre-7.0 data
|
||||
ignore_throttled: !includeFrozen, // whether to query frozen indices or not
|
||||
};
|
||||
}
|
||||
|
||||
interface APMOptions {
|
||||
includeLegacyData: boolean;
|
||||
}
|
||||
|
||||
interface ClientCreateOptions {
|
||||
clientAsInternalUser?: boolean;
|
||||
indices: ApmIndicesConfig;
|
||||
includeFrozen: boolean;
|
||||
}
|
||||
|
||||
export type ESClient = ReturnType<typeof getESClient>;
|
||||
|
||||
function formatObj(obj: Record<string, any>) {
|
||||
return JSON.stringify(obj, null, 2);
|
||||
}
|
||||
|
||||
export function getESClient(
|
||||
context: APMRequestHandlerContext,
|
||||
request: KibanaRequest,
|
||||
{ clientAsInternalUser = false, indices, includeFrozen }: ClientCreateOptions
|
||||
) {
|
||||
const {
|
||||
callAsCurrentUser,
|
||||
callAsInternalUser,
|
||||
} = context.core.elasticsearch.legacy.client;
|
||||
|
||||
async function callEs(operationName: string, params: Record<string, any>) {
|
||||
const startTime = process.hrtime();
|
||||
|
||||
let res: any;
|
||||
let esError = null;
|
||||
try {
|
||||
res = clientAsInternalUser
|
||||
? await callAsInternalUser(operationName, params)
|
||||
: await callAsCurrentUser(operationName, params);
|
||||
} catch (e) {
|
||||
// catch error and throw after outputting debug info
|
||||
esError = e;
|
||||
}
|
||||
|
||||
if (context.params.query._debug) {
|
||||
const highlightColor = esError ? 'bgRed' : 'inverse';
|
||||
const diff = process.hrtime(startTime);
|
||||
const duration = `${Math.round(diff[0] * 1000 + diff[1] / 1e6)}ms`;
|
||||
const routeInfo = `${request.route.method.toUpperCase()} ${
|
||||
request.route.path
|
||||
}`;
|
||||
|
||||
console.log(
|
||||
chalk.bold[highlightColor](`=== Debug: ${routeInfo} (${duration}) ===`)
|
||||
);
|
||||
|
||||
if (operationName === 'search') {
|
||||
console.log(`GET ${params.index}/_${operationName}`);
|
||||
console.log(formatObj(params.body));
|
||||
} else {
|
||||
console.log(chalk.bold('ES operation:'), operationName);
|
||||
|
||||
console.log(chalk.bold('ES query:'));
|
||||
console.log(formatObj(params));
|
||||
}
|
||||
console.log(`\n`);
|
||||
}
|
||||
|
||||
if (esError) {
|
||||
throw esError;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return {
|
||||
search: async <
|
||||
TDocument = unknown,
|
||||
TSearchRequest extends ESSearchRequest = {}
|
||||
>(
|
||||
params: TSearchRequest,
|
||||
apmOptions?: APMOptions
|
||||
): Promise<ESSearchResponse<TDocument, TSearchRequest>> => {
|
||||
const nextParams = await getParamsForSearchRequest({
|
||||
context,
|
||||
params,
|
||||
indices,
|
||||
includeFrozen,
|
||||
...apmOptions,
|
||||
});
|
||||
|
||||
return callEs('search', nextParams);
|
||||
},
|
||||
index: <Body>(params: APMIndexDocumentParams<Body>) => {
|
||||
return callEs('index', params);
|
||||
},
|
||||
delete: (
|
||||
params: Omit<DeleteDocumentParams, 'type'>
|
||||
): Promise<DeleteDocumentResponse> => {
|
||||
return callEs('delete', params);
|
||||
},
|
||||
indicesCreate: (params: IndicesCreateParams) => {
|
||||
return callEs('indices.create', params);
|
||||
},
|
||||
hasPrivileges: (
|
||||
params: IndexPrivilegesParams
|
||||
): Promise<IndexPrivileges> => {
|
||||
return callEs('transport.request', {
|
||||
method: 'POST',
|
||||
path: '/_security/user/_has_privileges',
|
||||
body: params,
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
|
@ -7,6 +7,8 @@ import { setupRequest } from './setup_request';
|
|||
import { APMConfig } from '../..';
|
||||
import { APMRequestHandlerContext } from '../../routes/typings';
|
||||
import { KibanaRequest } from '../../../../../../src/core/server';
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import { PROCESSOR_EVENT } from '../../../common/elasticsearch_fieldnames';
|
||||
|
||||
jest.mock('../settings/apm_indices/get_apm_indices', () => ({
|
||||
getApmIndices: async () => ({
|
||||
|
@ -93,19 +95,26 @@ function getMockRequest() {
|
|||
}
|
||||
|
||||
describe('setupRequest', () => {
|
||||
it('should call callWithRequest with default args', async () => {
|
||||
describe('with default args', () => {
|
||||
it('calls callWithRequest', async () => {
|
||||
const { mockContext, mockRequest } = getMockRequest();
|
||||
const { client } = await setupRequest(mockContext, mockRequest);
|
||||
await client.search({ index: 'apm-*', body: { foo: 'bar' } } as any);
|
||||
const { apmEventClient } = await setupRequest(mockContext, mockRequest);
|
||||
await apmEventClient.search({
|
||||
apm: { events: [ProcessorEvent.transaction] },
|
||||
body: { foo: 'bar' },
|
||||
});
|
||||
expect(
|
||||
mockContext.core.elasticsearch.legacy.client.callAsCurrentUser
|
||||
).toHaveBeenCalledWith('search', {
|
||||
index: 'apm-*',
|
||||
index: ['apm-*'],
|
||||
body: {
|
||||
foo: 'bar',
|
||||
query: {
|
||||
bool: {
|
||||
filter: [{ range: { 'observer.version_major': { gte: 7 } } }],
|
||||
filter: [
|
||||
{ terms: { 'processor.event': ['transaction'] } },
|
||||
{ range: { 'observer.version_major': { gte: 7 } } },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -113,36 +122,32 @@ describe('setupRequest', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should call callWithInternalUser with default args', async () => {
|
||||
it('calls callWithInternalUser', async () => {
|
||||
const { mockContext, mockRequest } = getMockRequest();
|
||||
const { internalClient } = await setupRequest(mockContext, mockRequest);
|
||||
await internalClient.search({
|
||||
index: 'apm-*',
|
||||
index: ['apm-*'],
|
||||
body: { foo: 'bar' },
|
||||
} as any);
|
||||
expect(
|
||||
mockContext.core.elasticsearch.legacy.client.callAsInternalUser
|
||||
).toHaveBeenCalledWith('search', {
|
||||
index: 'apm-*',
|
||||
index: ['apm-*'],
|
||||
body: {
|
||||
foo: 'bar',
|
||||
query: {
|
||||
bool: {
|
||||
filter: [{ range: { 'observer.version_major': { gte: 7 } } }],
|
||||
},
|
||||
},
|
||||
},
|
||||
ignore_throttled: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('observer.version_major filter', () => {
|
||||
describe('if index is apm-*', () => {
|
||||
it('should merge `observer.version_major` filter with existing boolean filters', async () => {
|
||||
describe('with a bool filter', () => {
|
||||
it('adds a range filter for `observer.version_major` to the existing filter', async () => {
|
||||
const { mockContext, mockRequest } = getMockRequest();
|
||||
const { client } = await setupRequest(mockContext, mockRequest);
|
||||
await client.search({
|
||||
index: 'apm-*',
|
||||
const { apmEventClient } = await setupRequest(mockContext, mockRequest);
|
||||
await apmEventClient.search({
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: { query: { bool: { filter: [{ term: 'someTerm' }] } } },
|
||||
});
|
||||
const params =
|
||||
|
@ -153,6 +158,7 @@ describe('setupRequest', () => {
|
|||
bool: {
|
||||
filter: [
|
||||
{ term: 'someTerm' },
|
||||
{ terms: { [PROCESSOR_EVENT]: ['transaction'] } },
|
||||
{ range: { 'observer.version_major': { gte: 7 } } },
|
||||
],
|
||||
},
|
||||
|
@ -160,28 +166,14 @@ describe('setupRequest', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should add `observer.version_major` filter if none exists', async () => {
|
||||
it('does not add a range filter for `observer.version_major` if includeLegacyData=true', async () => {
|
||||
const { mockContext, mockRequest } = getMockRequest();
|
||||
const { client } = await setupRequest(mockContext, mockRequest);
|
||||
await client.search({ index: 'apm-*' });
|
||||
const params =
|
||||
mockContext.core.elasticsearch.legacy.client.callAsCurrentUser.mock
|
||||
.calls[0][1];
|
||||
expect(params.body).toEqual({
|
||||
query: {
|
||||
bool: {
|
||||
filter: [{ range: { 'observer.version_major': { gte: 7 } } }],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should not add `observer.version_major` filter if `includeLegacyData=true`', async () => {
|
||||
const { mockContext, mockRequest } = getMockRequest();
|
||||
const { client } = await setupRequest(mockContext, mockRequest);
|
||||
await client.search(
|
||||
const { apmEventClient } = await setupRequest(mockContext, mockRequest);
|
||||
await apmEventClient.search(
|
||||
{
|
||||
index: 'apm-*',
|
||||
apm: {
|
||||
events: [ProcessorEvent.error],
|
||||
},
|
||||
body: { query: { bool: { filter: [{ term: 'someTerm' }] } } },
|
||||
},
|
||||
{
|
||||
|
@ -192,18 +184,30 @@ describe('setupRequest', () => {
|
|||
mockContext.core.elasticsearch.legacy.client.callAsCurrentUser.mock
|
||||
.calls[0][1];
|
||||
expect(params.body).toEqual({
|
||||
query: { bool: { filter: [{ term: 'someTerm' }] } },
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ term: 'someTerm' },
|
||||
{
|
||||
terms: {
|
||||
[PROCESSOR_EVENT]: ['error'],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('if index is not an APM index, it should not add `observer.version_major` filter', async () => {
|
||||
describe('without a bool filter', () => {
|
||||
it('adds a range filter for `observer.version_major`', async () => {
|
||||
const { mockContext, mockRequest } = getMockRequest();
|
||||
const { client } = await setupRequest(mockContext, mockRequest);
|
||||
await client.search({
|
||||
index: '.ml-*',
|
||||
body: {
|
||||
query: { bool: { filter: [{ term: 'someTerm' }] } },
|
||||
const { apmEventClient } = await setupRequest(mockContext, mockRequest);
|
||||
await apmEventClient.search({
|
||||
apm: {
|
||||
events: [ProcessorEvent.error],
|
||||
},
|
||||
});
|
||||
const params =
|
||||
|
@ -212,39 +216,50 @@ describe('setupRequest', () => {
|
|||
expect(params.body).toEqual({
|
||||
query: {
|
||||
bool: {
|
||||
filter: [{ term: 'someTerm' }],
|
||||
filter: [
|
||||
{ terms: { [PROCESSOR_EVENT]: ['error'] } },
|
||||
{ range: { 'observer.version_major': { gte: 7 } } },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ignore_throttled', () => {
|
||||
it('should set `ignore_throttled=true` if `includeFrozen=false`', async () => {
|
||||
describe('with includeFrozen=false', () => {
|
||||
it('sets `ignore_throttled=true`', async () => {
|
||||
const { mockContext, mockRequest } = getMockRequest();
|
||||
|
||||
// mock includeFrozen to return false
|
||||
mockContext.core.uiSettings.client.get.mockResolvedValue(false);
|
||||
|
||||
const { client } = await setupRequest(mockContext, mockRequest);
|
||||
const { apmEventClient } = await setupRequest(mockContext, mockRequest);
|
||||
|
||||
await client.search({});
|
||||
await apmEventClient.search({
|
||||
apm: {
|
||||
events: [],
|
||||
},
|
||||
});
|
||||
|
||||
const params =
|
||||
mockContext.core.elasticsearch.legacy.client.callAsCurrentUser.mock
|
||||
.calls[0][1];
|
||||
expect(params.ignore_throttled).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should set `ignore_throttled=false` if `includeFrozen=true`', async () => {
|
||||
describe('with includeFrozen=true', () => {
|
||||
it('sets `ignore_throttled=false`', async () => {
|
||||
const { mockContext, mockRequest } = getMockRequest();
|
||||
|
||||
// mock includeFrozen to return true
|
||||
mockContext.core.uiSettings.client.get.mockResolvedValue(true);
|
||||
|
||||
const { client } = await setupRequest(mockContext, mockRequest);
|
||||
const { apmEventClient } = await setupRequest(mockContext, mockRequest);
|
||||
|
||||
await client.search({});
|
||||
await apmEventClient.search({
|
||||
apm: { events: [] },
|
||||
});
|
||||
|
||||
const params =
|
||||
mockContext.core.elasticsearch.legacy.client.callAsCurrentUser.mock
|
||||
|
@ -252,4 +267,3 @@ describe('setupRequest', () => {
|
|||
expect(params.ignore_throttled).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -13,11 +13,17 @@ import {
|
|||
ApmIndicesConfig,
|
||||
} from '../settings/apm_indices/get_apm_indices';
|
||||
import { ESFilter } from '../../../typings/elasticsearch';
|
||||
import { ESClient } from './es_client';
|
||||
import { getUiFiltersES } from './convert_ui_filters/get_ui_filters_es';
|
||||
import { APMRequestHandlerContext } from '../../routes/typings';
|
||||
import { getESClient } from './es_client';
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import {
|
||||
APMEventClient,
|
||||
createApmEventClient,
|
||||
} from './create_es_client/create_apm_event_client';
|
||||
import {
|
||||
APMInternalClient,
|
||||
createInternalESClient,
|
||||
} from './create_es_client/create_internal_es_client';
|
||||
|
||||
function decodeUiFilters(uiFiltersEncoded?: string) {
|
||||
if (!uiFiltersEncoded) {
|
||||
|
@ -30,8 +36,8 @@ function decodeUiFilters(uiFiltersEncoded?: string) {
|
|||
// https://github.com/microsoft/TypeScript/issues/34933
|
||||
|
||||
export interface Setup {
|
||||
client: ESClient;
|
||||
internalClient: ESClient;
|
||||
apmEventClient: APMEventClient;
|
||||
internalClient: APMInternalClient;
|
||||
ml?: ReturnType<typeof getMlSetup>;
|
||||
config: APMConfig;
|
||||
indices: ApmIndicesConfig;
|
||||
|
@ -78,22 +84,19 @@ export async function setupRequest<TParams extends SetupRequestParams>(
|
|||
context.core.uiSettings.client.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN),
|
||||
]);
|
||||
|
||||
const createClientOptions = {
|
||||
indices,
|
||||
includeFrozen,
|
||||
};
|
||||
|
||||
const uiFiltersES = decodeUiFilters(query.uiFilters);
|
||||
|
||||
const coreSetupRequest = {
|
||||
indices,
|
||||
client: getESClient(context, request, {
|
||||
clientAsInternalUser: false,
|
||||
...createClientOptions,
|
||||
apmEventClient: createApmEventClient({
|
||||
context,
|
||||
request,
|
||||
indices,
|
||||
options: { includeFrozen },
|
||||
}),
|
||||
internalClient: getESClient(context, request, {
|
||||
clientAsInternalUser: true,
|
||||
...createClientOptions,
|
||||
internalClient: createInternalESClient({
|
||||
context,
|
||||
request,
|
||||
}),
|
||||
ml: getMlSetup(context, request),
|
||||
config,
|
||||
|
|
|
@ -11,7 +11,10 @@ import {
|
|||
IIndexPattern,
|
||||
} from '../../../../../../src/plugins/data/server';
|
||||
import { ApmIndicesConfig } from '../settings/apm_indices/get_apm_indices';
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import {
|
||||
ProcessorEvent,
|
||||
UIProcessorEvent,
|
||||
} from '../../../common/processor_event';
|
||||
import { APMRequestHandlerContext } from '../../routes/typings';
|
||||
|
||||
const cache = new LRU<string, IIndexPattern | undefined>({
|
||||
|
@ -27,7 +30,7 @@ export const getDynamicIndexPattern = async ({
|
|||
}: {
|
||||
context: APMRequestHandlerContext;
|
||||
indices: ApmIndicesConfig;
|
||||
processorEvent?: ProcessorEvent;
|
||||
processorEvent?: UIProcessorEvent;
|
||||
}) => {
|
||||
const patternIndices = getPatternIndices(indices, processorEvent);
|
||||
const indexPatternTitle = patternIndices.join(',');
|
||||
|
@ -75,17 +78,17 @@ export const getDynamicIndexPattern = async ({
|
|||
|
||||
function getPatternIndices(
|
||||
indices: ApmIndicesConfig,
|
||||
processorEvent?: ProcessorEvent
|
||||
processorEvent?: UIProcessorEvent
|
||||
) {
|
||||
const indexNames = processorEvent
|
||||
? [processorEvent]
|
||||
: ['transaction' as const, 'metric' as const, 'error' as const];
|
||||
: [ProcessorEvent.transaction, ProcessorEvent.metric, ProcessorEvent.error];
|
||||
|
||||
const indicesMap = {
|
||||
transaction: indices['apm_oss.transactionIndices'],
|
||||
metric: indices['apm_oss.metricsIndices'],
|
||||
error: indices['apm_oss.errorIndices'],
|
||||
[ProcessorEvent.transaction]: indices['apm_oss.transactionIndices'],
|
||||
[ProcessorEvent.metric]: indices['apm_oss.metricsIndices'],
|
||||
[ProcessorEvent.error]: indices['apm_oss.errorIndices'],
|
||||
};
|
||||
|
||||
return indexNames.map((name) => indicesMap[name]);
|
||||
return indexNames.map((name) => indicesMap[name as UIProcessorEvent]);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
exports[`metrics queries with a service node name fetches cpu chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"processCPUAverage": Object {
|
||||
|
@ -66,11 +71,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -95,12 +95,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`metrics queries with a service node name fetches heap memory chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"heapMemoryCommitted": Object {
|
||||
|
@ -155,11 +159,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -189,12 +188,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`metrics queries with a service node name fetches memory chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"memoryUsedAvg": Object {
|
||||
|
@ -251,11 +254,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -290,12 +288,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`metrics queries with a service node name fetches non heap memory chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"nonHeapMemoryCommitted": Object {
|
||||
|
@ -350,11 +352,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -384,12 +381,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`metrics queries with a service node name fetches thread count chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"threadCount": Object {
|
||||
|
@ -434,11 +435,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -468,12 +464,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`metrics queries with service_node_name_missing fetches cpu chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"processCPUAverage": Object {
|
||||
|
@ -538,11 +538,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -573,12 +568,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`metrics queries with service_node_name_missing fetches heap memory chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"heapMemoryCommitted": Object {
|
||||
|
@ -633,11 +632,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -673,12 +667,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`metrics queries with service_node_name_missing fetches memory chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"memoryUsedAvg": Object {
|
||||
|
@ -735,11 +733,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -780,12 +773,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`metrics queries with service_node_name_missing fetches non heap memory chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"nonHeapMemoryCommitted": Object {
|
||||
|
@ -840,11 +837,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -880,12 +872,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`metrics queries with service_node_name_missing fetches thread count chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"threadCount": Object {
|
||||
|
@ -930,11 +926,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -970,12 +961,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`metrics queries without a service node name fetches cpu chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"processCPUAverage": Object {
|
||||
|
@ -1040,11 +1035,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -1064,12 +1054,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`metrics queries without a service node name fetches heap memory chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"heapMemoryCommitted": Object {
|
||||
|
@ -1124,11 +1118,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -1153,12 +1142,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`metrics queries without a service node name fetches memory chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"memoryUsedAvg": Object {
|
||||
|
@ -1215,11 +1208,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -1249,12 +1237,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`metrics queries without a service node name fetches non heap memory chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"nonHeapMemoryCommitted": Object {
|
||||
|
@ -1309,11 +1301,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -1338,12 +1325,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`metrics queries without a service node name fetches thread count chart data 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"threadCount": Object {
|
||||
|
@ -1388,11 +1379,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -1417,6 +1403,5 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -18,8 +18,8 @@ import {
|
|||
} from '../../../../helpers/setup_request';
|
||||
import { getMetricsDateHistogramParams } from '../../../../helpers/metrics';
|
||||
import { ChartBase } from '../../../types';
|
||||
import { getMetricsProjection } from '../../../../../../common/projections/metrics';
|
||||
import { mergeProjection } from '../../../../../../common/projections/util/merge_projection';
|
||||
import { getMetricsProjection } from '../../../../../projections/metrics';
|
||||
import { mergeProjection } from '../../../../../projections/util/merge_projection';
|
||||
import {
|
||||
AGENT_NAME,
|
||||
LABEL_NAME,
|
||||
|
@ -42,7 +42,7 @@ export async function fetchAndTransformGcMetrics({
|
|||
chartBase: ChartBase;
|
||||
fieldName: typeof METRIC_JAVA_GC_COUNT | typeof METRIC_JAVA_GC_TIME;
|
||||
}) {
|
||||
const { start, end, client } = setup;
|
||||
const { start, end, apmEventClient } = setup;
|
||||
|
||||
const { bucketSize } = getBucketSize(start, end, 'auto');
|
||||
|
||||
|
@ -105,7 +105,7 @@ export async function fetchAndTransformGcMetrics({
|
|||
},
|
||||
});
|
||||
|
||||
const response = await client.search(params);
|
||||
const response = await apmEventClient.search(params);
|
||||
|
||||
const { aggregations } = response;
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
|
||||
import { Unionize, Overwrite } from 'utility-types';
|
||||
import { ESSearchRequest } from '../../../typings/elasticsearch';
|
||||
import {
|
||||
Setup,
|
||||
SetupTimeRange,
|
||||
|
@ -14,9 +13,10 @@ import {
|
|||
import { getMetricsDateHistogramParams } from '../helpers/metrics';
|
||||
import { ChartBase } from './types';
|
||||
import { transformDataToMetricsChart } from './transform_metrics_chart';
|
||||
import { getMetricsProjection } from '../../../common/projections/metrics';
|
||||
import { mergeProjection } from '../../../common/projections/util/merge_projection';
|
||||
import { getMetricsProjection } from '../../projections/metrics';
|
||||
import { mergeProjection } from '../../projections/util/merge_projection';
|
||||
import { AggregationOptionsByType } from '../../../typings/elasticsearch/aggregations';
|
||||
import { APMEventESSearchRequest } from '../helpers/create_es_client/create_apm_event_client';
|
||||
|
||||
type MetricsAggregationMap = Unionize<{
|
||||
min: AggregationOptionsByType['min'];
|
||||
|
@ -28,7 +28,7 @@ type MetricsAggregationMap = Unionize<{
|
|||
type MetricAggs = Record<string, MetricsAggregationMap>;
|
||||
|
||||
export type GenericMetricsRequest = Overwrite<
|
||||
ESSearchRequest,
|
||||
APMEventESSearchRequest,
|
||||
{
|
||||
body: {
|
||||
aggs: {
|
||||
|
@ -65,7 +65,7 @@ export async function fetchAndTransformMetrics<T extends MetricAggs>({
|
|||
aggs: T;
|
||||
additionalFilters?: Filter[];
|
||||
}) {
|
||||
const { start, end, client } = setup;
|
||||
const { start, end, apmEventClient } = setup;
|
||||
|
||||
const projection = getMetricsProjection({
|
||||
setup,
|
||||
|
@ -91,7 +91,7 @@ export async function fetchAndTransformMetrics<T extends MetricAggs>({
|
|||
},
|
||||
});
|
||||
|
||||
const response = await client.search(params);
|
||||
const response = await apmEventClient.search(params);
|
||||
|
||||
return transformDataToMetricsChart(response, chartBase);
|
||||
}
|
||||
|
|
|
@ -6,10 +6,7 @@
|
|||
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import { rangeFilter } from '../../../common/utils/range_filter';
|
||||
import {
|
||||
SERVICE_NAME,
|
||||
PROCESSOR_EVENT,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
import { SERVICE_NAME } from '../../../common/elasticsearch_fieldnames';
|
||||
import { Setup, SetupTimeRange } from '../helpers/setup_request';
|
||||
|
||||
export async function getServiceCount({
|
||||
|
@ -17,36 +14,27 @@ export async function getServiceCount({
|
|||
}: {
|
||||
setup: Setup & SetupTimeRange;
|
||||
}) {
|
||||
const { client, indices, start, end } = setup;
|
||||
const { apmEventClient, start, end } = setup;
|
||||
|
||||
const params = {
|
||||
index: [
|
||||
indices['apm_oss.transactionIndices'],
|
||||
indices['apm_oss.errorIndices'],
|
||||
indices['apm_oss.metricsIndices'],
|
||||
apm: {
|
||||
events: [
|
||||
ProcessorEvent.transaction,
|
||||
ProcessorEvent.error,
|
||||
ProcessorEvent.metric,
|
||||
],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ range: rangeFilter(start, end) },
|
||||
{
|
||||
terms: {
|
||||
[PROCESSOR_EVENT]: [
|
||||
ProcessorEvent.error,
|
||||
ProcessorEvent.transaction,
|
||||
ProcessorEvent.metric,
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
filter: [{ range: rangeFilter(start, end) }],
|
||||
},
|
||||
},
|
||||
aggs: { serviceCount: { cardinality: { field: SERVICE_NAME } } },
|
||||
},
|
||||
};
|
||||
|
||||
const { aggregations } = await client.search(params);
|
||||
const { aggregations } = await apmEventClient.search(params);
|
||||
return aggregations?.serviceCount.value || 0;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
*/
|
||||
import { rangeFilter } from '../../../common/utils/range_filter';
|
||||
import { Coordinates } from '../../../../observability/public';
|
||||
import { PROCESSOR_EVENT } from '../../../common/elasticsearch_fieldnames';
|
||||
import { Setup, SetupTimeRange } from '../helpers/setup_request';
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
|
||||
|
@ -21,18 +20,17 @@ export async function getTransactionCoordinates({
|
|||
setup: Setup & SetupTimeRange;
|
||||
bucketSize: string;
|
||||
}): Promise<Coordinates[]> {
|
||||
const { client, indices, start, end } = setup;
|
||||
const { apmEventClient, start, end } = setup;
|
||||
|
||||
const { aggregations } = await client.search({
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
const { aggregations } = await apmEventClient.search({
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
],
|
||||
filter: [{ range: rangeFilter(start, end) }],
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
|
|
|
@ -3,41 +3,27 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { PROCESSOR_EVENT } from '../../../common/elasticsearch_fieldnames';
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import { Setup } from '../helpers/setup_request';
|
||||
|
||||
export async function hasData({ setup }: { setup: Setup }) {
|
||||
const { client, indices } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
try {
|
||||
const params = {
|
||||
index: [
|
||||
indices['apm_oss.transactionIndices'],
|
||||
indices['apm_oss.errorIndices'],
|
||||
indices['apm_oss.metricsIndices'],
|
||||
apm: {
|
||||
events: [
|
||||
ProcessorEvent.transaction,
|
||||
ProcessorEvent.error,
|
||||
ProcessorEvent.metric,
|
||||
],
|
||||
},
|
||||
terminateAfter: 1,
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
terms: {
|
||||
[PROCESSOR_EVENT]: [
|
||||
ProcessorEvent.error,
|
||||
ProcessorEvent.metric,
|
||||
ProcessorEvent.transaction,
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const response = await client.search(params);
|
||||
const response = await apmEventClient.search(params);
|
||||
return response.hits.total.value > 0;
|
||||
} catch (e) {
|
||||
return false;
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
exports[`rum client dashboard queries fetches client metrics 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"backEnd": Object {
|
||||
|
@ -34,11 +39,6 @@ Object {
|
|||
},
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"transaction.type": "page-load",
|
||||
|
@ -59,12 +59,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`rum client dashboard queries fetches page load distribution 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"durPercentiles": Object {
|
||||
|
@ -101,11 +105,6 @@ Object {
|
|||
},
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"transaction.type": "page-load",
|
||||
|
@ -126,12 +125,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`rum client dashboard queries fetches page view trends 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"pageViews": Object {
|
||||
|
@ -154,11 +157,6 @@ Object {
|
|||
},
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"transaction.type": "page-load",
|
||||
|
@ -179,12 +177,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`rum client dashboard queries fetches rum services 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"services": Object {
|
||||
|
@ -206,11 +208,6 @@ Object {
|
|||
},
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"transaction.type": "page-load",
|
||||
|
@ -231,6 +228,5 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { getRumOverviewProjection } from '../../../common/projections/rum_overview';
|
||||
import { mergeProjection } from '../../../common/projections/util/merge_projection';
|
||||
import { getRumOverviewProjection } from '../../projections/rum_overview';
|
||||
import { mergeProjection } from '../../projections/util/merge_projection';
|
||||
import {
|
||||
Setup,
|
||||
SetupTimeRange,
|
||||
|
@ -45,9 +45,9 @@ export async function getClientMetrics({
|
|||
},
|
||||
});
|
||||
|
||||
const { client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const response = await client.search(params);
|
||||
const response = await apmEventClient.search(params);
|
||||
const { backEnd, domInteractive, pageViews } = response.aggregations!;
|
||||
|
||||
// Divide by 1000 to convert ms into seconds
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { getRumOverviewProjection } from '../../../common/projections/rum_overview';
|
||||
import { mergeProjection } from '../../../common/projections/util/merge_projection';
|
||||
import { getRumOverviewProjection } from '../../projections/rum_overview';
|
||||
import { mergeProjection } from '../../projections/util/merge_projection';
|
||||
import {
|
||||
Setup,
|
||||
SetupTimeRange,
|
||||
|
@ -57,12 +57,12 @@ export async function getPageLoadDistribution({
|
|||
},
|
||||
});
|
||||
|
||||
const { client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const {
|
||||
aggregations,
|
||||
hits: { total },
|
||||
} = await client.search(params);
|
||||
} = await apmEventClient.search(params);
|
||||
|
||||
if (total.value === 0) {
|
||||
return null;
|
||||
|
@ -130,9 +130,9 @@ const getPercentilesDistribution = async (
|
|||
},
|
||||
});
|
||||
|
||||
const { client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const { aggregations } = await client.search(params);
|
||||
const { aggregations } = await apmEventClient.search(params);
|
||||
|
||||
const pageDist = aggregations?.loadDistribution.values ?? [];
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { getRumOverviewProjection } from '../../../common/projections/rum_overview';
|
||||
import { mergeProjection } from '../../../common/projections/util/merge_projection';
|
||||
import { getRumOverviewProjection } from '../../projections/rum_overview';
|
||||
import { mergeProjection } from '../../projections/util/merge_projection';
|
||||
import {
|
||||
Setup,
|
||||
SetupTimeRange,
|
||||
|
@ -56,9 +56,9 @@ export async function getPageViewTrends({
|
|||
},
|
||||
});
|
||||
|
||||
const { client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const response = await client.search(params);
|
||||
const response = await apmEventClient.search(params);
|
||||
|
||||
const result = response.aggregations?.pageViews.buckets ?? [];
|
||||
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { getRumOverviewProjection } from '../../../common/projections/rum_overview';
|
||||
import { mergeProjection } from '../../../common/projections/util/merge_projection';
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import { getRumOverviewProjection } from '../../projections/rum_overview';
|
||||
import { mergeProjection } from '../../projections/util/merge_projection';
|
||||
import {
|
||||
Setup,
|
||||
SetupTimeRange,
|
||||
|
@ -16,6 +17,7 @@ import {
|
|||
USER_AGENT_DEVICE,
|
||||
USER_AGENT_NAME,
|
||||
USER_AGENT_OS,
|
||||
TRANSACTION_DURATION,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
import { MICRO_TO_SEC, microToSec } from './get_page_load_distribution';
|
||||
|
||||
|
@ -53,11 +55,11 @@ export const getPageLoadDistBreakdown = async (
|
|||
});
|
||||
|
||||
const params = mergeProjection(projection, {
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: projection.body.query.bool,
|
||||
},
|
||||
aggs: {
|
||||
breakdowns: {
|
||||
terms: {
|
||||
|
@ -67,7 +69,7 @@ export const getPageLoadDistBreakdown = async (
|
|||
aggs: {
|
||||
page_dist: {
|
||||
percentile_ranks: {
|
||||
field: 'transaction.duration.us',
|
||||
field: TRANSACTION_DURATION,
|
||||
values: stepValues,
|
||||
keyed: false,
|
||||
hdr: {
|
||||
|
@ -81,9 +83,9 @@ export const getPageLoadDistBreakdown = async (
|
|||
},
|
||||
});
|
||||
|
||||
const { client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const { aggregations } = await client.search(params);
|
||||
const { aggregations } = await apmEventClient.search(params);
|
||||
|
||||
const pageDistBreakdowns = aggregations?.breakdowns.buckets;
|
||||
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { getRumOverviewProjection } from '../../../common/projections/rum_overview';
|
||||
import { mergeProjection } from '../../../common/projections/util/merge_projection';
|
||||
import {
|
||||
Setup,
|
||||
SetupTimeRange,
|
||||
SetupUIFilters,
|
||||
} from '../helpers/setup_request';
|
||||
import { getRumOverviewProjection } from '../../projections/rum_overview';
|
||||
import { mergeProjection } from '../../projections/util/merge_projection';
|
||||
|
||||
export async function getRumServices({
|
||||
setup,
|
||||
|
@ -38,9 +38,9 @@ export async function getRumServices({
|
|||
},
|
||||
});
|
||||
|
||||
const { client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const response = await client.search(params);
|
||||
const response = await apmEventClient.search(params);
|
||||
|
||||
const result = response.aggregations?.services.buckets ?? [];
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { getRumOverviewProjection } from '../../../common/projections/rum_overview';
|
||||
import { mergeProjection } from '../../../common/projections/util/merge_projection';
|
||||
import { getRumOverviewProjection } from '../../projections/rum_overview';
|
||||
import { mergeProjection } from '../../projections/util/merge_projection';
|
||||
import {
|
||||
Setup,
|
||||
SetupTimeRange,
|
||||
|
@ -55,9 +55,9 @@ export async function getVisitorBreakdown({
|
|||
},
|
||||
});
|
||||
|
||||
const { client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const response = await client.search(params);
|
||||
const response = await apmEventClient.search(params);
|
||||
const { browsers, os, devices } = response.aggregations!;
|
||||
|
||||
return {
|
||||
|
|
|
@ -3,10 +3,8 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
TRACE_ID,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import { TRACE_ID } from '../../../common/elasticsearch_fieldnames';
|
||||
import {
|
||||
ConnectionNode,
|
||||
ExternalConnectionNode,
|
||||
|
@ -18,23 +16,17 @@ export async function fetchServicePathsFromTraceIds(
|
|||
setup: Setup,
|
||||
traceIds: string[]
|
||||
) {
|
||||
const { indices, client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const serviceMapParams = {
|
||||
index: [
|
||||
indices['apm_oss.spanIndices'],
|
||||
indices['apm_oss.transactionIndices'],
|
||||
],
|
||||
apm: {
|
||||
events: [ProcessorEvent.span, ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
terms: {
|
||||
[PROCESSOR_EVENT]: ['span', 'transaction'],
|
||||
},
|
||||
},
|
||||
{
|
||||
terms: {
|
||||
[TRACE_ID]: traceIds,
|
||||
|
@ -212,7 +204,7 @@ export async function fetchServicePathsFromTraceIds(
|
|||
},
|
||||
};
|
||||
|
||||
const serviceMapFromTraceIdsScriptResponse = await client.search(
|
||||
const serviceMapFromTraceIdsScriptResponse = await apmEventClient.search(
|
||||
serviceMapParams
|
||||
);
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ import {
|
|||
SERVICE_ENVIRONMENT,
|
||||
SERVICE_NAME,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
import { getServicesProjection } from '../../../common/projections/services';
|
||||
import { mergeProjection } from '../../../common/projections/util/merge_projection';
|
||||
import { getServicesProjection } from '../../projections/services';
|
||||
import { mergeProjection } from '../../projections/util/merge_projection';
|
||||
import { PromiseReturnType } from '../../../typings/common';
|
||||
import { Setup, SetupTimeRange } from '../helpers/setup_request';
|
||||
import { transformServiceMapResponses } from './transform_service_map_responses';
|
||||
|
@ -118,9 +118,9 @@ async function getServicesData(options: IEnvOptions) {
|
|||
},
|
||||
});
|
||||
|
||||
const { client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const response = await client.search(params);
|
||||
const response = await apmEventClient.search(params);
|
||||
|
||||
return (
|
||||
response.aggregations?.services.buckets.map((bucket) => {
|
||||
|
|
|
@ -12,7 +12,7 @@ describe('getServiceMapServiceNodeInfo', () => {
|
|||
describe('with no results', () => {
|
||||
it('returns null data', async () => {
|
||||
const setup = ({
|
||||
client: {
|
||||
apmEventClient: {
|
||||
search: () =>
|
||||
Promise.resolve({
|
||||
hits: { total: { value: 0 } },
|
||||
|
@ -49,7 +49,7 @@ describe('getServiceMapServiceNodeInfo', () => {
|
|||
});
|
||||
|
||||
const setup = ({
|
||||
client: {
|
||||
apmEventClient: {
|
||||
search: () =>
|
||||
Promise.resolve({
|
||||
hits: { total: { value: 1 } },
|
||||
|
|
|
@ -6,13 +6,12 @@
|
|||
|
||||
import { UIFilters } from '../../../typings/ui_filters';
|
||||
import {
|
||||
SERVICE_NAME,
|
||||
TRANSACTION_DURATION,
|
||||
TRANSACTION_TYPE,
|
||||
METRIC_SYSTEM_CPU_PERCENT,
|
||||
METRIC_SYSTEM_FREE_MEMORY,
|
||||
METRIC_SYSTEM_TOTAL_MEMORY,
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
TRANSACTION_DURATION,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import { rangeFilter } from '../../../common/utils/range_filter';
|
||||
|
@ -109,17 +108,18 @@ async function getTransactionStats({
|
|||
avgTransactionDuration: number | null;
|
||||
avgRequestsPerMinute: number | null;
|
||||
}> {
|
||||
const { indices, client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const params = {
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
...filter,
|
||||
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
|
||||
{
|
||||
terms: {
|
||||
[TRANSACTION_TYPE]: [
|
||||
|
@ -135,8 +135,9 @@ async function getTransactionStats({
|
|||
aggs: { duration: { avg: { field: TRANSACTION_DURATION } } },
|
||||
},
|
||||
};
|
||||
const response = await client.search(params);
|
||||
const response = await apmEventClient.search(params);
|
||||
const docCount = response.hits.total.value;
|
||||
|
||||
return {
|
||||
avgTransactionDuration: response.aggregations?.duration.value ?? null,
|
||||
avgRequestsPerMinute: docCount > 0 ? docCount / minutes : null,
|
||||
|
@ -147,18 +148,17 @@ async function getCpuStats({
|
|||
setup,
|
||||
filter,
|
||||
}: TaskParameters): Promise<{ avgCpuUsage: number | null }> {
|
||||
const { indices, client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const response = await client.search({
|
||||
index: indices['apm_oss.metricsIndices'],
|
||||
const response = await apmEventClient.search({
|
||||
apm: {
|
||||
events: [ProcessorEvent.metric],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: filter.concat([
|
||||
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.metric } },
|
||||
{ exists: { field: METRIC_SYSTEM_CPU_PERCENT } },
|
||||
]),
|
||||
filter: [...filter, { exists: { field: METRIC_SYSTEM_CPU_PERCENT } }],
|
||||
},
|
||||
},
|
||||
aggs: { avgCpuUsage: { avg: { field: METRIC_SYSTEM_CPU_PERCENT } } },
|
||||
|
@ -172,17 +172,19 @@ async function getMemoryStats({
|
|||
setup,
|
||||
filter,
|
||||
}: TaskParameters): Promise<{ avgMemoryUsage: number | null }> {
|
||||
const { client, indices } = setup;
|
||||
const response = await client.search({
|
||||
index: indices['apm_oss.metricsIndices'],
|
||||
const { apmEventClient } = setup;
|
||||
const response = await apmEventClient.search({
|
||||
apm: {
|
||||
events: [ProcessorEvent.metric],
|
||||
},
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
filter: filter.concat([
|
||||
{ term: { [PROCESSOR_EVENT]: 'metric' } },
|
||||
filter: [
|
||||
...filter,
|
||||
{ exists: { field: METRIC_SYSTEM_FREE_MEMORY } },
|
||||
{ exists: { field: METRIC_SYSTEM_TOTAL_MEMORY } },
|
||||
]),
|
||||
],
|
||||
},
|
||||
},
|
||||
aggs: { avgMemoryUsage: { avg: { script: percentMemoryUsedScript } } },
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { uniq, take, sortBy } from 'lodash';
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import { Setup, SetupTimeRange } from '../helpers/setup_request';
|
||||
import { rangeFilter } from '../../../common/utils/range_filter';
|
||||
import { ESFilter } from '../../../typings/elasticsearch';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
SERVICE_ENVIRONMENT,
|
||||
TRACE_ID,
|
||||
|
@ -26,18 +26,13 @@ export async function getTraceSampleIds({
|
|||
environment?: string;
|
||||
setup: Setup & SetupTimeRange;
|
||||
}) {
|
||||
const { start, end, client, indices, config } = setup;
|
||||
const { start, end, apmEventClient, config } = setup;
|
||||
|
||||
const rangeQuery = { range: rangeFilter(start, end) };
|
||||
|
||||
const query = {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
term: {
|
||||
[PROCESSOR_EVENT]: 'span',
|
||||
},
|
||||
},
|
||||
{
|
||||
exists: {
|
||||
field: SPAN_DESTINATION_SERVICE_RESOURCE,
|
||||
|
@ -67,7 +62,9 @@ export async function getTraceSampleIds({
|
|||
const samplerShardSize = traceIdBucketSize * 10;
|
||||
|
||||
const params = {
|
||||
index: [indices['apm_oss.spanIndices']],
|
||||
apm: {
|
||||
events: [ProcessorEvent.span],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query,
|
||||
|
@ -126,9 +123,7 @@ export async function getTraceSampleIds({
|
|||
},
|
||||
};
|
||||
|
||||
const tracesSampleResponse = await client.search<unknown, typeof params>(
|
||||
params
|
||||
);
|
||||
const tracesSampleResponse = await apmEventClient.search(params);
|
||||
|
||||
// make sure at least one trace per composite/connection bucket
|
||||
// is queried
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
exports[`service node queries fetches metadata for a service node 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"containerId": Object {
|
||||
|
@ -30,11 +35,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -59,12 +59,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`service node queries fetches metadata for unidentified service nodes 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"containerId": Object {
|
||||
|
@ -93,11 +97,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -128,12 +127,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`service node queries fetches services nodes 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"nodes": Object {
|
||||
|
@ -174,11 +177,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -197,6 +195,5 @@ Object {
|
|||
},
|
||||
},
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -9,8 +9,8 @@ import {
|
|||
SetupTimeRange,
|
||||
SetupUIFilters,
|
||||
} from '../helpers/setup_request';
|
||||
import { getServiceNodesProjection } from '../../../common/projections/service_nodes';
|
||||
import { mergeProjection } from '../../../common/projections/util/merge_projection';
|
||||
import { getServiceNodesProjection } from '../../projections/service_nodes';
|
||||
import { mergeProjection } from '../../projections/util/merge_projection';
|
||||
import { SERVICE_NODE_NAME_MISSING } from '../../../common/service_nodes';
|
||||
import {
|
||||
METRIC_PROCESS_CPU_PERCENT,
|
||||
|
@ -26,7 +26,7 @@ const getServiceNodes = async ({
|
|||
setup: Setup & SetupTimeRange & SetupUIFilters;
|
||||
serviceName: string;
|
||||
}) => {
|
||||
const { client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const projection = getServiceNodesProjection({ setup, serviceName });
|
||||
|
||||
|
@ -66,7 +66,7 @@ const getServiceNodes = async ({
|
|||
},
|
||||
});
|
||||
|
||||
const response = await client.search(params);
|
||||
const response = await apmEventClient.search(params);
|
||||
|
||||
if (!response.aggregations) {
|
||||
return [];
|
||||
|
|
|
@ -2,48 +2,32 @@
|
|||
|
||||
exports[`services queries fetches the agent status 1`] = `
|
||||
Object {
|
||||
"body": Object {
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"terms": Object {
|
||||
"processor.event": Array [
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"error",
|
||||
"metric",
|
||||
"sourcemap",
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"body": Object {
|
||||
"size": 0,
|
||||
},
|
||||
"index": Array [
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
],
|
||||
"terminateAfter": 1,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`services queries fetches the legacy data status 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"terms": Object {
|
||||
"processor.event": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"observer.version_major": Object {
|
||||
|
@ -56,13 +40,19 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
"terminateAfter": 1,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`services queries fetches the service agent name 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"error",
|
||||
"transaction",
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"agents": Object {
|
||||
|
@ -80,15 +70,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"terms": Object {
|
||||
"processor.event": Array [
|
||||
"error",
|
||||
"transaction",
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -103,11 +84,6 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": Array [
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
],
|
||||
"terminateAfter": 1,
|
||||
}
|
||||
`;
|
||||
|
@ -115,6 +91,11 @@ Object {
|
|||
exports[`services queries fetches the service items 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"services": Object {
|
||||
|
@ -148,20 +129,20 @@ Array [
|
|||
"my.custom.ui.filter": "foo-bar",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
"size": 0,
|
||||
},
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
"error",
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"services": Object {
|
||||
|
@ -198,27 +179,18 @@ Array [
|
|||
"my.custom.ui.filter": "foo-bar",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"size": 0,
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"terms": Object {
|
||||
"processor.event": Array [
|
||||
"metric",
|
||||
"error",
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": Array [
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"services": Object {
|
||||
|
@ -245,19 +217,18 @@ Array [
|
|||
"my.custom.ui.filter": "foo-bar",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
},
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"error",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"services": Object {
|
||||
|
@ -284,19 +255,20 @@ Array [
|
|||
"my.custom.ui.filter": "foo-bar",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "error",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
},
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
"transaction",
|
||||
"error",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"services": Object {
|
||||
|
@ -330,31 +302,22 @@ Array [
|
|||
"my.custom.ui.filter": "foo-bar",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"terms": Object {
|
||||
"processor.event": Array [
|
||||
"transaction",
|
||||
"error",
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": Array [
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
],
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`services queries fetches the service transaction types 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"types": Object {
|
||||
|
@ -372,13 +335,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"terms": Object {
|
||||
"processor.event": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -393,6 +349,5 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { isNumber } from 'lodash';
|
||||
import { ProcessorEvent } from '../../../../common/processor_event';
|
||||
import { Annotation, AnnotationType } from '../../../../common/annotations';
|
||||
import { SetupTimeRange, Setup } from '../../helpers/setup_request';
|
||||
import { ESFilter } from '../../../../typings/elasticsearch';
|
||||
import { rangeFilter } from '../../../../common/utils/range_filter';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
SERVICE_VERSION,
|
||||
} from '../../../../common/elasticsearch_fieldnames';
|
||||
|
@ -24,23 +24,24 @@ export async function getDerivedServiceAnnotations({
|
|||
environment?: string;
|
||||
setup: Setup & SetupTimeRange;
|
||||
}) {
|
||||
const { start, end, client, indices } = setup;
|
||||
const { start, end, apmEventClient } = setup;
|
||||
|
||||
const filter: ESFilter[] = [
|
||||
{ term: { [PROCESSOR_EVENT]: 'transaction' } },
|
||||
{ term: { [SERVICE_NAME]: serviceName } },
|
||||
...getEnvironmentUiFilterES(environment),
|
||||
];
|
||||
|
||||
const versions =
|
||||
(
|
||||
await client.search({
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
await apmEventClient.search({
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: filter.concat({ range: rangeFilter(start, end) }),
|
||||
filter: [...filter, { range: rangeFilter(start, end) }],
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
|
@ -59,17 +60,15 @@ export async function getDerivedServiceAnnotations({
|
|||
}
|
||||
const annotations = await Promise.all(
|
||||
versions.map(async (version) => {
|
||||
const response = await client.search({
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
const response = await apmEventClient.search({
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: filter.concat({
|
||||
term: {
|
||||
[SERVICE_VERSION]: version,
|
||||
},
|
||||
}),
|
||||
filter: [...filter, { term: { [SERVICE_VERSION]: version } }],
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
AGENT_NAME,
|
||||
SERVICE_NAME,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
|
@ -15,24 +15,23 @@ export async function getServiceAgentName(
|
|||
serviceName: string,
|
||||
setup: Setup & SetupTimeRange
|
||||
) {
|
||||
const { start, end, client, indices } = setup;
|
||||
const { start, end, apmEventClient } = setup;
|
||||
|
||||
const params = {
|
||||
terminateAfter: 1,
|
||||
index: [
|
||||
indices['apm_oss.errorIndices'],
|
||||
indices['apm_oss.transactionIndices'],
|
||||
indices['apm_oss.metricsIndices'],
|
||||
apm: {
|
||||
events: [
|
||||
ProcessorEvent.error,
|
||||
ProcessorEvent.transaction,
|
||||
ProcessorEvent.metric,
|
||||
],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ term: { [SERVICE_NAME]: serviceName } },
|
||||
{
|
||||
terms: { [PROCESSOR_EVENT]: ['error', 'transaction', 'metric'] },
|
||||
},
|
||||
{ range: rangeFilter(start, end) },
|
||||
],
|
||||
},
|
||||
|
@ -45,7 +44,7 @@ export async function getServiceAgentName(
|
|||
},
|
||||
};
|
||||
|
||||
const { aggregations } = await client.search(params);
|
||||
const { aggregations } = await apmEventClient.search(params);
|
||||
const agentName = aggregations?.agents.buckets[0]?.key as string | undefined;
|
||||
return { agentName };
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ import {
|
|||
CONTAINER_ID,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
import { NOT_AVAILABLE_LABEL } from '../../../common/i18n';
|
||||
import { mergeProjection } from '../../../common/projections/util/merge_projection';
|
||||
import { getServiceNodesProjection } from '../../../common/projections/service_nodes';
|
||||
import { mergeProjection } from '../../projections/util/merge_projection';
|
||||
import { getServiceNodesProjection } from '../../projections/service_nodes';
|
||||
|
||||
export async function getServiceNodeMetadata({
|
||||
serviceName,
|
||||
|
@ -26,7 +26,7 @@ export async function getServiceNodeMetadata({
|
|||
serviceNodeName: string;
|
||||
setup: Setup & SetupTimeRange & SetupUIFilters;
|
||||
}) {
|
||||
const { client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const query = mergeProjection(
|
||||
getServiceNodesProjection({
|
||||
|
@ -55,7 +55,7 @@ export async function getServiceNodeMetadata({
|
|||
}
|
||||
);
|
||||
|
||||
const response = await client.search(query);
|
||||
const response = await apmEventClient.search(query);
|
||||
|
||||
return {
|
||||
host: response.aggregations?.host.buckets[0]?.key || NOT_AVAILABLE_LABEL,
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
TRANSACTION_TYPE,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
|
@ -15,17 +15,18 @@ export async function getServiceTransactionTypes(
|
|||
serviceName: string,
|
||||
setup: Setup & SetupTimeRange
|
||||
) {
|
||||
const { start, end, client, indices } = setup;
|
||||
const { start, end, apmEventClient } = setup;
|
||||
|
||||
const params = {
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ term: { [SERVICE_NAME]: serviceName } },
|
||||
{ terms: { [PROCESSOR_EVENT]: ['transaction'] } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
],
|
||||
},
|
||||
|
@ -38,7 +39,7 @@ export async function getServiceTransactionTypes(
|
|||
},
|
||||
};
|
||||
|
||||
const { aggregations } = await client.search(params);
|
||||
const { aggregations } = await apmEventClient.search(params);
|
||||
const transactionTypes =
|
||||
aggregations?.types.buckets.map((bucket) => bucket.key as string) || [];
|
||||
return { transactionTypes };
|
||||
|
|
|
@ -4,33 +4,30 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import {
|
||||
OBSERVER_VERSION_MAJOR,
|
||||
PROCESSOR_EVENT,
|
||||
} from '../../../../common/elasticsearch_fieldnames';
|
||||
import { ProcessorEvent } from '../../../../common/processor_event';
|
||||
import { OBSERVER_VERSION_MAJOR } from '../../../../common/elasticsearch_fieldnames';
|
||||
import { Setup } from '../../helpers/setup_request';
|
||||
|
||||
// returns true if 6.x data is found
|
||||
export async function getLegacyDataStatus(setup: Setup) {
|
||||
const { client, indices } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const params = {
|
||||
terminateAfter: 1,
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ terms: { [PROCESSOR_EVENT]: ['transaction'] } },
|
||||
{ range: { [OBSERVER_VERSION_MAJOR]: { lt: 7 } } },
|
||||
],
|
||||
filter: [{ range: { [OBSERVER_VERSION_MAJOR]: { lt: 7 } } }],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const resp = await client.search(params, { includeLegacyData: true });
|
||||
const resp = await apmEventClient.search(params, { includeLegacyData: true });
|
||||
const hasLegacyData = resp.hits.total.value > 0;
|
||||
return hasLegacyData;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
SetupTimeRange,
|
||||
SetupUIFilters,
|
||||
} from '../../helpers/setup_request';
|
||||
import { getServicesProjection } from '../../../../common/projections/services';
|
||||
import { getServicesProjection } from '../../../projections/services';
|
||||
import {
|
||||
getTransactionDurationAverages,
|
||||
getAgentNames,
|
||||
|
@ -25,7 +25,7 @@ export type ServicesItemsProjection = ReturnType<typeof getServicesProjection>;
|
|||
|
||||
export async function getServicesItems(setup: ServicesItemsSetup) {
|
||||
const params = {
|
||||
projection: getServicesProjection({ setup, noEvents: true }),
|
||||
projection: getServicesProjection({ setup }),
|
||||
setup,
|
||||
};
|
||||
|
||||
|
|
|
@ -5,12 +5,11 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
TRANSACTION_DURATION,
|
||||
AGENT_NAME,
|
||||
SERVICE_ENVIRONMENT,
|
||||
} from '../../../../common/elasticsearch_fieldnames';
|
||||
import { mergeProjection } from '../../../../common/projections/util/merge_projection';
|
||||
import { mergeProjection } from '../../../projections/util/merge_projection';
|
||||
import { ProcessorEvent } from '../../../../common/processor_event';
|
||||
import {
|
||||
ServicesItemsSetup,
|
||||
|
@ -31,22 +30,15 @@ export const getTransactionDurationAverages = async ({
|
|||
setup,
|
||||
projection,
|
||||
}: AggregationParams) => {
|
||||
const { client, indices } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const response = await client.search(
|
||||
const response = await apmEventClient.search(
|
||||
mergeProjection(projection, {
|
||||
size: 0,
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
filter: projection.body.query.bool.filter.concat({
|
||||
term: {
|
||||
[PROCESSOR_EVENT]: ProcessorEvent.transaction,
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
size: 0,
|
||||
aggs: {
|
||||
services: {
|
||||
terms: {
|
||||
|
@ -82,32 +74,18 @@ export const getAgentNames = async ({
|
|||
setup,
|
||||
projection,
|
||||
}: AggregationParams) => {
|
||||
const { client, indices } = setup;
|
||||
const response = await client.search(
|
||||
const { apmEventClient } = setup;
|
||||
const response = await apmEventClient.search(
|
||||
mergeProjection(projection, {
|
||||
index: [
|
||||
indices['apm_oss.metricsIndices'],
|
||||
indices['apm_oss.errorIndices'],
|
||||
indices['apm_oss.transactionIndices'],
|
||||
],
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
...projection.body.query.bool.filter,
|
||||
{
|
||||
terms: {
|
||||
[PROCESSOR_EVENT]: [
|
||||
apm: {
|
||||
events: [
|
||||
ProcessorEvent.metric,
|
||||
ProcessorEvent.error,
|
||||
ProcessorEvent.transaction,
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
aggs: {
|
||||
services: {
|
||||
terms: {
|
||||
|
@ -136,11 +114,7 @@ export const getAgentNames = async ({
|
|||
|
||||
return aggregations.services.buckets.map((bucket) => ({
|
||||
serviceName: bucket.key as string,
|
||||
agentName: (bucket.agent_name.hits.hits[0]?._source as {
|
||||
agent: {
|
||||
name: string;
|
||||
};
|
||||
}).agent.name,
|
||||
agentName: bucket.agent_name.hits.hits[0]?._source.agent.name,
|
||||
}));
|
||||
};
|
||||
|
||||
|
@ -148,24 +122,14 @@ export const getTransactionRates = async ({
|
|||
setup,
|
||||
projection,
|
||||
}: AggregationParams) => {
|
||||
const { client, indices } = setup;
|
||||
const response = await client.search(
|
||||
const { apmEventClient } = setup;
|
||||
const response = await apmEventClient.search(
|
||||
mergeProjection(projection, {
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
...projection.body.query.bool.filter,
|
||||
{
|
||||
term: {
|
||||
[PROCESSOR_EVENT]: ProcessorEvent.transaction,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
services: {
|
||||
terms: {
|
||||
|
@ -199,24 +163,14 @@ export const getErrorRates = async ({
|
|||
setup,
|
||||
projection,
|
||||
}: AggregationParams) => {
|
||||
const { client, indices } = setup;
|
||||
const response = await client.search(
|
||||
const { apmEventClient } = setup;
|
||||
const response = await apmEventClient.search(
|
||||
mergeProjection(projection, {
|
||||
index: indices['apm_oss.errorIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.error],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
...projection.body.query.bool.filter,
|
||||
{
|
||||
term: {
|
||||
[PROCESSOR_EVENT]: ProcessorEvent.error,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
services: {
|
||||
terms: {
|
||||
|
@ -250,32 +204,18 @@ export const getEnvironments = async ({
|
|||
setup,
|
||||
projection,
|
||||
}: AggregationParams) => {
|
||||
const { client, indices } = setup;
|
||||
const response = await client.search(
|
||||
const { apmEventClient } = setup;
|
||||
const response = await apmEventClient.search(
|
||||
mergeProjection(projection, {
|
||||
index: [
|
||||
indices['apm_oss.metricsIndices'],
|
||||
indices['apm_oss.errorIndices'],
|
||||
indices['apm_oss.transactionIndices'],
|
||||
],
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
...projection.body.query.bool.filter,
|
||||
{
|
||||
terms: {
|
||||
[PROCESSOR_EVENT]: [
|
||||
apm: {
|
||||
events: [
|
||||
ProcessorEvent.metric,
|
||||
ProcessorEvent.transaction,
|
||||
ProcessorEvent.error,
|
||||
ProcessorEvent.metric,
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
aggs: {
|
||||
services: {
|
||||
terms: {
|
||||
|
|
|
@ -4,43 +4,28 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { PROCESSOR_EVENT } from '../../../../common/elasticsearch_fieldnames';
|
||||
import { ProcessorEvent } from '../../../../common/processor_event';
|
||||
import { Setup } from '../../helpers/setup_request';
|
||||
|
||||
// Note: this logic is duplicated in tutorials/apm/envs/on_prem
|
||||
export async function hasHistoricalAgentData(setup: Setup) {
|
||||
const { client, indices } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const params = {
|
||||
terminateAfter: 1,
|
||||
index: [
|
||||
indices['apm_oss.errorIndices'],
|
||||
indices['apm_oss.metricsIndices'],
|
||||
indices['apm_oss.sourcemapIndices'],
|
||||
indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [
|
||||
ProcessorEvent.error,
|
||||
ProcessorEvent.metric,
|
||||
ProcessorEvent.sourcemap,
|
||||
ProcessorEvent.transaction,
|
||||
],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
terms: {
|
||||
[PROCESSOR_EVENT]: [
|
||||
'error',
|
||||
'metric',
|
||||
'sourcemap',
|
||||
'transaction',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const resp = await client.search(params);
|
||||
const hasHistorialAgentData = resp.hits.total.value > 0;
|
||||
return hasHistorialAgentData;
|
||||
const resp = await apmEventClient.search(params);
|
||||
return resp.hits.total.value > 0;
|
||||
}
|
||||
|
|
|
@ -115,6 +115,13 @@ Object {
|
|||
|
||||
exports[`agent configuration queries getServiceNames fetches service names 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
"error",
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"services": Object {
|
||||
|
@ -124,28 +131,8 @@ Object {
|
|||
},
|
||||
},
|
||||
},
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"terms": Object {
|
||||
"processor.event": Array [
|
||||
"transaction",
|
||||
"error",
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": Array [
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
AgentConfiguration,
|
||||
AgentConfigurationIntake,
|
||||
} from '../../../../common/agent_configuration/configuration_types';
|
||||
import { APMIndexDocumentParams } from '../../helpers/es_client';
|
||||
import { APMIndexDocumentParams } from '../../helpers/create_es_client/create_internal_es_client';
|
||||
|
||||
export async function createOrUpdateConfiguration({
|
||||
configurationId,
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ProcessorEvent } from '../../../../common/processor_event';
|
||||
import { Setup } from '../../helpers/setup_request';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
} from '../../../../common/elasticsearch_fieldnames';
|
||||
import { SERVICE_NAME } from '../../../../common/elasticsearch_fieldnames';
|
||||
import { AGENT_NAME } from '../../../../common/elasticsearch_fieldnames';
|
||||
|
||||
export async function getAgentNameByService({
|
||||
|
@ -18,25 +16,22 @@ export async function getAgentNameByService({
|
|||
serviceName: string;
|
||||
setup: Setup;
|
||||
}) {
|
||||
const { client, indices } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const params = {
|
||||
terminateAfter: 1,
|
||||
index: [
|
||||
indices['apm_oss.metricsIndices'],
|
||||
indices['apm_oss.errorIndices'],
|
||||
indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [
|
||||
ProcessorEvent.transaction,
|
||||
ProcessorEvent.error,
|
||||
ProcessorEvent.metric,
|
||||
],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
terms: { [PROCESSOR_EVENT]: ['transaction', 'error', 'metric'] },
|
||||
},
|
||||
{ term: { [SERVICE_NAME]: serviceName } },
|
||||
],
|
||||
filter: [{ term: { [SERVICE_NAME]: serviceName } }],
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
|
@ -47,7 +42,7 @@ export async function getAgentNameByService({
|
|||
},
|
||||
};
|
||||
|
||||
const { aggregations } = await client.search(params);
|
||||
const { aggregations } = await apmEventClient.search(params);
|
||||
const agentName = aggregations?.agent_names.buckets[0]?.key;
|
||||
return agentName as string | undefined;
|
||||
}
|
||||
|
|
|
@ -4,37 +4,28 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ProcessorEvent } from '../../../../common/processor_event';
|
||||
import { Setup } from '../../helpers/setup_request';
|
||||
import { PromiseReturnType } from '../../../../../observability/typings/common';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
} from '../../../../common/elasticsearch_fieldnames';
|
||||
import { SERVICE_NAME } from '../../../../common/elasticsearch_fieldnames';
|
||||
import { ALL_OPTION_VALUE } from '../../../../common/agent_configuration/all_option';
|
||||
|
||||
export type AgentConfigurationServicesAPIResponse = PromiseReturnType<
|
||||
typeof getServiceNames
|
||||
>;
|
||||
export async function getServiceNames({ setup }: { setup: Setup }) {
|
||||
const { client, indices } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const params = {
|
||||
index: [
|
||||
indices['apm_oss.metricsIndices'],
|
||||
indices['apm_oss.errorIndices'],
|
||||
indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [
|
||||
ProcessorEvent.transaction,
|
||||
ProcessorEvent.error,
|
||||
ProcessorEvent.metric,
|
||||
],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
terms: { [PROCESSOR_EVENT]: ['transaction', 'error', 'metric'] },
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
services: {
|
||||
terms: {
|
||||
|
@ -46,7 +37,7 @@ export async function getServiceNames({ setup }: { setup: Setup }) {
|
|||
},
|
||||
};
|
||||
|
||||
const resp = await client.search(params);
|
||||
const resp = await apmEventClient.search(params);
|
||||
const serviceNames =
|
||||
resp.aggregations?.services.buckets
|
||||
.map((bucket) => bucket.key as string)
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
|
||||
exports[`custom link get transaction fetches with all filter 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"terms": Object {
|
||||
"service.name": Array [
|
||||
|
@ -43,7 +43,6 @@ Object {
|
|||
},
|
||||
},
|
||||
},
|
||||
"index": "myIndex",
|
||||
"size": 1,
|
||||
"terminateAfter": 1,
|
||||
}
|
||||
|
@ -51,20 +50,18 @@ Object {
|
|||
|
||||
exports[`custom link get transaction fetches without filter 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
],
|
||||
"filter": Array [],
|
||||
},
|
||||
},
|
||||
},
|
||||
"index": "myIndex",
|
||||
"size": 1,
|
||||
"terminateAfter": 1,
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@ import {
|
|||
CustomLink,
|
||||
CustomLinkES,
|
||||
} from '../../../../common/custom_link/custom_link_types';
|
||||
import { APMIndexDocumentParams } from '../../helpers/es_client';
|
||||
import { Setup } from '../../helpers/setup_request';
|
||||
import { toESFormat } from './helper';
|
||||
import { APMIndexDocumentParams } from '../../helpers/create_es_client/create_internal_es_client';
|
||||
|
||||
export async function createOrUpdateCustomLink({
|
||||
customLinkId,
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import * as t from 'io-ts';
|
||||
import { PROCESSOR_EVENT } from '../../../../common/elasticsearch_fieldnames';
|
||||
import { Transaction } from '../../../../typings/es_schemas/ui/transaction';
|
||||
import { Setup } from '../../helpers/setup_request';
|
||||
import { ProcessorEvent } from '../../../../common/processor_event';
|
||||
import { filterOptionsRt } from './custom_link_types';
|
||||
|
@ -18,7 +16,7 @@ export async function getTransaction({
|
|||
setup: Setup;
|
||||
filters?: t.TypeOf<typeof filterOptionsRt>;
|
||||
}) {
|
||||
const { client, indices } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const esFilters = Object.entries(filters)
|
||||
// loops through the filters splitting the value by comma and removing white spaces
|
||||
|
@ -32,19 +30,18 @@ export async function getTransaction({
|
|||
|
||||
const params = {
|
||||
terminateAfter: 1,
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction as const],
|
||||
},
|
||||
size: 1,
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
|
||||
...esFilters,
|
||||
],
|
||||
filter: esFilters,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const resp = await client.search<Transaction>(params);
|
||||
const resp = await apmEventClient.search(params);
|
||||
return resp.hits.hits[0]?._source;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
exports[`trace queries fetches a trace 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"error",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"by_transaction_id": Object {
|
||||
|
@ -20,11 +25,6 @@ Object {
|
|||
"trace.id": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "error",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -48,6 +48,5 @@ Object {
|
|||
},
|
||||
"size": "myIndex",
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
TRACE_ID,
|
||||
PARENT_ID,
|
||||
TRANSACTION_DURATION,
|
||||
|
@ -13,8 +13,6 @@ import {
|
|||
TRANSACTION_ID,
|
||||
ERROR_LOG_LEVEL,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
import { Span } from '../../../typings/es_schemas/ui/span';
|
||||
import { Transaction } from '../../../typings/es_schemas/ui/transaction';
|
||||
import { APMError } from '../../../typings/es_schemas/ui/apm_error';
|
||||
import { rangeFilter } from '../../../common/utils/range_filter';
|
||||
import { Setup, SetupTimeRange } from '../helpers/setup_request';
|
||||
|
@ -28,19 +26,20 @@ export async function getTraceItems(
|
|||
traceId: string,
|
||||
setup: Setup & SetupTimeRange
|
||||
) {
|
||||
const { start, end, client, config, indices } = setup;
|
||||
const { start, end, apmEventClient, config } = setup;
|
||||
const maxTraceItems = config['xpack.apm.ui.maxTraceItems'];
|
||||
const excludedLogLevels = ['debug', 'info', 'warning'];
|
||||
|
||||
const errorResponsePromise = client.search({
|
||||
index: indices['apm_oss.errorIndices'],
|
||||
const errorResponsePromise = apmEventClient.search({
|
||||
apm: {
|
||||
events: [ProcessorEvent.error],
|
||||
},
|
||||
body: {
|
||||
size: maxTraceItems,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ term: { [TRACE_ID]: traceId } },
|
||||
{ term: { [PROCESSOR_EVENT]: 'error' } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
],
|
||||
must_not: { terms: { [ERROR_LOG_LEVEL]: excludedLogLevels } },
|
||||
|
@ -59,18 +58,16 @@ export async function getTraceItems(
|
|||
},
|
||||
});
|
||||
|
||||
const traceResponsePromise = client.search({
|
||||
index: [
|
||||
indices['apm_oss.spanIndices'],
|
||||
indices['apm_oss.transactionIndices'],
|
||||
],
|
||||
const traceResponsePromise = apmEventClient.search({
|
||||
apm: {
|
||||
events: [ProcessorEvent.span, ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: maxTraceItems,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ term: { [TRACE_ID]: traceId } },
|
||||
{ terms: { [PROCESSOR_EVENT]: ['span', 'transaction'] } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
],
|
||||
should: {
|
||||
|
@ -91,22 +88,17 @@ export async function getTraceItems(
|
|||
// explicit intermediary types to avoid TS "excessively deep" error
|
||||
PromiseValueType<typeof errorResponsePromise>,
|
||||
PromiseValueType<typeof traceResponsePromise>
|
||||
// @ts-ignore
|
||||
] = await Promise.all([errorResponsePromise, traceResponsePromise]);
|
||||
|
||||
const exceedsMax = traceResponse.hits.total.value > maxTraceItems;
|
||||
|
||||
const items = (traceResponse.hits.hits as Array<{
|
||||
_source: Transaction | Span;
|
||||
}>).map((hit) => hit._source);
|
||||
const items = traceResponse.hits.hits.map((hit) => hit._source);
|
||||
|
||||
const errorFrequencies: {
|
||||
errorsPerTransaction: ErrorsPerTransaction;
|
||||
errorDocs: APMError[];
|
||||
} = {
|
||||
errorDocs: errorResponse.hits.hits.map(
|
||||
({ _source }) => _source as APMError
|
||||
),
|
||||
errorDocs: errorResponse.hits.hits.map(({ _source }) => _source),
|
||||
errorsPerTransaction:
|
||||
errorResponse.aggregations?.by_transaction_id.buckets.reduce(
|
||||
(acc, current) => {
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
exports[`transaction group queries fetches top traces 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"transaction_groups": Object {
|
||||
|
@ -46,11 +51,6 @@ Array [
|
|||
},
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"my.custom.ui.filter": "foo-bar",
|
||||
|
@ -84,10 +84,14 @@ Array [
|
|||
},
|
||||
],
|
||||
},
|
||||
"index": "myIndex",
|
||||
"size": 0,
|
||||
},
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"transaction_groups": Object {
|
||||
|
@ -131,11 +135,6 @@ Array [
|
|||
},
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"my.custom.ui.filter": "foo-bar",
|
||||
|
@ -152,10 +151,14 @@ Array [
|
|||
},
|
||||
},
|
||||
},
|
||||
"index": "myIndex",
|
||||
"size": 0,
|
||||
},
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"transaction_groups": Object {
|
||||
|
@ -199,11 +202,6 @@ Array [
|
|||
},
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"my.custom.ui.filter": "foo-bar",
|
||||
|
@ -220,7 +218,6 @@ Array [
|
|||
},
|
||||
},
|
||||
},
|
||||
"index": "myIndex",
|
||||
"size": 0,
|
||||
},
|
||||
]
|
||||
|
@ -229,6 +226,11 @@ Array [
|
|||
exports[`transaction group queries fetches top transactions 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"transaction_groups": Object {
|
||||
|
@ -257,11 +259,6 @@ Array [
|
|||
},
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"transaction.type": "bar",
|
||||
|
@ -298,10 +295,14 @@ Array [
|
|||
},
|
||||
],
|
||||
},
|
||||
"index": "myIndex",
|
||||
"size": 0,
|
||||
},
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"transaction_groups": Object {
|
||||
|
@ -330,11 +331,6 @@ Array [
|
|||
},
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"transaction.type": "bar",
|
||||
|
@ -354,10 +350,14 @@ Array [
|
|||
},
|
||||
},
|
||||
},
|
||||
"index": "myIndex",
|
||||
"size": 0,
|
||||
},
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"transaction_groups": Object {
|
||||
|
@ -386,11 +386,6 @@ Array [
|
|||
},
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"transaction.type": "bar",
|
||||
|
@ -410,10 +405,14 @@ Array [
|
|||
},
|
||||
},
|
||||
},
|
||||
"index": "myIndex",
|
||||
"size": 0,
|
||||
},
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"transaction_groups": Object {
|
||||
|
@ -448,11 +447,6 @@ Array [
|
|||
},
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"transaction.type": "bar",
|
||||
|
@ -472,7 +466,6 @@ Array [
|
|||
},
|
||||
},
|
||||
},
|
||||
"index": "myIndex",
|
||||
"size": 0,
|
||||
},
|
||||
]
|
||||
|
|
|
@ -7,13 +7,12 @@ import { take, sortBy } from 'lodash';
|
|||
import { Unionize } from 'utility-types';
|
||||
import moment from 'moment';
|
||||
import { joinByKey } from '../../../common/utils/join_by_key';
|
||||
import { ESSearchRequest } from '../../../typings/elasticsearch';
|
||||
import {
|
||||
SERVICE_NAME,
|
||||
TRANSACTION_NAME,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
import { getTransactionGroupsProjection } from '../../../common/projections/transaction_groups';
|
||||
import { mergeProjection } from '../../../common/projections/util/merge_projection';
|
||||
import { getTransactionGroupsProjection } from '../../projections/transaction_groups';
|
||||
import { mergeProjection } from '../../projections/util/merge_projection';
|
||||
import { PromiseReturnType } from '../../../../observability/typings/common';
|
||||
import { AggregationOptionsByType } from '../../../typings/elasticsearch/aggregations';
|
||||
import { Transaction } from '../../../typings/es_schemas/ui/transaction';
|
||||
|
@ -45,7 +44,9 @@ export type Options = TopTransactionOptions | TopTraceOptions;
|
|||
|
||||
export type ESResponse = PromiseReturnType<typeof transactionGroupsFetcher>;
|
||||
|
||||
export type TransactionGroupRequestBase = ESSearchRequest & {
|
||||
export type TransactionGroupRequestBase = ReturnType<
|
||||
typeof getTransactionGroupsProjection
|
||||
> & {
|
||||
body: {
|
||||
aggs: {
|
||||
transaction_groups: Unionize<
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
import { mean } from 'lodash';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
HTTP_RESPONSE_STATUS_CODE,
|
||||
TRANSACTION_NAME,
|
||||
TRANSACTION_TYPE,
|
||||
|
@ -31,7 +30,7 @@ export async function getErrorRate({
|
|||
transactionName?: string;
|
||||
setup: Setup & SetupTimeRange & SetupUIFilters;
|
||||
}) {
|
||||
const { start, end, uiFiltersES, client, indices } = setup;
|
||||
const { start, end, uiFiltersES, apmEventClient } = setup;
|
||||
|
||||
const transactionNamefilter = transactionName
|
||||
? [{ term: { [TRANSACTION_NAME]: transactionName } }]
|
||||
|
@ -42,7 +41,6 @@ export async function getErrorRate({
|
|||
|
||||
const filter = [
|
||||
{ term: { [SERVICE_NAME]: serviceName } },
|
||||
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
{ exists: { field: HTTP_RESPONSE_STATUS_CODE } },
|
||||
...transactionNamefilter,
|
||||
|
@ -51,7 +49,9 @@ export async function getErrorRate({
|
|||
];
|
||||
|
||||
const params = {
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: { bool: { filter } },
|
||||
|
@ -68,7 +68,7 @@ export async function getErrorRate({
|
|||
},
|
||||
};
|
||||
|
||||
const resp = await client.search(params);
|
||||
const resp = await apmEventClient.search(params);
|
||||
|
||||
const noHits = resp.hits.total.value === 0;
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
import { merge } from 'lodash';
|
||||
import { arrayUnionToCallable } from '../../../common/utils/array_union_to_callable';
|
||||
import { Transaction } from '../../../typings/es_schemas/ui/transaction';
|
||||
import {
|
||||
TRANSACTION_SAMPLED,
|
||||
TRANSACTION_DURATION,
|
||||
|
@ -52,7 +51,7 @@ export async function getSamples({ request, setup }: MetricParams) {
|
|||
{ '@timestamp': { order: 'desc' as const } },
|
||||
];
|
||||
|
||||
const response = await setup.client.search({
|
||||
const response = await setup.apmEventClient.search({
|
||||
...params,
|
||||
body: {
|
||||
...params.body,
|
||||
|
@ -73,7 +72,7 @@ export async function getSamples({ request, setup }: MetricParams) {
|
|||
return {
|
||||
key: bucket.key as BucketKey,
|
||||
count: bucket.doc_count,
|
||||
sample: bucket.sample.hits.hits[0]._source as Transaction,
|
||||
sample: bucket.sample.hits.hits[0]._source,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -87,7 +86,7 @@ export async function getAverages({ request, setup }: MetricParams) {
|
|||
},
|
||||
});
|
||||
|
||||
const response = await setup.client.search(params);
|
||||
const response = await setup.apmEventClient.search(params);
|
||||
|
||||
return arrayUnionToCallable(
|
||||
response.aggregations?.transaction_groups.buckets ?? []
|
||||
|
@ -108,7 +107,7 @@ export async function getSums({ request, setup }: MetricParams) {
|
|||
},
|
||||
});
|
||||
|
||||
const response = await setup.client.search(params);
|
||||
const response = await setup.apmEventClient.search(params);
|
||||
|
||||
return arrayUnionToCallable(
|
||||
response.aggregations?.transaction_groups.buckets ?? []
|
||||
|
@ -131,7 +130,7 @@ export async function getPercentiles({ request, setup }: MetricParams) {
|
|||
},
|
||||
});
|
||||
|
||||
const response = await setup.client.search(params);
|
||||
const response = await setup.apmEventClient.search(params);
|
||||
|
||||
return arrayUnionToCallable(
|
||||
response.aggregations?.transaction_groups.buckets ?? []
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
|
||||
exports[`transaction queries fetches a transaction 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"transaction.id": "foo",
|
||||
|
@ -35,12 +35,16 @@ Object {
|
|||
},
|
||||
"size": 1,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`transaction queries fetches breakdown data for transactions 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"by_date": Object {
|
||||
|
@ -146,11 +150,6 @@ Object {
|
|||
"transaction.type": "bar",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -170,12 +169,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`transaction queries fetches breakdown data for transactions for a transaction name 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"by_date": Object {
|
||||
|
@ -281,11 +284,6 @@ Object {
|
|||
"transaction.type": "bar",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "metric",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -310,12 +308,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`transaction queries fetches transaction charts 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"overall_avg_duration": Object {
|
||||
|
@ -376,11 +378,6 @@ Object {
|
|||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"service.name": "foo",
|
||||
|
@ -405,12 +402,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`transaction queries fetches transaction charts for a transaction type 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"overall_avg_duration": Object {
|
||||
|
@ -471,11 +472,6 @@ Object {
|
|||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"service.name": "foo",
|
||||
|
@ -505,12 +501,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`transaction queries fetches transaction charts for a transaction type and transaction name 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"overall_avg_duration": Object {
|
||||
|
@ -571,11 +571,6 @@ Object {
|
|||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"service.name": "foo",
|
||||
|
@ -610,12 +605,16 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`transaction queries fetches transaction distribution 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"stats": Object {
|
||||
|
@ -632,11 +631,6 @@ Object {
|
|||
"service.name": "foo",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"transaction.type": "baz",
|
||||
|
@ -666,6 +660,5 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -15,7 +15,7 @@ describe('fetcher', () => {
|
|||
it('performs a search', async () => {
|
||||
const search = jest.fn();
|
||||
const setup = ({
|
||||
client: { search },
|
||||
apmEventClient: { search },
|
||||
indices: {},
|
||||
uiFiltersES: [],
|
||||
} as unknown) as Setup & SetupTimeRange & SetupUIFilters;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
import { ESFilter } from '../../../../typings/elasticsearch';
|
||||
import { PromiseReturnType } from '../../../../../observability/typings/common';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
TRANSACTION_TYPE,
|
||||
USER_AGENT_NAME,
|
||||
|
@ -23,7 +22,7 @@ import { ProcessorEvent } from '../../../../common/processor_event';
|
|||
export type ESResponse = PromiseReturnType<typeof fetcher>;
|
||||
|
||||
export function fetcher(options: Options) {
|
||||
const { end, client, indices, start, uiFiltersES } = options.setup;
|
||||
const { end, apmEventClient, start, uiFiltersES } = options.setup;
|
||||
const { serviceName, transactionName } = options;
|
||||
const { intervalString } = getBucketSize(start, end, 'auto');
|
||||
|
||||
|
@ -32,7 +31,6 @@ export function fetcher(options: Options) {
|
|||
: [];
|
||||
|
||||
const filter: ESFilter[] = [
|
||||
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
|
||||
{ term: { [SERVICE_NAME]: serviceName } },
|
||||
{ term: { [TRANSACTION_TYPE]: TRANSACTION_PAGE_LOAD } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
|
@ -41,7 +39,9 @@ export function fetcher(options: Options) {
|
|||
];
|
||||
|
||||
const params = {
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: { bool: { filter } },
|
||||
|
@ -80,5 +80,5 @@ export function fetcher(options: Options) {
|
|||
},
|
||||
};
|
||||
|
||||
return client.search(params);
|
||||
return apmEventClient.search(params);
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ProcessorEvent } from '../../../../common/processor_event';
|
||||
import {
|
||||
CLIENT_GEO_COUNTRY_ISO_CODE,
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
TRANSACTION_DURATION,
|
||||
TRANSACTION_TYPE,
|
||||
|
@ -29,12 +29,14 @@ export async function getTransactionAvgDurationByCountry({
|
|||
serviceName: string;
|
||||
transactionName?: string;
|
||||
}) {
|
||||
const { uiFiltersES, client, start, end, indices } = setup;
|
||||
const { uiFiltersES, apmEventClient, start, end } = setup;
|
||||
const transactionNameFilter = transactionName
|
||||
? [{ term: { [TRANSACTION_NAME]: transactionName } }]
|
||||
: [];
|
||||
const params = {
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
|
@ -42,7 +44,6 @@ export async function getTransactionAvgDurationByCountry({
|
|||
filter: [
|
||||
{ term: { [SERVICE_NAME]: serviceName } },
|
||||
...transactionNameFilter,
|
||||
{ term: { [PROCESSOR_EVENT]: 'transaction' } },
|
||||
{ term: { [TRANSACTION_TYPE]: TRANSACTION_PAGE_LOAD } },
|
||||
{ exists: { field: CLIENT_GEO_COUNTRY_ISO_CODE } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
|
@ -66,7 +67,7 @@ export async function getTransactionAvgDurationByCountry({
|
|||
},
|
||||
};
|
||||
|
||||
const resp = await client.search(params);
|
||||
const resp = await apmEventClient.search(params);
|
||||
|
||||
if (!resp.aggregations) {
|
||||
return [];
|
||||
|
|
|
@ -26,7 +26,7 @@ function getMockSetup(esResponse: any) {
|
|||
return {
|
||||
start: 0,
|
||||
end: 500000,
|
||||
client: { search: clientSpy } as any,
|
||||
apmEventClient: { search: clientSpy } as any,
|
||||
internalClient: { search: clientSpy } as any,
|
||||
config: new Proxy(
|
||||
{},
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { flatten, orderBy, last } from 'lodash';
|
||||
import { ProcessorEvent } from '../../../../common/processor_event';
|
||||
import {
|
||||
SERVICE_NAME,
|
||||
SPAN_SUBTYPE,
|
||||
|
@ -13,7 +14,6 @@ import {
|
|||
TRANSACTION_TYPE,
|
||||
TRANSACTION_NAME,
|
||||
TRANSACTION_BREAKDOWN_COUNT,
|
||||
PROCESSOR_EVENT,
|
||||
} from '../../../../common/elasticsearch_fieldnames';
|
||||
import {
|
||||
Setup,
|
||||
|
@ -36,7 +36,7 @@ export async function getTransactionBreakdown({
|
|||
transactionName?: string;
|
||||
transactionType: string;
|
||||
}) {
|
||||
const { uiFiltersES, client, start, end, indices } = setup;
|
||||
const { uiFiltersES, apmEventClient, start, end } = setup;
|
||||
|
||||
const subAggs = {
|
||||
sum_all_self_times: {
|
||||
|
@ -82,7 +82,6 @@ export async function getTransactionBreakdown({
|
|||
const filters = [
|
||||
{ term: { [SERVICE_NAME]: serviceName } },
|
||||
{ term: { [TRANSACTION_TYPE]: transactionType } },
|
||||
{ term: { [PROCESSOR_EVENT]: 'metric' } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
...uiFiltersES,
|
||||
];
|
||||
|
@ -92,7 +91,9 @@ export async function getTransactionBreakdown({
|
|||
}
|
||||
|
||||
const params = {
|
||||
index: indices['apm_oss.metricsIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.metric],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
|
@ -110,7 +111,7 @@ export async function getTransactionBreakdown({
|
|||
},
|
||||
};
|
||||
|
||||
const resp = await client.search(params);
|
||||
const resp = await apmEventClient.search(params);
|
||||
|
||||
const formatBucket = (
|
||||
aggs:
|
||||
|
|
|
@ -4,6 +4,11 @@ exports[`timeseriesFetcher should call client with correct query 1`] = `
|
|||
Array [
|
||||
Array [
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"overall_avg_duration": Object {
|
||||
|
@ -64,11 +69,6 @@ Array [
|
|||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"term": Object {
|
||||
"processor.event": "transaction",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"term": Object {
|
||||
"service.name": "myServiceName",
|
||||
|
@ -98,7 +98,6 @@ Array [
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": "myIndex",
|
||||
},
|
||||
],
|
||||
]
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { PROCESSOR_EVENT } from '../../../../../common/elasticsearch_fieldnames';
|
||||
import { ESResponse, timeseriesFetcher } from './fetcher';
|
||||
import { APMConfig } from '../../../../../server';
|
||||
import { ProcessorEvent } from '../../../../../common/processor_event';
|
||||
|
||||
describe('timeseriesFetcher', () => {
|
||||
let res: ESResponse;
|
||||
|
@ -21,7 +21,7 @@ describe('timeseriesFetcher', () => {
|
|||
setup: {
|
||||
start: 1528113600000,
|
||||
end: 1528977600000,
|
||||
client: { search: clientSpy } as any,
|
||||
apmEventClient: { search: clientSpy } as any,
|
||||
internalClient: { search: clientSpy } as any,
|
||||
config: new Proxy(
|
||||
{},
|
||||
|
@ -54,15 +54,7 @@ describe('timeseriesFetcher', () => {
|
|||
|
||||
it('should restrict results to only transaction documents', () => {
|
||||
const query = clientSpy.mock.calls[0][0];
|
||||
expect(query.body.query.bool.filter).toEqual(
|
||||
expect.arrayContaining([
|
||||
{
|
||||
term: {
|
||||
[PROCESSOR_EVENT]: 'transaction',
|
||||
},
|
||||
} as any,
|
||||
])
|
||||
);
|
||||
expect(query.apm.events).toEqual([ProcessorEvent.transaction]);
|
||||
});
|
||||
|
||||
it('should return correct response', () => {
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ProcessorEvent } from '../../../../../common/processor_event';
|
||||
import { ESFilter } from '../../../../../typings/elasticsearch';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
TRANSACTION_DURATION,
|
||||
TRANSACTION_NAME,
|
||||
|
@ -34,11 +34,10 @@ export function timeseriesFetcher({
|
|||
transactionName: string | undefined;
|
||||
setup: Setup & SetupTimeRange & SetupUIFilters;
|
||||
}) {
|
||||
const { start, end, uiFiltersES, client, indices } = setup;
|
||||
const { start, end, uiFiltersES, apmEventClient } = setup;
|
||||
const { intervalString } = getBucketSize(start, end, 'auto');
|
||||
|
||||
const filter: ESFilter[] = [
|
||||
{ term: { [PROCESSOR_EVENT]: 'transaction' } },
|
||||
{ term: { [SERVICE_NAME]: serviceName } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
...uiFiltersES,
|
||||
|
@ -54,7 +53,9 @@ export function timeseriesFetcher({
|
|||
}
|
||||
|
||||
const params = {
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction as const],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: { bool: { filter } },
|
||||
|
@ -95,5 +96,5 @@ export function timeseriesFetcher({
|
|||
},
|
||||
};
|
||||
|
||||
return client.search(params);
|
||||
return apmEventClient.search(params);
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Transaction } from '../../../../../typings/es_schemas/ui/transaction';
|
||||
import { ProcessorEvent } from '../../../../../common/processor_event';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
TRACE_ID,
|
||||
TRANSACTION_DURATION,
|
||||
|
@ -32,17 +31,18 @@ export async function bucketFetcher(
|
|||
bucketSize: number,
|
||||
setup: Setup & SetupTimeRange & SetupUIFilters
|
||||
) {
|
||||
const { start, end, uiFiltersES, client, indices } = setup;
|
||||
const { start, end, uiFiltersES, apmEventClient } = setup;
|
||||
|
||||
const params = {
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction as const],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ term: { [SERVICE_NAME]: serviceName } },
|
||||
{ term: { [PROCESSOR_EVENT]: 'transaction' } },
|
||||
{ term: { [TRANSACTION_TYPE]: transactionType } },
|
||||
{ term: { [TRANSACTION_NAME]: transactionName } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
|
@ -85,7 +85,7 @@ export async function bucketFetcher(
|
|||
},
|
||||
};
|
||||
|
||||
const response = await client.search<Transaction, typeof params>(params);
|
||||
const response = await apmEventClient.search(params);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ProcessorEvent } from '../../../../common/processor_event';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
TRANSACTION_DURATION,
|
||||
TRANSACTION_NAME,
|
||||
|
@ -23,17 +23,18 @@ export async function getDistributionMax(
|
|||
transactionType: string,
|
||||
setup: Setup & SetupTimeRange & SetupUIFilters
|
||||
) {
|
||||
const { start, end, uiFiltersES, client, indices } = setup;
|
||||
const { start, end, uiFiltersES, apmEventClient } = setup;
|
||||
|
||||
const params = {
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ term: { [SERVICE_NAME]: serviceName } },
|
||||
{ term: { [PROCESSOR_EVENT]: 'transaction' } },
|
||||
{ term: { [TRANSACTION_TYPE]: transactionType } },
|
||||
{ term: { [TRANSACTION_NAME]: transactionName } },
|
||||
{
|
||||
|
@ -59,6 +60,6 @@ export async function getDistributionMax(
|
|||
},
|
||||
};
|
||||
|
||||
const resp = await client.search(params);
|
||||
const resp = await apmEventClient.search(params);
|
||||
return resp.aggregations ? resp.aggregations.stats.max : null;
|
||||
}
|
||||
|
|
|
@ -5,11 +5,9 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
TRACE_ID,
|
||||
TRANSACTION_ID,
|
||||
} from '../../../../common/elasticsearch_fieldnames';
|
||||
import { Transaction } from '../../../../typings/es_schemas/ui/transaction';
|
||||
import { rangeFilter } from '../../../../common/utils/range_filter';
|
||||
import {
|
||||
Setup,
|
||||
|
@ -27,16 +25,17 @@ export async function getTransaction({
|
|||
traceId: string;
|
||||
setup: Setup & SetupTimeRange & SetupUIFilters;
|
||||
}) {
|
||||
const { start, end, client, indices } = setup;
|
||||
const { start, end, apmEventClient } = setup;
|
||||
|
||||
const params = {
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
const resp = await apmEventClient.search({
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
body: {
|
||||
size: 1,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
|
||||
{ term: { [TRANSACTION_ID]: transactionId } },
|
||||
{ term: { [TRACE_ID]: traceId } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
|
@ -44,8 +43,7 @@ export async function getTransaction({
|
|||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const resp = await client.search<Transaction>(params);
|
||||
return resp.hits.hits[0]?._source;
|
||||
}
|
||||
|
|
|
@ -5,11 +5,9 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
TRACE_ID,
|
||||
PARENT_ID,
|
||||
} from '../../../../common/elasticsearch_fieldnames';
|
||||
import { Transaction } from '../../../../typings/es_schemas/ui/transaction';
|
||||
import { Setup } from '../../helpers/setup_request';
|
||||
import { ProcessorEvent } from '../../../../common/processor_event';
|
||||
|
||||
|
@ -17,9 +15,12 @@ export async function getRootTransactionByTraceId(
|
|||
traceId: string,
|
||||
setup: Setup
|
||||
) {
|
||||
const { client, indices } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const params = {
|
||||
index: indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction as const],
|
||||
},
|
||||
body: {
|
||||
size: 1,
|
||||
query: {
|
||||
|
@ -35,16 +36,13 @@ export async function getRootTransactionByTraceId(
|
|||
},
|
||||
},
|
||||
],
|
||||
filter: [
|
||||
{ term: { [TRACE_ID]: traceId } },
|
||||
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
|
||||
],
|
||||
filter: [{ term: { [TRACE_ID]: traceId } }],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const resp = await client.search<Transaction>(params);
|
||||
const resp = await apmEventClient.search(params);
|
||||
return {
|
||||
transaction: resp.hits.hits[0]?._source,
|
||||
};
|
||||
|
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
exports[`ui filter queries fetches environments 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
"metric",
|
||||
"error",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"environments": Object {
|
||||
|
@ -14,15 +21,6 @@ Object {
|
|||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"terms": Object {
|
||||
"processor.event": Array [
|
||||
"transaction",
|
||||
"error",
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -42,16 +40,18 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": Array [
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`ui filter queries fetches environments without a service name 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
"metric",
|
||||
"error",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"environments": Object {
|
||||
|
@ -64,15 +64,6 @@ Object {
|
|||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"terms": Object {
|
||||
"processor.event": Array [
|
||||
"transaction",
|
||||
"error",
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -87,10 +78,5 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": Array [
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ProcessorEvent } from '../../../common/processor_event';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_ENVIRONMENT,
|
||||
SERVICE_NAME,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
|
@ -18,12 +18,9 @@ export async function getEnvironments(
|
|||
setup: Setup & SetupTimeRange,
|
||||
serviceName?: string
|
||||
) {
|
||||
const { start, end, client, indices } = setup;
|
||||
const { start, end, apmEventClient } = setup;
|
||||
|
||||
const filter: ESFilter[] = [
|
||||
{ terms: { [PROCESSOR_EVENT]: ['transaction', 'error', 'metric'] } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
];
|
||||
const filter: ESFilter[] = [{ range: rangeFilter(start, end) }];
|
||||
|
||||
if (serviceName) {
|
||||
filter.push({
|
||||
|
@ -32,11 +29,13 @@ export async function getEnvironments(
|
|||
}
|
||||
|
||||
const params = {
|
||||
index: [
|
||||
indices['apm_oss.metricsIndices'],
|
||||
indices['apm_oss.errorIndices'],
|
||||
indices['apm_oss.transactionIndices'],
|
||||
apm: {
|
||||
events: [
|
||||
ProcessorEvent.transaction,
|
||||
ProcessorEvent.metric,
|
||||
ProcessorEvent.error,
|
||||
],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
|
@ -55,7 +54,7 @@ export async function getEnvironments(
|
|||
},
|
||||
};
|
||||
|
||||
const resp = await client.search(params);
|
||||
const resp = await apmEventClient.search(params);
|
||||
const aggs = resp.aggregations;
|
||||
const environmentsBuckets = aggs?.environments.buckets || [];
|
||||
|
||||
|
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
exports[`local ui filter queries fetches local ui filter aggregations 1`] = `
|
||||
Object {
|
||||
"apm": Object {
|
||||
"events": Array [
|
||||
"transaction",
|
||||
"metric",
|
||||
"error",
|
||||
],
|
||||
},
|
||||
"body": Object {
|
||||
"aggs": Object {
|
||||
"by_terms": Object {
|
||||
|
@ -28,15 +35,6 @@ Object {
|
|||
"query": Object {
|
||||
"bool": Object {
|
||||
"filter": Array [
|
||||
Object {
|
||||
"terms": Object {
|
||||
"processor.event": Array [
|
||||
"transaction",
|
||||
"error",
|
||||
"metric",
|
||||
],
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"range": Object {
|
||||
"@timestamp": Object {
|
||||
|
@ -56,10 +54,5 @@ Object {
|
|||
},
|
||||
"size": 0,
|
||||
},
|
||||
"index": Array [
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
"myIndex",
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
*/
|
||||
|
||||
import { omit } from 'lodash';
|
||||
import { mergeProjection } from '../../../../common/projections/util/merge_projection';
|
||||
import { Projection } from '../../../../common/projections/typings';
|
||||
import { mergeProjection } from '../../../projections/util/merge_projection';
|
||||
import { Projection } from '../../../projections/typings';
|
||||
import { UIFilters } from '../../../../typings/ui_filters';
|
||||
import { getUiFiltersES } from '../../helpers/convert_ui_filters/get_ui_filters_es';
|
||||
import { localUIFilters, LocalUIFilterName } from './config';
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
import { cloneDeep, orderBy } from 'lodash';
|
||||
import { UIFilters } from '../../../../typings/ui_filters';
|
||||
import { Projection } from '../../../../common/projections/typings';
|
||||
import { Projection } from '../../../projections/typings';
|
||||
import { PromiseReturnType } from '../../../../../observability/typings/common';
|
||||
import { getLocalFilterQuery } from './get_local_filter_query';
|
||||
import { Setup } from '../../helpers/setup_request';
|
||||
|
@ -26,7 +26,7 @@ export async function getLocalUIFilters({
|
|||
uiFilters: UIFilters;
|
||||
localFilterNames: LocalUIFilterName[];
|
||||
}) {
|
||||
const { client } = setup;
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const projectionWithoutAggs = cloneDeep(projection);
|
||||
|
||||
|
@ -40,7 +40,7 @@ export async function getLocalUIFilters({
|
|||
localUIFilterName: name,
|
||||
});
|
||||
|
||||
const response = await client.search(query);
|
||||
const response = await apmEventClient.search(query);
|
||||
|
||||
const filter = localUIFilters[name];
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
SearchParamsMock,
|
||||
inspectSearchParams,
|
||||
} from '../../../../public/utils/testHelpers';
|
||||
import { getServicesProjection } from '../../../../common/projections/services';
|
||||
import { getServicesProjection } from '../../../projections/services';
|
||||
|
||||
describe('local ui filter queries', () => {
|
||||
let mock: SearchParamsMock;
|
||||
|
|
|
@ -8,15 +8,13 @@ import {
|
|||
Setup,
|
||||
SetupTimeRange,
|
||||
SetupUIFilters,
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
} from '../../server/lib/helpers/setup_request';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_NAME,
|
||||
ERROR_GROUP_ID,
|
||||
} from '../elasticsearch_fieldnames';
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { rangeFilter } from '../utils/range_filter';
|
||||
} from '../../common/elasticsearch_fieldnames';
|
||||
import { rangeFilter } from '../../common/utils/range_filter';
|
||||
import { ProcessorEvent } from '../../common/processor_event';
|
||||
|
||||
export function getErrorGroupsProjection({
|
||||
setup,
|
||||
|
@ -25,16 +23,17 @@ export function getErrorGroupsProjection({
|
|||
setup: Setup & SetupTimeRange & SetupUIFilters;
|
||||
serviceName: string;
|
||||
}) {
|
||||
const { start, end, uiFiltersES, indices } = setup;
|
||||
const { start, end, uiFiltersES } = setup;
|
||||
|
||||
return {
|
||||
index: indices['apm_oss.errorIndices'],
|
||||
apm: {
|
||||
events: [ProcessorEvent.error as const],
|
||||
},
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ term: { [SERVICE_NAME]: serviceName } },
|
||||
{ term: { [PROCESSOR_EVENT]: 'error' } },
|
||||
{ range: rangeFilter(start, end) },
|
||||
...uiFiltersES,
|
||||
],
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue