[APM] Add data access plugin (#162367)

Closes https://github.com/elastic/kibana/issues/161906
Related to:
https://github.com/elastic/observability-dev/discussions/2787
(_internal_)

This add a new plugin `apm_data_access` that contains the APM query
targets (indices to query for APM data).
This plugin can be consumed by apm and any other plugin, making it
possible for other plugins to know about the configured APM query
targets.



## Example:

APM query targets can be specified in kibana[.dev].yml using
`xpack.apm.indices.{dataset}: some-index-*` for instances:

```yml
xpack.apm.indices.transaction: apm-*
```

See all config options on:
https://www.elastic.co/guide/en/kibana/current/apm-settings-kb.html#general-apm-settings-kb

Query targets can also be specified via the UI (and persisted in a saved
object) via the settings page: `/app/apm/settings/apm-indices`

**Retrieving the query targets**
Query targets can be retrieved from other plugins via `getApmIndices`:
```ts
const apmIndices = await plugins.apmDataAccess.setup.getApmIndices(savedObjects.client); 
```

TODO:

- [x] Add SO client and fetch space aware index config (see
4d7f626da0/x-pack/plugins/apm/server/routes/settings/apm_indices/get_apm_indices.ts (L32-L44))
- [ ] Add simple APM client for querying apm data

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Søren Louv-Jansen 2023-08-22 11:19:09 +02:00 committed by GitHub
parent 90c1a4a95c
commit 7df1cee163
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
112 changed files with 755 additions and 582 deletions

1
.github/CODEOWNERS vendored
View file

@ -36,6 +36,7 @@ packages/analytics/shippers/elastic_v3/server @elastic/kibana-core
packages/analytics/shippers/fullstory @elastic/kibana-core
packages/analytics/shippers/gainsight @elastic/kibana-core
packages/kbn-apm-config-loader @elastic/kibana-core @vigneshshanmugam
x-pack/plugins/apm_data_access @elastic/apm-ui
x-pack/plugins/apm @elastic/apm-ui
packages/kbn-apm-synthtrace @elastic/apm-ui
packages/kbn-apm-synthtrace-client @elastic/apm-ui

View file

@ -434,6 +434,10 @@ The plugin exposes the static DefaultEditorController class to consume.
|This plugin provides access to App Monitoring features provided by Elastic. It allows you to monitor your software services and applications in real-time; visualize detailed performance information on your services, identify and analyze errors, and monitor host-level and APM agent-specific metrics like JVM and Go runtime metrics.
|{kib-repo}blob/{branch}/x-pack/plugins/apm_data_access[apmDataAccess]
|WARNING: Missing README.
|{kib-repo}blob/{branch}/x-pack/plugins/asset_manager/README.md[assetManager]
|This plugin provides access to the asset data stored in assets-* indices, primarily
for inventory and topology purposes.

View file

@ -152,6 +152,7 @@
"@kbn/analytics-shippers-fullstory": "link:packages/analytics/shippers/fullstory",
"@kbn/analytics-shippers-gainsight": "link:packages/analytics/shippers/gainsight",
"@kbn/apm-config-loader": "link:packages/kbn-apm-config-loader",
"@kbn/apm-data-access-plugin": "link:x-pack/plugins/apm_data_access",
"@kbn/apm-plugin": "link:x-pack/plugins/apm",
"@kbn/apm-utils": "link:packages/kbn-apm-utils",
"@kbn/app-link-test-plugin": "link:test/plugin_functional/plugins/app_link_test",

View file

@ -66,6 +66,8 @@
"@kbn/analytics-shippers-gainsight/*": ["packages/analytics/shippers/gainsight/*"],
"@kbn/apm-config-loader": ["packages/kbn-apm-config-loader"],
"@kbn/apm-config-loader/*": ["packages/kbn-apm-config-loader/*"],
"@kbn/apm-data-access-plugin": ["x-pack/plugins/apm_data_access"],
"@kbn/apm-data-access-plugin/*": ["x-pack/plugins/apm_data_access/*"],
"@kbn/apm-plugin": ["x-pack/plugins/apm"],
"@kbn/apm-plugin/*": ["x-pack/plugins/apm/*"],
"@kbn/apm-synthtrace": ["packages/kbn-apm-synthtrace"],

View file

@ -8,6 +8,7 @@
"xpack.stackAlerts": "plugins/stack_alerts",
"xpack.stackConnectors": "plugins/stack_connectors",
"xpack.apm": "plugins/apm",
"xpack.apmDataAccess": "plugins/apm_data_access",
"xpack.banners": "plugins/banners",
"xpack.canvas": "plugins/canvas",
"xpack.cases": "plugins/cases",

View file

@ -5,13 +5,6 @@
* 2.0.
*/
// the types have to match the names of the saved object mappings
// in /x-pack/plugins/apm/mappings.json
// APM index settings
export const APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE = 'apm-indices';
export const APM_INDEX_SETTINGS_SAVED_OBJECT_ID = 'apm-indices';
// APM telemetry
export const APM_TELEMETRY_SAVED_OBJECT_TYPE = 'apm-telemetry';
export const APM_TELEMETRY_SAVED_OBJECT_ID = 'apm-telemetry';

View file

@ -9,6 +9,7 @@
"browser": true,
"configPath": ["xpack", "apm"],
"requiredPlugins": [
"apmDataAccess",
"data",
"dashboard",
"controls",

View file

@ -10,9 +10,9 @@
import { Client } from '@elastic/elasticsearch';
import fs from 'fs/promises';
import axios, { AxiosInstance } from 'axios';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { APIReturnType } from '../../public/services/rest/create_call_apm_api';
import { getDiagnosticsBundle } from '../../server/routes/diagnostics/get_diagnostics_bundle';
import { ApmIndicesConfig } from '../../server/routes/settings/apm_indices/get_apm_indices';
type DiagnosticsBundle = APIReturnType<'GET /internal/apm/diagnostics'>;
@ -100,7 +100,7 @@ async function getApmIndices(kibanaClient: AxiosInstance) {
savedValue ?? defaultValue,
]
)
) as ApmIndicesConfig;
) as APMIndices;
}
async function getFleetPackageInfo(kibanaClient: AxiosInstance) {

View file

@ -10,8 +10,8 @@ import { kibanaPackageJson } from '@kbn/repo-info';
import { GetDeprecationsContext } from '@kbn/core/server';
import { CloudSetup } from '@kbn/cloud-plugin/server';
import { getDeprecations } from '.';
import { APMRouteHandlerResources } from '..';
import { AgentPolicy } from '@kbn/fleet-plugin/common';
import { APMRouteHandlerResources } from '../routes/apm_routes/register_apm_server_routes';
const deprecationContext = {
esClient: {},

View file

@ -13,7 +13,7 @@ import {
getCloudAgentPolicy,
getApmPackagePolicy,
} from '../routes/fleet/get_cloud_apm_package_policy';
import { APMRouteHandlerResources } from '..';
import { APMRouteHandlerResources } from '../routes/apm_routes/register_apm_server_routes';
export function getDeprecations({
cloudSetup,

View file

@ -12,11 +12,11 @@ import {
LicensingPluginSetup,
LicensingApiRequestHandlerContext,
} from '@kbn/licensing-plugin/server';
import { APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE } from '@kbn/apm-data-access-plugin/server/saved_objects/apm_indices';
import {
ApmRuleType,
APM_SERVER_FEATURE_ID,
} from '../common/rules/apm_rule_types';
import { APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE } from '../common/apm_saved_object_constants';
export const APM_FEATURE = {
id: APM_SERVER_FEATURE_ID,

View file

@ -56,13 +56,6 @@ const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: false }),
}),
}),
indices: schema.object({
transaction: schema.string({ defaultValue: 'traces-apm*,apm-*' }),
span: schema.string({ defaultValue: 'traces-apm*,apm-*' }),
error: schema.string({ defaultValue: 'logs-apm*,apm-*' }),
metric: schema.string({ defaultValue: 'metrics-apm*,apm-*' }),
onboarding: schema.string({ defaultValue: 'apm-*' }),
}),
forceSyntheticSource: schema.boolean({ defaultValue: false }),
latestAgentVersionsUrl: schema.string({
defaultValue: 'https://apm-agent-versions.elastic.co/versions.json',
@ -109,35 +102,12 @@ export const config: PluginConfigDescriptor<APMConfig> = {
deprecateFromRoot,
unusedFromRoot,
}) => [
unused('indices.sourcemap', { level: 'warning' }),
unused('ui.transactionGroupBucketSize', {
level: 'warning',
}),
rename('autocreateApmIndexPattern', 'autoCreateApmDataView', {
level: 'warning',
}),
renameFromRoot(
'apm_oss.transactionIndices',
'xpack.apm.indices.transaction',
{ level: 'warning' }
),
renameFromRoot('apm_oss.spanIndices', 'xpack.apm.indices.span', {
level: 'warning',
}),
renameFromRoot('apm_oss.errorIndices', 'xpack.apm.indices.error', {
level: 'warning',
}),
renameFromRoot('apm_oss.metricsIndices', 'xpack.apm.indices.metric', {
level: 'warning',
}),
renameFromRoot('apm_oss.sourcemapIndices', 'xpack.apm.indices.sourcemap', {
level: 'warning',
}),
renameFromRoot(
'apm_oss.onboardingIndices',
'xpack.apm.indices.onboarding',
{ level: 'warning' }
),
deprecateFromRoot('apm_oss.enabled', '8.0.0', { level: 'warning' }),
unusedFromRoot('apm_oss.fleetMode', { level: 'warning' }),
unusedFromRoot('apm_oss.indexPattern', { level: 'warning' }),
@ -165,7 +135,6 @@ export const config: PluginConfigDescriptor<APMConfig> = {
};
export type APMConfig = TypeOf<typeof configSchema>;
export type ApmIndicesConfigName = keyof APMConfig['indices'];
export const plugin = (initContext: PluginInitializerContext) =>
new APMPlugin(initContext);
@ -177,4 +146,3 @@ export type {
APMServerRouteRepository,
APIEndpoint,
} from './routes/apm_routes/get_global_apm_server_route_repository';
export type { APMRouteHandlerResources } from './routes/typings';

View file

@ -12,6 +12,7 @@ import moment from 'moment';
import { v4 as uuidv4 } from 'uuid';
import { ProcessorEvent } from '@kbn/observability-plugin/common';
import { waitForIndexStatus } from '@kbn/core-saved-objects-migration-server-internal';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { ML_ERRORS } from '../../../common/anomaly_detection';
import { METRICSET_NAME, PROCESSOR_EVENT } from '../../../common/es_fields/apm';
import { Environment } from '../../../common/environment_rt';
@ -20,7 +21,6 @@ import { withApmSpan } from '../../utils/with_apm_span';
import { MlClient } from '../helpers/get_ml_client';
import { APM_ML_JOB_GROUP, ML_MODULE_ID_APM_TRANSACTION } from './constants';
import { getAnomalyDetectionJobs } from './get_anomaly_detection_jobs';
import { ApmIndicesConfig } from '../../routes/settings/apm_indices/get_apm_indices';
const DEFAULT_TIMEOUT = '60s';
@ -33,7 +33,7 @@ export async function createAnomalyDetectionJobs({
}: {
mlClient?: MlClient;
esClient: ElasticsearchClient;
indices: ApmIndicesConfig;
indices: APMIndices;
environments: Environment[];
logger: Logger;
}) {

View file

@ -6,7 +6,7 @@
*/
import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks';
import { ApmIndicesConfig } from '../../../routes/settings/apm_indices/get_apm_indices';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { tasks } from './tasks';
import {
SERVICE_NAME,
@ -19,7 +19,7 @@ describe('data telemetry collection tasks', () => {
metric: 'apm-8.0.0-metric',
span: 'apm-8.0.0-span',
transaction: 'apm-8.0.0-transaction',
} as ApmIndicesConfig;
} as APMIndices;
describe('environments', () => {
const task = tasks.find((t) => t.name === 'environments');

View file

@ -10,6 +10,7 @@ import { ProcessorEvent } from '@kbn/observability-plugin/common';
import { createHash } from 'crypto';
import { flatten, merge, pickBy, sortBy, sum, uniq } from 'lodash';
import { SavedObjectsClient } from '@kbn/core/server';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { AGENT_NAMES, RUM_AGENT_NAMES } from '../../../../common/agent_name';
import {
AGENT_ACTIVATION_METHOD,
@ -56,10 +57,7 @@ import { AgentName } from '../../../../typings/es_schemas/ui/fields/agent';
import { Span } from '../../../../typings/es_schemas/ui/span';
import { Transaction } from '../../../../typings/es_schemas/ui/transaction';
import { APMTelemetry, APMPerService, APMDataTelemetry } from '../types';
import {
ApmIndicesConfig,
APM_AGENT_CONFIGURATION_INDEX,
} from '../../../routes/settings/apm_indices/get_apm_indices';
import { APM_AGENT_CONFIGURATION_INDEX } from '../../../routes/settings/apm_indices/apm_system_index_constants';
import { TelemetryClient } from '../telemetry_client';
type ISavedObjectsClient = Pick<SavedObjectsClient, 'find'>;
@ -76,7 +74,7 @@ interface TelemetryTask {
export interface TelemetryTaskExecutorParams {
telemetryClient: TelemetryClient;
indices: ApmIndicesConfig;
indices: APMIndices;
savedObjectsClient: ISavedObjectsClient;
}

View file

@ -6,12 +6,17 @@
*/
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server';
import { CoreSetup, Logger, SavedObjectsErrorHelpers } from '@kbn/core/server';
import {
CoreSetup,
Logger,
SavedObjectsClientContract,
SavedObjectsErrorHelpers,
} from '@kbn/core/server';
import {
TaskManagerSetupContract,
TaskManagerStartContract,
} from '@kbn/task-manager-plugin/server';
import { APMConfig } from '../..';
import { APMDataAccessConfig } from '@kbn/apm-data-access-plugin/server';
import {
APM_TELEMETRY_SAVED_OBJECT_ID,
APM_TELEMETRY_SAVED_OBJECT_TYPE,
@ -20,14 +25,13 @@ import { getInternalSavedObjectsClient } from '../helpers/get_internal_saved_obj
import { collectDataTelemetry } from './collect_data_telemetry';
import { APMUsage } from './types';
import { apmSchema } from './schema';
import { getApmIndices } from '../../routes/settings/apm_indices/get_apm_indices';
import { getTelemetryClient } from './telemetry_client';
export const APM_TELEMETRY_TASK_NAME = 'apm-telemetry-task';
export async function createApmTelemetry({
core,
config,
getApmIndices,
usageCollector,
taskManager,
logger,
@ -35,7 +39,9 @@ export async function createApmTelemetry({
isProd,
}: {
core: CoreSetup;
config: APMConfig;
getApmIndices: (
soClient: SavedObjectsClientContract
) => Promise<APMDataAccessConfig['indices']>;
usageCollector: UsageCollectionSetup;
taskManager: TaskManagerSetupContract;
logger: Logger;
@ -56,14 +62,14 @@ export async function createApmTelemetry({
},
});
const telemetryClient = await getTelemetryClient({ core });
const [coreStart] = await core.getStartServices();
const savedObjectsClient = await getInternalSavedObjectsClient(coreStart);
const indices = await getApmIndices({ config, savedObjectsClient });
const telemetryClient = await getTelemetryClient({ core });
const apmIndices = await getApmIndices(savedObjectsClient);
const collectAndStore = async () => {
const dataTelemetry = await collectDataTelemetry({
indices,
indices: apmIndices,
telemetryClient,
logger,
savedObjectsClient,

View file

@ -6,7 +6,7 @@
*/
import { APMEventESSearchRequest } from '.';
import { ApmIndicesConfig } from '../../../../routes/settings/apm_indices/get_apm_indices';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { getRequestBase } from './get_request_base';
describe('getRequestBase', () => {
@ -26,7 +26,7 @@ describe('getRequestBase', () => {
error: 'my-apm-*-error-*',
span: 'my-apm-*-span-*',
onboarding: 'my-apm-*-onboarding-*',
} as ApmIndicesConfig;
} as APMIndices;
res = getRequestBase({ ...request, indices });
});

View file

@ -6,12 +6,12 @@
*/
import type { ESFilter } from '@kbn/es-types';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { ProcessorEvent } from '@kbn/observability-plugin/common';
import { uniq } from 'lodash';
import { ApmDataSource } from '../../../../../common/data_source';
import {} from '../../../../../common/document_type';
import { PROCESSOR_EVENT } from '../../../../../common/es_fields/apm';
import { ApmIndicesConfig } from '../../../../routes/settings/apm_indices/get_apm_indices';
import {
getConfigForDocumentType,
getProcessorEventForDocumentType,
@ -26,7 +26,7 @@ const processorEventIndexMap = {
export function processorEventsToIndex(
events: ProcessorEvent[],
indices: ApmIndicesConfig
indices: APMIndices
) {
return uniq(
events.flatMap((event) =>
@ -37,7 +37,7 @@ export function processorEventsToIndex(
export function getRequestBase(options: {
apm: { events: ProcessorEvent[] } | { sources: ApmDataSource[] };
indices: ApmIndicesConfig;
indices: APMIndices;
}) {
const events =
'events' in options.apm

View file

@ -20,12 +20,12 @@ import { ProcessorEvent } from '@kbn/observability-plugin/common';
import { unwrapEsResponse } from '@kbn/observability-plugin/server';
import { compact, omit } from 'lodash';
import { ValuesType } from 'utility-types';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { ApmDataSource } from '../../../../../common/data_source';
import { APMError } from '../../../../../typings/es_schemas/ui/apm_error';
import { Metric } from '../../../../../typings/es_schemas/ui/metric';
import { Span } from '../../../../../typings/es_schemas/ui/span';
import { Transaction } from '../../../../../typings/es_schemas/ui/transaction';
import { ApmIndicesConfig } from '../../../../routes/settings/apm_indices/get_apm_indices';
import { withApmSpan } from '../../../../utils/with_apm_span';
import {
callAsyncWithDebug,
@ -87,7 +87,7 @@ export interface APMEventClientConfig {
esClient: ElasticsearchClient;
debug: boolean;
request: KibanaRequest;
indices: ApmIndicesConfig;
indices: APMIndices;
options: {
includeFrozen: boolean;
forceSyntheticSource: boolean;
@ -98,7 +98,7 @@ export class APMEventClient {
private readonly esClient: ElasticsearchClient;
private readonly debug: boolean;
private readonly request: KibanaRequest;
public readonly indices: ApmIndicesConfig;
public readonly indices: APMIndices;
private readonly includeFrozen: boolean;
private readonly forceSyntheticSource: boolean;

View file

@ -6,7 +6,7 @@
*/
import { ESSearchRequest, InferSearchResponseOf } from '@kbn/es-types';
import { APMRouteHandlerResources } from '../../../../routes/typings';
import { APMRouteHandlerResources } from '../../../../routes/apm_routes/register_apm_server_routes';
import { getInfraMetricIndices } from '../../get_infra_metric_indices';
type InfraMetricsSearchParams = Omit<ESSearchRequest, 'index'> & {

View file

@ -8,17 +8,15 @@
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { unwrapEsResponse } from '@kbn/observability-plugin/server';
import type { ESSearchResponse, ESSearchRequest } from '@kbn/es-types';
import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { APMConfig } from '../../../..';
import { APMRouteHandlerResources } from '../../../../routes/typings';
import { APMRouteHandlerResources } from '../../../../routes/apm_routes/register_apm_server_routes';
import {
callAsyncWithDebug,
getDebugBody,
getDebugTitle,
} from '../call_async_with_debug';
import { cancelEsRequestOnAbort } from '../cancel_es_request_on_abort';
import { getApmIndices } from '../../../../routes/settings/apm_indices/get_apm_indices';
export type APMIndexDocumentParams<T> = estypes.IndexRequest<T>;
@ -28,39 +26,35 @@ export type APMInternalESClient = Awaited<
export async function createInternalESClientWithContext({
debug,
config,
apmIndices,
request,
context,
}: {
debug: boolean;
config: APMConfig;
apmIndices: APMIndices;
request: APMRouteHandlerResources['request'];
context: APMRouteHandlerResources['context'];
}) {
const coreContext = await context.core;
const { asInternalUser } = coreContext.elasticsearch.client;
const savedObjectsClient = coreContext.savedObjects.client;
return createInternalESClient({
debug,
config,
apmIndices,
request,
savedObjectsClient,
elasticsearchClient: asInternalUser,
});
}
export async function createInternalESClient({
debug,
config,
apmIndices,
request,
savedObjectsClient,
elasticsearchClient,
}: {
debug: boolean;
config: APMConfig;
apmIndices: APMIndices;
request?: APMRouteHandlerResources['request'];
savedObjectsClient: SavedObjectsClientContract;
elasticsearchClient: ElasticsearchClient;
}) {
function callEs<T extends { body: any }>(
@ -98,7 +92,7 @@ export async function createInternalESClient({
}
return {
apmIndices: await getApmIndices({ savedObjectsClient, config }),
apmIndices,
search: async <
TDocument = unknown,
TSearchRequest extends ESSearchRequest = ESSearchRequest

View file

@ -8,7 +8,7 @@
import { isEmpty } from 'lodash';
import { ESSearchRequest, InferSearchResponseOf } from '@kbn/es-types';
import { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common';
import { APMRouteHandlerResources } from '../../routes/typings';
import { APMRouteHandlerResources } from '../../routes/apm_routes/register_apm_server_routes';
export type ApmAlertsClient = Awaited<ReturnType<typeof getApmAlertsClient>>;

View file

@ -6,24 +6,21 @@
*/
import { UI_SETTINGS } from '@kbn/data-plugin/common';
import { APMRouteHandlerResources } from '../../routes/typings';
import { getApmIndices } from '../../routes/settings/apm_indices/get_apm_indices';
import { APMEventClient } from './create_es_client/create_apm_event_client';
import { withApmSpan } from '../../utils/with_apm_span';
import { APMRouteHandlerResources } from '../../routes/apm_routes/register_apm_server_routes';
export async function getApmEventClient({
context,
params,
config,
getApmIndices,
request,
}: APMRouteHandlerResources): Promise<APMEventClient> {
return withApmSpan('get_apm_event_client', async () => {
const coreContext = await context.core;
const [indices, includeFrozen] = await Promise.all([
getApmIndices({
savedObjectsClient: coreContext.savedObjects.client,
config,
}),
getApmIndices(),
withApmSpan('get_ui_settings', () =>
coreContext.uiSettings.client.get<boolean>(
UI_SETTINGS.SEARCH_INCLUDE_FROZEN

View file

@ -6,7 +6,7 @@
*/
import { SavedObjectsClientContract } from '@kbn/core/server';
import { APMRouteHandlerResources } from '../../routes/typings';
import { APMRouteHandlerResources } from '../../routes/apm_routes/register_apm_server_routes';
export async function getInfraMetricIndices({
infraPlugin,

View file

@ -7,10 +7,6 @@
import { CoreStart } from '@kbn/core/server';
export type InternalSavedObjectsClient = Awaited<
ReturnType<typeof getInternalSavedObjectsClient>
>;
export async function getInternalSavedObjectsClient(coreStart: CoreStart) {
return coreStart.savedObjects.createInternalRepository();
}

View file

@ -11,7 +11,7 @@ import {
MlModules,
} from '@kbn/ml-plugin/server';
import { isActivePlatinumLicense } from '../../../common/license_check';
import { APMRouteHandlerResources } from '../../routes/typings';
import { APMRouteHandlerResources } from '../../routes/apm_routes/register_apm_server_routes';
export interface MlClient {
mlSystem: MlMlSystem;

View file

@ -7,7 +7,7 @@
import { KibanaRequest } from '@kbn/core/server';
import seedrandom from 'seedrandom';
import { APMRouteHandlerResources } from '../../..';
import { APMRouteHandlerResources } from '../../../routes/apm_routes/register_apm_server_routes';
export async function getRandomSampler({
security,

View file

@ -5,18 +5,15 @@
* 2.0.
*/
import { firstValueFrom } from 'rxjs';
import {
CoreSetup,
CoreStart,
KibanaRequest,
Logger,
Plugin,
PluginInitializerContext,
} from '@kbn/core/server';
import { isEmpty, mapValues } from 'lodash';
import { Dataset } from '@kbn/rule-registry-plugin/server';
import { UI_SETTINGS } from '@kbn/data-plugin/common';
import { mappingFromFieldMap } from '@kbn/alerting-plugin/common';
import { alertsLocatorID } from '@kbn/observability-plugin/common';
import { APMConfig, APM_SERVER_FEATURE_ID } from '.';
@ -28,30 +25,25 @@ import {
} from './routes/alerts/register_apm_rule_types';
import { registerFleetPolicyCallbacks } from './routes/fleet/register_fleet_policy_callbacks';
import { createApmTelemetry } from './lib/apm_telemetry';
import { APMEventClient } from './lib/helpers/create_es_client/create_apm_event_client';
import { getInternalSavedObjectsClient } from './lib/helpers/get_internal_saved_objects_client';
import { createApmAgentConfigurationIndex } from './routes/settings/agent_configuration/create_agent_config_index';
import { getApmIndices } from './routes/settings/apm_indices/get_apm_indices';
import { createApmCustomLinkIndex } from './routes/settings/custom_link/create_custom_link_index';
import {
apmIndices,
apmTelemetry,
apmServerSettings,
apmServiceGroups,
} from './saved_objects';
import type {
ApmPluginRequestHandlerContext,
APMRouteHandlerResources,
} from './routes/typings';
import {
APMPluginSetup,
APMPluginSetupDependencies,
APMPluginStartDependencies,
} from './types';
import { registerRoutes } from './routes/apm_routes/register_apm_server_routes';
import {
APMRouteHandlerResources,
registerRoutes,
} from './routes/apm_routes/register_apm_server_routes';
import { getGlobalApmServerRouteRepository } from './routes/apm_routes/get_global_apm_server_route_repository';
import { tutorialProvider } from './tutorial';
import { migrateLegacyAPMIndicesToSpaceAware } from './saved_objects/migrations/migrate_legacy_apm_indices_to_space_aware';
import { scheduleSourceMapMigration } from './routes/source_maps/schedule_source_map_migration';
import { createApmSourceMapIndexTemplate } from './routes/source_maps/create_apm_source_map_index_template';
import { addApiKeysToEveryPackagePolicyIfMissing } from './routes/fleet/api_keys/add_api_keys_to_policies_if_missing';
@ -80,7 +72,6 @@ export class APMPlugin
this.logger = this.initContext.logger.get();
const config$ = this.initContext.config.create<APMConfig>();
core.savedObjects.registerType(apmIndices);
core.savedObjects.registerType(apmTelemetry);
core.savedObjects.registerType(apmServerSettings);
core.savedObjects.registerType(apmServiceGroups);
@ -95,7 +86,7 @@ export class APMPlugin
) {
createApmTelemetry({
core,
config: currentConfig,
getApmIndices: plugins.apmDataAccess.getApmIndices,
usageCollector: plugins.usageCollection,
taskManager: plugins.taskManager,
logger: this.logger,
@ -141,13 +132,12 @@ export class APMPlugin
};
}) as APMRouteHandlerResources['plugins'];
const boundGetApmIndices = async () => {
const apmIndicesPromise = (async () => {
const coreStart = await getCoreStart();
return getApmIndices({
savedObjectsClient: await getInternalSavedObjectsClient(coreStart),
config: await firstValueFrom(config$),
});
};
const soClient = await getInternalSavedObjectsClient(coreStart);
const { getApmIndices } = plugins.apmDataAccess;
return getApmIndices(soClient);
})();
// This if else block will go away in favour of removing Home Tutorial Integration
// Ideally we will directly register a custom integration and pass the configs
@ -158,11 +148,11 @@ export class APMPlugin
apmTutorialCustomIntegration
);
} else {
boundGetApmIndices().then((indices) => {
apmIndicesPromise.then((apmIndices) => {
plugins.home?.tutorials.registerTutorial(
tutorialProvider({
apmConfig: currentConfig,
apmIndices: indices,
apmIndices,
cloud: plugins.cloud,
isFleetPluginEnabled: !isEmpty(resourcePlugins.fleet),
})
@ -190,11 +180,14 @@ export class APMPlugin
kibanaVersion: this.initContext.env.packageInfo.version,
});
const { getApmIndices } = plugins.apmDataAccess;
if (plugins.alerting) {
registerApmRuleTypes({
getApmIndices,
alerting: plugins.alerting,
basePath: core.http.basePath,
config$,
apmConfig: currentConfig,
logger: this.logger!.get('rule'),
ml: plugins.ml,
observability: plugins.observability,
@ -207,7 +200,6 @@ export class APMPlugin
logger: this.logger,
coreStartPromise: getCoreStart(),
plugins: resourcePlugins,
config: currentConfig,
}).catch((e) => {
this.logger?.error('Failed to register APM Fleet policy callbacks');
this.logger?.error(e);
@ -236,38 +228,7 @@ export class APMPlugin
this.logger?.error(e);
});
return {
config$,
getApmIndices: boundGetApmIndices,
createApmEventClient: async ({
request,
context,
debug,
}: {
debug?: boolean;
request: KibanaRequest;
context: ApmPluginRequestHandlerContext;
}) => {
const coreContext = await context.core;
const [indices, includeFrozen] = await Promise.all([
boundGetApmIndices(),
coreContext.uiSettings.client.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN),
]);
const esClient = coreContext.elasticsearch.client.asCurrentUser;
return new APMEventClient({
debug: debug ?? false,
esClient,
request,
indices,
options: {
includeFrozen,
forceSyntheticSource: currentConfig.forceSyntheticSource,
},
});
},
};
return { config$ };
}
public start(core: CoreStart, plugins: APMPluginStartDependencies) {
@ -295,14 +256,6 @@ export class APMPlugin
logger.error('Failed to create apm-source-map index template');
logger.error(e);
});
// TODO: remove in 9.0
migrateLegacyAPMIndicesToSpaceAware({ coreStart: core, logger }).catch(
(e) => {
logger.error('Failed to run migration making APM indices space aware');
logger.error(e);
}
);
}
public stop() {}

View file

@ -7,8 +7,11 @@
import type { AlertsLocatorParams } from '@kbn/observability-plugin/common';
import { LocatorPublic } from '@kbn/share-plugin/common';
import { Observable } from 'rxjs';
import { IBasePath, Logger } from '@kbn/core/server';
import {
IBasePath,
Logger,
SavedObjectsClientContract,
} from '@kbn/core/server';
import {
PluginSetupContract as AlertingPluginSetupContract,
type IRuleTypeAlerts,
@ -17,6 +20,7 @@ import { ObservabilityPluginSetup } from '@kbn/observability-plugin/server';
import { IRuleDataClient } from '@kbn/rule-registry-plugin/server';
import { MlPluginSetup } from '@kbn/ml-plugin/server';
import { legacyExperimentalFieldMap } from '@kbn/alerts-as-data-utils';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import {
AGENT_NAME,
ERROR_GROUP_ID,
@ -91,7 +95,8 @@ export const ApmRuleTypeAlertDefinition: IRuleTypeAlerts = {
export interface RegisterRuleDependencies {
alerting: AlertingPluginSetupContract;
basePath: IBasePath;
config$: Observable<APMConfig>;
getApmIndices: (soClient: SavedObjectsClientContract) => Promise<APMIndices>;
apmConfig: APMConfig;
logger: Logger;
ml?: MlPluginSetup;
observability: ObservabilityPluginSetup;

View file

@ -4,11 +4,12 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { firstValueFrom } from 'rxjs';
import {
IScopedClusterClient,
SavedObjectsClientContract,
} from '@kbn/core/server';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import {
SERVICE_ENVIRONMENT,
SERVICE_NAME,
@ -20,20 +21,17 @@ import {
getServiceGroupFields,
getServiceGroupFieldsAgg,
} from '../get_service_group_fields';
import { getApmIndices } from '../../../settings/apm_indices/get_apm_indices';
import { RegisterRuleDependencies } from '../../register_apm_rule_types';
export async function getServiceGroupFieldsForAnomaly({
config$,
apmIndices,
scopedClusterClient,
savedObjectsClient,
serviceName,
environment,
transactionType,
timestamp,
bucketSpan,
}: {
config$: RegisterRuleDependencies['config$'];
apmIndices: APMIndices;
scopedClusterClient: IScopedClusterClient;
savedObjectsClient: SavedObjectsClientContract;
serviceName: string;
@ -42,15 +40,8 @@ export async function getServiceGroupFieldsForAnomaly({
timestamp: number;
bucketSpan: number;
}) {
const config = await firstValueFrom(config$);
const indices = await getApmIndices({
config,
savedObjectsClient,
});
const { transaction: index } = indices;
const params = {
index,
index: apmIndices.transaction,
body: {
size: 0,
track_total_hits: false,

View file

@ -63,8 +63,8 @@ const ruleTypeConfig = RULE_TYPES_CONFIG[ApmRuleType.Anomaly];
export function registerAnomalyRuleType({
alerting,
alertsLocator,
getApmIndices,
basePath,
config$,
logger,
ml,
ruleDataClient,
@ -108,6 +108,8 @@ export function registerAnomalyRuleType({
scopedClusterClient,
} = services;
const apmIndices = await getApmIndices(savedObjectsClient);
const ruleParams = params;
const request = {} as KibanaRequest;
const { mlAnomalySearch } = ml.mlSystemProvider(
@ -256,7 +258,7 @@ export function registerAnomalyRuleType({
} = anomaly;
const eventSourceFields = await getServiceGroupFieldsForAnomaly({
config$,
apmIndices,
scopedClusterClient,
savedObjectsClient,
serviceName,

View file

@ -25,7 +25,6 @@ import {
} from '@kbn/observability-plugin/server';
import { addSpaceIdToPath } from '@kbn/spaces-plugin/common';
import { asyncForEach } from '@kbn/std';
import { firstValueFrom } from 'rxjs';
import { getEnvironmentEsField } from '../../../../../common/environment_filter_values';
import {
ERROR_GROUP_ID,
@ -42,7 +41,6 @@ import {
import { errorCountParamsSchema } from '../../../../../common/rules/schema';
import { environmentQuery } from '../../../../../common/utils/environment_query';
import { getAlertUrlErrorCount } from '../../../../../common/utils/formatters';
import { getApmIndices } from '../../../settings/apm_indices/get_apm_indices';
import { apmActionVariables } from '../../action_variables';
import { alertingEsClient } from '../../alerting_es_client';
import {
@ -63,7 +61,7 @@ export function registerErrorCountRuleType({
alerting,
alertsLocator,
basePath,
config$,
getApmIndices,
logger,
ruleDataClient,
}: RegisterRuleDependencies) {
@ -108,8 +106,6 @@ export function registerErrorCountRuleType({
ruleParams.groupBy
);
const config = await firstValueFrom(config$);
const {
getAlertUuid,
getAlertStartedDate,
@ -117,10 +113,7 @@ export function registerErrorCountRuleType({
scopedClusterClient,
} = services;
const indices = await getApmIndices({
config,
savedObjectsClient,
});
const indices = await getApmIndices(savedObjectsClient);
const termFilterQuery = !ruleParams.kqlFilter
? [

View file

@ -26,7 +26,6 @@ import {
} from '@kbn/rule-data-utils';
import { createLifecycleRuleTypeFactory } from '@kbn/rule-registry-plugin/server';
import { addSpaceIdToPath } from '@kbn/spaces-plugin/common';
import { firstValueFrom } from 'rxjs';
import { getGroupByTerms } from '../utils/get_groupby_terms';
import { SearchAggregatedTransactionSetting } from '../../../../../common/aggregated_transactions';
import { getEnvironmentEsField } from '../../../../../common/environment_filter_values';
@ -53,7 +52,6 @@ import {
getDocumentTypeFilterForTransactions,
getDurationFieldForTransactions,
} from '../../../../lib/helpers/transactions';
import { getApmIndices } from '../../../settings/apm_indices/get_apm_indices';
import { apmActionVariables } from '../../action_variables';
import { alertingEsClient } from '../../alerting_es_client';
import {
@ -76,7 +74,8 @@ const ruleTypeConfig = RULE_TYPES_CONFIG[ApmRuleType.TransactionDuration];
export function registerTransactionDurationRuleType({
alerting,
ruleDataClient,
config$,
getApmIndices,
apmConfig,
logger,
basePath,
}: RegisterRuleDependencies) {
@ -114,21 +113,16 @@ export function registerTransactionDurationRuleType({
ruleParams.groupBy
);
const config = await firstValueFrom(config$);
const { getAlertUuid, savedObjectsClient, scopedClusterClient } =
services;
const indices = await getApmIndices({
config,
savedObjectsClient,
});
const indices = await getApmIndices(savedObjectsClient);
// only query transaction events when set to 'never',
// to prevent (likely) unnecessary blocking request
// in rule execution
const searchAggregatedTransactions =
config.searchAggregatedTransactions !==
apmConfig.searchAggregatedTransactions !==
SearchAggregatedTransactionSetting.never;
const index = searchAggregatedTransactions

View file

@ -26,7 +26,6 @@ import {
import { createLifecycleRuleTypeFactory } from '@kbn/rule-registry-plugin/server';
import { addSpaceIdToPath } from '@kbn/spaces-plugin/common';
import { asyncForEach } from '@kbn/std';
import { firstValueFrom } from 'rxjs';
import { SearchAggregatedTransactionSetting } from '../../../../../common/aggregated_transactions';
import { getEnvironmentEsField } from '../../../../../common/environment_filter_values';
import {
@ -51,7 +50,6 @@ import {
getAlertUrlTransaction,
} from '../../../../../common/utils/formatters';
import { getDocumentTypeFilterForTransactions } from '../../../../lib/helpers/transactions';
import { getApmIndices } from '../../../settings/apm_indices/get_apm_indices';
import { apmActionVariables } from '../../action_variables';
import { alertingEsClient } from '../../alerting_es_client';
import {
@ -72,7 +70,8 @@ export function registerTransactionErrorRateRuleType({
alerting,
alertsLocator,
basePath,
config$,
getApmIndices,
apmConfig,
logger,
ruleDataClient,
}: RegisterRuleDependencies) {
@ -117,8 +116,6 @@ export function registerTransactionErrorRateRuleType({
ruleParams.groupBy
);
const config = await firstValueFrom(config$);
const {
getAlertUuid,
getAlertStartedDate,
@ -126,16 +123,13 @@ export function registerTransactionErrorRateRuleType({
scopedClusterClient,
} = services;
const indices = await getApmIndices({
config,
savedObjectsClient,
});
const indices = await getApmIndices(savedObjectsClient);
// only query transaction events when set to 'never',
// to prevent (likely) unnecessary blocking request
// in rule execution
const searchAggregatedTransactions =
config.searchAggregatedTransactions !==
apmConfig.searchAggregatedTransactions !==
SearchAggregatedTransactionSetting.never;
const index = searchAggregatedTransactions

View file

@ -5,7 +5,6 @@
* 2.0.
*/
import { of } from 'rxjs';
import { IBasePath, Logger } from '@kbn/core/server';
import { elasticsearchServiceMock } from '@kbn/core/server/mocks';
import type { AlertsLocatorParams } from '@kbn/observability-plugin/common';
@ -20,13 +19,6 @@ import { APMConfig, APM_SERVER_FEATURE_ID } from '../../..';
export const createRuleTypeMocks = () => {
let alertExecutor: (...args: any[]) => Promise<any>;
const mockedConfig$ = of({
indices: {
error: 'apm-*',
transaction: 'apm-*',
},
} as APMConfig);
const loggerMock = {
debug: jest.fn(),
warn: jest.fn(),
@ -64,7 +56,14 @@ export const createRuleTypeMocks = () => {
publicBaseUrl: 'http://localhost:5601/eyr',
serverBasePath: '/eyr',
} as IBasePath,
config$: mockedConfig$,
apmConfig: { searchAggregatedTransactions: true } as any as APMConfig,
getApmIndices: async () => ({
error: 'apm-*',
transaction: 'apm-*',
span: 'apm-*',
metric: 'apm-*',
onboarding: 'apm-*',
}),
observability: {
getAlertDetailsConfig: jest.fn().mockReturnValue({ apm: true }),
} as unknown as ObservabilityPluginSetup,

View file

@ -5,7 +5,8 @@
* 2.0.
*/
import { createServerRouteFactory } from '@kbn/server-route-repository';
import { APMRouteCreateOptions, APMRouteHandlerResources } from '../typings';
import { APMRouteCreateOptions } from '../typings';
import { APMRouteHandlerResources } from './register_apm_server_routes';
export const createApmServerRoute = createServerRouteFactory<
APMRouteHandlerResources,

View file

@ -13,8 +13,11 @@ import {
import * as t from 'io-ts';
import { CoreSetup, Logger } from '@kbn/core/server';
import { APMConfig } from '../..';
import { APMRouteCreateOptions, APMRouteHandlerResources } from '../typings';
import { registerRoutes } from './register_apm_server_routes';
import { APMRouteCreateOptions } from '../typings';
import {
APMRouteHandlerResources,
registerRoutes,
} from './register_apm_server_routes';
import { NEVER } from 'rxjs';
type RegisterRouteDependencies = Parameters<typeof registerRoutes>[0];
@ -54,7 +57,18 @@ const getRegisterRouteDependencies = () => {
},
logger,
config: {} as APMConfig,
plugins: {},
plugins: {
apmDataAccess: {
setup: {
indices: {
errorIndices: 'apm-*',
metricsIndices: 'apm-*',
spanIndices: 'apm-*',
transactionIndices: 'apm-*',
},
},
},
},
} as unknown as RegisterRouteDependencies,
};
};
@ -208,9 +222,7 @@ describe('createApi', () => {
} = initApi([
{
endpoint: 'GET /foo',
options: {
tags: [],
},
options: { tags: [] },
handler: handlerMock,
},
]);

View file

@ -8,6 +8,7 @@
import Boom from '@hapi/boom';
import * as t from 'io-ts';
import {
Logger,
KibanaRequest,
KibanaResponseFactory,
RouteRegistrar,
@ -25,9 +26,17 @@ import { jsonRt, mergeRt } from '@kbn/io-ts-utils';
import { InspectResponse } from '@kbn/observability-plugin/typings/common';
import apm from 'elastic-apm-node';
import { VersionedRouteRegistrar } from '@kbn/core-http-server';
import { IRuleDataClient } from '@kbn/rule-registry-plugin/server';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { ApmFeatureFlags } from '../../../common/apm_feature_flags';
import { pickKeys } from '../../../common/utils/pick_keys';
import { APMRouteHandlerResources, TelemetryUsageCounter } from '../typings';
import { APMCore, TelemetryUsageCounter } from '../typings';
import type { ApmPluginRequestHandlerContext } from '../typings';
import { APMConfig } from '../..';
import {
APMPluginSetupDependencies,
APMPluginStartDependencies,
} from '../../types';
const inspectRt = t.exact(
t.partial({
@ -99,6 +108,14 @@ export function registerRoutes({
runtimeType
);
const getApmIndices = async () => {
const coreContext = await context.core;
const apmIndices = await plugins.apmDataAccess.setup.getApmIndices(
coreContext.savedObjects.client
);
return apmIndices;
};
const { aborted, data } = await Promise.race([
handler({
request,
@ -109,6 +126,7 @@ export function registerRoutes({
core,
plugins,
telemetryUsageCounter,
getApmIndices,
params: merge(
{
query: {
@ -231,3 +249,29 @@ export function registerRoutes({
}
});
}
type Plugins = {
[key in keyof APMPluginSetupDependencies]: {
setup: Required<APMPluginSetupDependencies>[key];
start: () => Promise<Required<APMPluginStartDependencies>[key]>;
};
};
export interface APMRouteHandlerResources {
request: KibanaRequest;
context: ApmPluginRequestHandlerContext;
params: {
query: {
_inspect: boolean;
};
};
config: APMConfig;
featureFlags: ApmFeatureFlags;
logger: Logger;
core: APMCore;
plugins: Plugins;
ruleDataClient: IRuleDataClient;
telemetryUsageCounter?: TelemetryUsageCounter;
kibanaVersion: string;
getApmIndices: () => Promise<APMIndices>;
}

View file

@ -8,9 +8,10 @@
import { createStaticDataView } from './create_static_data_view';
import * as HistoricalAgentData from '../historical_data/has_historical_agent_data';
import { DataViewsService } from '@kbn/data-views-plugin/common';
import { APMRouteHandlerResources, APMCore } from '../typings';
import { APMCore } from '../typings';
import { APMEventClient } from '../../lib/helpers/create_es_client/create_apm_event_client';
import { APMConfig } from '../..';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { APMRouteHandlerResources } from '../apm_routes/register_apm_server_routes';
function getMockedDataViewService(existingDataViewTitle: string) {
return {
@ -42,7 +43,7 @@ const apmEventClientMock = {
span: 'apm-*-span-*',
error: 'apm-*-error-*',
metric: 'apm-*-metrics-*',
} as APMConfig['indices'],
} as APMIndices,
} as unknown as APMEventClient;
describe('createStaticDataView', () => {

View file

@ -17,9 +17,8 @@ import { APM_STATIC_DATA_VIEW_ID } from '../../../common/data_view_constants';
import { hasHistoricalAgentData } from '../historical_data/has_historical_agent_data';
import { withApmSpan } from '../../utils/with_apm_span';
import { getApmDataViewTitle } from './get_apm_data_view_title';
import { APMRouteHandlerResources } from '../typings';
import { APMEventClient } from '../../lib/helpers/create_es_client/create_apm_event_client';
import { APMRouteHandlerResources } from '../apm_routes/register_apm_server_routes';
export type CreateDataViewResponse = Promise<
| { created: boolean; dataView: DataView }

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { ApmIndicesConfig } from '../settings/apm_indices/get_apm_indices';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { getApmDataViewTitle } from './get_apm_data_view_title';
describe('getApmDataViewTitle', () => {
@ -15,7 +15,7 @@ describe('getApmDataViewTitle', () => {
span: 'apm-*-span-*',
error: 'apm-*-error-*',
metric: 'apm-*-metrics-*',
} as ApmIndicesConfig);
} as APMIndices);
expect(title).toBe(
'apm-*-transaction-*,apm-*-span-*,apm-*-error-*,apm-*-metrics-*'
);
@ -27,7 +27,7 @@ describe('getApmDataViewTitle', () => {
span: 'apm-*',
error: 'apm-*',
metric: 'apm-*',
} as ApmIndicesConfig);
} as APMIndices);
expect(title).toBe('apm-*');
});
});

View file

@ -6,13 +6,13 @@
*/
import { uniq } from 'lodash';
import { ApmIndicesConfig } from '../settings/apm_indices/get_apm_indices';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
export function getApmDataViewTitle(apmIndicesConfig: ApmIndicesConfig) {
export function getApmDataViewTitle(apmIndices: APMIndices) {
return uniq([
apmIndicesConfig.transaction,
apmIndicesConfig.span,
apmIndicesConfig.error,
apmIndicesConfig.metric,
apmIndices.transaction,
apmIndices.span,
apmIndices.error,
apmIndices.metric,
]).join(',');
}

View file

@ -11,7 +11,6 @@ import {
} from './create_static_data_view';
import { createApmServerRoute } from '../apm_routes/create_apm_server_route';
import { getApmDataViewTitle } from './get_apm_data_view_title';
import { getApmIndices } from '../settings/apm_indices/get_apm_indices';
import { getApmEventClient } from '../../lib/helpers/get_apm_event_client';
const staticDataViewRoute = createApmServerRoute({
@ -43,15 +42,8 @@ const staticDataViewRoute = createApmServerRoute({
const dataViewTitleRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/data_view/title',
options: { tags: ['access:apm'] },
handler: async ({
context,
config,
}): Promise<{ apmDataViewTitle: string }> => {
const coreContext = await context.core;
const apmIndicies = await getApmIndices({
savedObjectsClient: coreContext.savedObjects.client,
config,
});
handler: async ({ getApmIndices }): Promise<{ apmDataViewTitle: string }> => {
const apmIndicies = await getApmIndices();
const apmDataViewTitle = getApmDataViewTitle(apmIndicies);
return { apmDataViewTitle };

View file

@ -8,6 +8,7 @@
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { kqlQuery, rangeQuery } from '@kbn/observability-plugin/server';
import { merge } from 'lodash';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import {
PROCESSOR_EVENT,
METRICSET_NAME,
@ -15,7 +16,6 @@ import {
TRANSACTION_DURATION_SUMMARY,
INDEX,
} from '../../../../common/es_fields/apm';
import { ApmIndicesConfig } from '../../settings/apm_indices/get_apm_indices';
import { getTypedSearch, TypedSearch } from '../create_typed_es_client';
import { getApmIndexPatterns } from './get_indices';
@ -36,7 +36,7 @@ export async function getApmEvents({
kuery,
}: {
esClient: ElasticsearchClient;
apmIndices: ApmIndicesConfig;
apmIndices: APMIndices;
start: number;
end: number;
kuery?: string;

View file

@ -6,7 +6,7 @@
*/
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { ApmIndicesConfig } from '../../settings/apm_indices/get_apm_indices';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { getApmIndexPatterns } from './get_indices';
export async function getDataStreams({
@ -14,7 +14,7 @@ export async function getDataStreams({
apmIndices,
}: {
esClient: ElasticsearchClient;
apmIndices: ApmIndicesConfig;
apmIndices: APMIndices;
}) {
const apmIndexPatterns = getApmIndexPatterns([
apmIndices.error,

View file

@ -6,8 +6,8 @@
*/
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { SERVICE_NAME } from '../../../../common/es_fields/apm';
import { ApmIndicesConfig } from '../../settings/apm_indices/get_apm_indices';
import { getApmIndexPatterns } from './get_indices';
export function getFieldCaps({
@ -15,7 +15,7 @@ export function getFieldCaps({
apmIndices,
}: {
esClient: ElasticsearchClient;
apmIndices: ApmIndicesConfig;
apmIndices: APMIndices;
}) {
return esClient.fieldCaps({
index: getApmIndexPatterns([apmIndices.metric, apmIndices.transaction]),

View file

@ -9,7 +9,7 @@ import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { IndicesSimulateTemplateResponse } from '@elastic/elasticsearch/lib/api/types';
import { orderBy } from 'lodash';
import { errors } from '@elastic/elasticsearch';
import { ApmIndicesConfig } from '../../settings/apm_indices/get_apm_indices';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { getApmIndexPatterns } from './get_indices';
import { getIndexTemplate } from './get_index_template';
import { getApmIndexTemplateNames } from '../helpers/get_apm_index_template_names';
@ -19,7 +19,7 @@ export async function getIndexTemplatesByIndexPattern({
apmIndices,
}: {
esClient: ElasticsearchClient;
apmIndices: ApmIndicesConfig;
apmIndices: APMIndices;
}) {
const indexPatterns = getApmIndexPatterns([
apmIndices.error,

View file

@ -7,7 +7,7 @@
import { compact, uniq } from 'lodash';
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { ApmIndicesConfig } from '../../settings/apm_indices/get_apm_indices';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
export function getApmIndexPatterns(indices: string[]) {
return uniq(indices.flatMap((index): string[] => index.split(',')));
@ -18,7 +18,7 @@ export async function getIndicesAndIngestPipelines({
apmIndices,
}: {
esClient: ElasticsearchClient;
apmIndices: ApmIndicesConfig;
apmIndices: APMIndices;
}) {
const indices = await esClient.indices.get({
index: getApmIndexPatterns([

View file

@ -6,7 +6,7 @@
*/
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { ApmIndicesConfig } from '@kbn/observability-plugin/common/typings';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { SERVICE_NAME } from '../../../../common/es_fields/apm';
import { getApmIndexTemplateNames } from '../helpers/get_apm_index_template_names';
import { getFieldCaps } from './get_field_caps';
@ -17,7 +17,7 @@ export async function getIndicesStates({
apmIndices,
}: {
esClient: ElasticsearchClient;
apmIndices: ApmIndicesConfig;
apmIndices: APMIndices;
}) {
const { indices, ingestPipelines } = await getIndicesAndIngestPipelines({
esClient,

View file

@ -6,7 +6,7 @@
*/
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { ApmIndicesConfig } from '@kbn/observability-plugin/common/typings';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { getApmIndexPatterns } from './get_indices';
export async function getNonDataStreamIndices({
@ -14,7 +14,7 @@ export async function getNonDataStreamIndices({
apmIndices,
}: {
esClient: ElasticsearchClient;
apmIndices: ApmIndicesConfig;
apmIndices: APMIndices;
}) {
const apmIndexPatterns = getApmIndexPatterns([
apmIndices.error,

View file

@ -6,8 +6,8 @@
*/
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { NOT_AVAILABLE_LABEL } from '../../../common/i18n';
import { ApmIndicesConfig } from '../settings/apm_indices/get_apm_indices';
import { getDataStreams } from './bundle/get_data_streams';
import { getNonDataStreamIndices } from './bundle/get_non_data_stream_indices';
import { getElasticsearchVersion } from './get_elasticsearch_version';
@ -30,7 +30,7 @@ export async function getDiagnosticsBundle({
kuery,
}: {
esClient: ElasticsearchClient;
apmIndices: ApmIndicesConfig;
apmIndices: APMIndices;
start: number | undefined;
end: number | undefined;
kuery: string | undefined;

View file

@ -6,7 +6,7 @@
*/
import { FleetUnauthorizedError } from '@kbn/fleet-plugin/server/errors';
import { APMRouteHandlerResources } from '../typings';
import { APMRouteHandlerResources } from '../apm_routes/register_apm_server_routes';
export async function getFleetPackageInfo(resources: APMRouteHandlerResources) {
const fleetPluginStart = await resources.plugins.fleet?.start();

View file

@ -6,7 +6,7 @@
*/
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { ApmIndicesConfig } from '../../settings/apm_indices/get_apm_indices';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { getApmIndexPatterns } from '../bundle/get_indices';
export async function getDiagnosticsPrivileges({
@ -14,7 +14,7 @@ export async function getDiagnosticsPrivileges({
apmIndices,
}: {
esClient: ElasticsearchClient;
apmIndices: ApmIndicesConfig;
apmIndices: APMIndices;
}) {
const indexPatterns = getApmIndexPatterns([
apmIndices.error,

View file

@ -13,13 +13,10 @@ import {
IngestGetPipelineResponse,
SecurityHasPrivilegesPrivileges,
} from '@elastic/elasticsearch/lib/api/types';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import * as t from 'io-ts';
import { isoToEpochRt } from '@kbn/io-ts-utils';
import { createApmServerRoute } from '../apm_routes/create_apm_server_route';
import {
ApmIndicesConfig,
getApmIndices,
} from '../settings/apm_indices/get_apm_indices';
import { ApmEvent } from './bundle/get_apm_events';
import { getDiagnosticsBundle } from './get_diagnostics_bundle';
import { getFleetPackageInfo } from './get_fleet_package_info';
@ -38,6 +35,49 @@ export interface IndiciesItem {
isValid: boolean;
}
export type DiagnosticsBundle = Promise<{
esResponses: {
existingIndexTemplates: IndicesGetIndexTemplateIndexTemplateItem[];
fieldCaps: FieldCapsResponse;
indices: IndicesGetResponse;
ingestPipelines: IngestGetPipelineResponse;
};
diagnosticsPrivileges: {
index: Record<string, SecurityHasPrivilegesPrivileges>;
cluster: Record<string, boolean>;
hasAllClusterPrivileges: boolean;
hasAllIndexPrivileges: boolean;
hasAllPrivileges: boolean;
};
apmIndices: APMIndices;
apmIndexTemplates: Array<{
name: string;
isNonStandard: boolean;
exists: boolean;
}>;
fleetPackageInfo: {
isInstalled: boolean;
version?: string;
};
kibanaVersion: string;
elasticsearchVersion: string;
apmEvents: ApmEvent[];
invalidIndices: IndiciesItem[];
validIndices: IndiciesItem[];
dataStreams: IndicesDataStream[];
nonDataStreamIndices: string[];
indexTemplatesByIndexPattern: Array<{
indexPattern: string;
indexTemplates: Array<{
priority: number | undefined;
isNonStandard: boolean;
templateIndexPatterns: string[];
templateName: string;
}>;
}>;
params: { start: number; end: number; kuery?: string };
}>;
const getDiagnosticsRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/diagnostics',
options: { tags: ['access:apm'] },
@ -64,7 +104,7 @@ const getDiagnosticsRoute = createApmServerRoute({
hasAllIndexPrivileges: boolean;
hasAllPrivileges: boolean;
};
apmIndices: ApmIndicesConfig;
apmIndices: APMIndices;
apmIndexTemplates: Array<{
name: string;
isNonStandard: boolean;
@ -94,11 +134,8 @@ const getDiagnosticsRoute = createApmServerRoute({
}> => {
const { start, end, kuery } = resources.params.query;
const coreContext = await resources.context.core;
const apmIndices = await resources.getApmIndices();
const { asCurrentUser: esClient } = coreContext.elasticsearch.client;
const apmIndices = await getApmIndices({
savedObjectsClient: coreContext.savedObjects.client,
config: resources.config,
});
const bundle = await getDiagnosticsBundle({
esClient,

View file

@ -9,7 +9,7 @@ import { CoreStart, Logger } from '@kbn/core/server';
import {
APM_AGENT_CONFIGURATION_INDEX,
APM_SOURCE_MAP_INDEX,
} from '../../settings/apm_indices/get_apm_indices';
} from '../../settings/apm_indices/apm_system_index_constants';
const apiKeyMetadata = {
application: 'apm',

View file

@ -5,7 +5,11 @@
* 2.0.
*/
import { Logger, CoreStart } from '@kbn/core/server';
import {
Logger,
CoreStart,
SavedObjectsClientContract,
} from '@kbn/core/server';
import {
FleetStartContract,
PostPackagePolicyCreateCallback,
@ -14,7 +18,7 @@ import {
PutPackagePolicyUpdateCallback,
} from '@kbn/fleet-plugin/server';
import { get } from 'lodash';
import { APMConfig, APMPlugin, APMRouteHandlerResources } from '../..';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { decoratePackagePolicyWithAgentConfigAndSourceMap } from './merge_package_policy_with_apm';
import { addApiKeysToPackagePolicyIfMissing } from './api_keys/add_api_keys_to_policies_if_missing';
import {
@ -23,33 +27,41 @@ import {
} from './get_package_policy_decorators';
import { createInternalESClient } from '../../lib/helpers/create_es_client/create_internal_es_client';
import { getInternalSavedObjectsClient } from '../../lib/helpers/get_internal_saved_objects_client';
import { APMRouteHandlerResources } from '../apm_routes/register_apm_server_routes';
export async function registerFleetPolicyCallbacks({
logger,
coreStartPromise,
plugins,
config,
}: {
logger: Logger;
coreStartPromise: Promise<CoreStart>;
plugins: APMRouteHandlerResources['plugins'];
config: NonNullable<APMPlugin['currentConfig']>;
}) {
if (!plugins.fleet) {
return;
}
const fleetPluginStart = await plugins.fleet.start();
const { getApmIndices } = plugins.apmDataAccess.setup;
const coreStart = await coreStartPromise;
fleetPluginStart.registerExternalCallback(
'packagePolicyUpdate',
onPackagePolicyCreateOrUpdate({ fleetPluginStart, config, coreStart })
onPackagePolicyCreateOrUpdate({
fleetPluginStart,
getApmIndices,
coreStart,
})
);
fleetPluginStart.registerExternalCallback(
'packagePolicyCreate',
onPackagePolicyCreateOrUpdate({ fleetPluginStart, config, coreStart })
onPackagePolicyCreateOrUpdate({
fleetPluginStart,
getApmIndices,
coreStart,
})
);
fleetPluginStart.registerExternalCallback(
@ -143,11 +155,11 @@ function onPackagePolicyPostCreate({
*/
function onPackagePolicyCreateOrUpdate({
fleetPluginStart,
config,
getApmIndices,
coreStart,
}: {
fleetPluginStart: FleetStartContract;
config: APMConfig;
getApmIndices: (soClient: SavedObjectsClientContract) => Promise<APMIndices>;
coreStart: CoreStart;
}): PutPackagePolicyUpdateCallback & PostPackagePolicyCreateCallback {
return async (packagePolicy) => {
@ -157,10 +169,11 @@ function onPackagePolicyCreateOrUpdate({
const { asInternalUser } = coreStart.elasticsearch.client;
const savedObjectsClient = await getInternalSavedObjectsClient(coreStart);
const apmIndices = await getApmIndices(savedObjectsClient);
const internalESClient = await createInternalESClient({
debug: false,
config,
savedObjectsClient,
apmIndices,
elasticsearchClient: asInternalUser,
});

View file

@ -153,11 +153,13 @@ const createCloudApmPackagePolicyRoute = createApmServerRoute({
coreStart,
fleetPluginStart,
securityPluginStart,
apmIndices,
] = await Promise.all([
(await context.core).savedObjects.client,
resources.core.start(),
plugins.fleet.start(),
plugins.security.start(),
resources.getApmIndices(),
]);
const esClient = coreStart.elasticsearch.client.asScoped(
@ -174,7 +176,7 @@ const createCloudApmPackagePolicyRoute = createApmServerRoute({
context,
request,
debug: resources.params.query._inspect,
config: resources.config,
apmIndices,
});
const cloudApmPackagePolicy = await createCloudApmPackgePolicy({

View file

@ -6,7 +6,7 @@
*/
import { PackagePolicy } from '@kbn/fleet-plugin/common';
import { APMRouteHandlerResources } from '../typings';
import { APMRouteHandlerResources } from '../apm_routes/register_apm_server_routes';
import { getApmPackagePolicies } from './get_apm_package_policies';
import {
getApmPackagePolicy,

View file

@ -6,8 +6,8 @@
*/
import { ProcessorEvent } from '@kbn/observability-plugin/common';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { APMEventClient } from '../../lib/helpers/create_es_client/create_apm_event_client';
import { ApmIndicesConfig } from '../settings/apm_indices/get_apm_indices';
export interface HasDataResponse {
hasData: boolean;
@ -24,7 +24,7 @@ export async function getHasData({
indices,
apmEventClient,
}: {
indices: ApmIndicesConfig;
indices: APMIndices;
apmEventClient: APMEventClient;
}): Promise<HasDataResponse> {
try {

View file

@ -10,7 +10,7 @@ import {
createOrUpdateIndex,
Mappings,
} from '@kbn/observability-plugin/server';
import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/get_apm_indices';
import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/apm_system_index_constants';
export async function createApmAgentConfigurationIndex({
client,

View file

@ -14,7 +14,7 @@ import {
APMIndexDocumentParams,
APMInternalESClient,
} from '../../../lib/helpers/create_es_client/create_internal_es_client';
import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/get_apm_indices';
import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/apm_system_index_constants';
export function createOrUpdateConfiguration({
configurationId,

View file

@ -6,7 +6,7 @@
*/
import { APMInternalESClient } from '../../../lib/helpers/create_es_client/create_internal_es_client';
import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/get_apm_indices';
import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/apm_system_index_constants';
export async function deleteConfiguration({
configurationId,

View file

@ -12,7 +12,7 @@ import {
SERVICE_NAME,
} from '../../../../common/es_fields/apm';
import { APMInternalESClient } from '../../../lib/helpers/create_es_client/create_internal_es_client';
import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/get_apm_indices';
import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/apm_system_index_constants';
import { convertConfigSettingsToString } from './convert_settings_to_string';
import { getConfigsAppliedToAgentsThroughFleet } from './get_config_applied_to_agent_through_fleet';

View file

@ -11,7 +11,7 @@ import {
} from '../../../../../common/es_fields/apm';
import { ALL_OPTION_VALUE } from '../../../../../common/agent_configuration/all_option';
import { APMInternalESClient } from '../../../../lib/helpers/create_es_client/create_internal_es_client';
import { APM_AGENT_CONFIGURATION_INDEX } from '../../apm_indices/get_apm_indices';
import { APM_AGENT_CONFIGURATION_INDEX } from '../../apm_indices/apm_system_index_constants';
export async function getExistingEnvironmentsForService({
serviceName,

View file

@ -9,7 +9,7 @@ import { AgentConfiguration } from '../../../../common/agent_configuration/confi
import { convertConfigSettingsToString } from './convert_settings_to_string';
import { getConfigsAppliedToAgentsThroughFleet } from './get_config_applied_to_agent_through_fleet';
import { APMInternalESClient } from '../../../lib/helpers/create_es_client/create_internal_es_client';
import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/get_apm_indices';
import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/apm_system_index_constants';
export async function listConfigurations(
internalESClient: APMInternalESClient

View file

@ -7,7 +7,7 @@
import { AgentConfiguration } from '../../../../common/agent_configuration/configuration_types';
import { APMInternalESClient } from '../../../lib/helpers/create_es_client/create_internal_es_client';
import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/get_apm_indices';
import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/apm_system_index_constants';
// We're not wrapping this function with a span as it is not blocking the request
export async function markAppliedByAgent({

View file

@ -49,13 +49,14 @@ const agentConfigurationRoute = createApmServerRoute({
}> => {
throwNotFoundIfAgentConfigNotAvailable(resources.featureFlags);
const { context, request, params, config } = resources;
const { context, request, params } = resources;
const apmIndices = await resources.getApmIndices();
const internalESClient = await createInternalESClientWithContext({
context,
request,
debug: params.query._inspect,
config,
apmIndices,
});
const configurations = await listConfigurations(internalESClient);
@ -74,15 +75,16 @@ const getSingleAgentConfigurationRoute = createApmServerRoute({
handler: async (resources): Promise<AgentConfiguration> => {
throwNotFoundIfAgentConfigNotAvailable(resources.featureFlags);
const { params, logger, context, request, config } = resources;
const { params, logger, context, request } = resources;
const { name, environment, _inspect } = params.query;
const service = { name, environment };
const apmIndices = await resources.getApmIndices();
const internalESClient = await createInternalESClientWithContext({
context,
request,
debug: _inspect,
config,
apmIndices,
});
const exactConfig = await findExactConfiguration({
service,
@ -115,22 +117,16 @@ const deleteAgentConfigurationRoute = createApmServerRoute({
handler: async (resources): Promise<{ result: string }> => {
throwNotFoundIfAgentConfigNotAvailable(resources.featureFlags);
const {
params,
logger,
core,
telemetryUsageCounter,
context,
request,
config,
} = resources;
const { params, logger, core, telemetryUsageCounter, context, request } =
resources;
const { service } = params.body;
const apmIndices = await resources.getApmIndices();
const internalESClient = await createInternalESClientWithContext({
context,
request,
debug: params.query._inspect,
config,
apmIndices,
});
const exactConfig = await findExactConfiguration({
service,
@ -181,22 +177,16 @@ const createOrUpdateAgentConfigurationRoute = createApmServerRoute({
]),
handler: async (resources): Promise<void> => {
throwNotFoundIfAgentConfigNotAvailable(resources.featureFlags);
const {
params,
logger,
core,
telemetryUsageCounter,
context,
request,
config,
} = resources;
const { params, logger, core, telemetryUsageCounter, context, request } =
resources;
const { body, query } = params;
const apmIndices = await resources.getApmIndices();
const internalESClient = await createInternalESClientWithContext({
context,
request,
debug: params.query._inspect,
config,
apmIndices,
});
// if the config already exists, it is fetched and updated
@ -258,19 +248,20 @@ const agentConfigurationSearchRoute = createApmServerRoute({
): Promise<SearchHit<AgentConfiguration, undefined, undefined> | null> => {
throwNotFoundIfAgentConfigNotAvailable(resources.featureFlags);
const { params, logger, context, config, request } = resources;
const { params, logger, context, request } = resources;
const {
service,
etag,
mark_as_applied_by_agent: markAsAppliedByAgent,
} = params.body;
const apmIndices = await resources.getApmIndices();
const internalESClient = await createInternalESClientWithContext({
context,
request,
debug: params.query._inspect,
config,
apmIndices,
});
const configuration = await searchConfigurations({
service,
@ -332,12 +323,14 @@ const listAgentConfigurationEnvironmentsRoute = createApmServerRoute({
throwNotFoundIfAgentConfigNotAvailable(resources.featureFlags);
const { context, request, params, config } = resources;
const apmIndices = await resources.getApmIndices();
const [internalESClient, apmEventClient] = await Promise.all([
createInternalESClientWithContext({
context,
request,
debug: params.query._inspect,
config,
apmIndices,
}),
getApmEventClient(resources),
]);

View file

@ -13,7 +13,7 @@ import {
import { AgentConfiguration } from '../../../../common/agent_configuration/configuration_types';
import { convertConfigSettingsToString } from './convert_settings_to_string';
import { APMInternalESClient } from '../../../lib/helpers/create_es_client/create_internal_es_client';
import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/get_apm_indices';
import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/apm_system_index_constants';
export async function searchConfigurations({
service,

View file

@ -21,7 +21,6 @@ import { updateToV3 } from './update_to_v3';
import { environmentStringRt } from '../../../../common/environment_rt';
import { getMlJobsWithAPMGroup } from '../../../lib/anomaly_detection/get_ml_jobs_with_apm_group';
import { getApmEventClient } from '../../../lib/helpers/get_apm_event_client';
import { getApmIndices } from '../apm_indices/get_apm_indices';
import { ApmMlJob } from '../../../../common/anomaly_detection/apm_ml_job';
// get ML anomaly detection jobs for each environment
const anomalyDetectionJobsRoute = createApmServerRoute({
@ -68,18 +67,14 @@ const createAnomalyDetectionJobsRoute = createApmServerRoute({
}),
}),
handler: async (resources): Promise<{ jobCreated: true }> => {
const { params, context, logger, config } = resources;
const { params, context, logger, getApmIndices } = resources;
const { environments } = params.body;
const licensingContext = await context.licensing;
const coreContext = await context.core;
const esClient = (await context.core).elasticsearch.client;
const [mlClient, indices] = await Promise.all([
getMlClient(resources),
getApmIndices({
savedObjectsClient: coreContext.savedObjects.client,
config,
}),
getApmIndices(),
]);
if (!isActivePlatinumLicense(licensingContext.license)) {
@ -142,9 +137,9 @@ const anomalyDetectionUpdateToV3Route = createApmServerRoute({
],
},
handler: async (resources): Promise<{ update: boolean }> => {
const { config, context } = resources;
const coreContext = await context.core;
const [mlClient, esClient, indices] = await Promise.all([
const { getApmIndices } = resources;
const [indices, mlClient, esClient] = await Promise.all([
getApmIndices(),
getMlClient(resources),
resources.core
.start()
@ -152,10 +147,6 @@ const anomalyDetectionUpdateToV3Route = createApmServerRoute({
(start): ElasticsearchClient =>
start.elasticsearch.client.asInternalUser
),
getApmIndices({
config,
savedObjectsClient: coreContext.savedObjects.client,
}),
]);
const { logger } = resources;

View file

@ -9,11 +9,11 @@ import { uniq } from 'lodash';
import pLimit from 'p-limit';
import { ElasticsearchClient } from '@kbn/core/server';
import { JOB_STATE } from '@kbn/ml-plugin/common';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { createAnomalyDetectionJobs } from '../../../lib/anomaly_detection/create_anomaly_detection_jobs';
import { getAnomalyDetectionJobs } from '../../../lib/anomaly_detection/get_anomaly_detection_jobs';
import { MlClient } from '../../../lib/helpers/get_ml_client';
import { withApmSpan } from '../../../utils/with_apm_span';
import { ApmIndicesConfig } from '../apm_indices/get_apm_indices';
export async function updateToV3({
logger,
@ -23,7 +23,7 @@ export async function updateToV3({
}: {
logger: Logger;
mlClient?: MlClient;
indices: ApmIndicesConfig;
indices: APMIndices;
esClient: ElasticsearchClient;
}) {
const allJobs = await getAnomalyDetectionJobs(mlClient);

View file

@ -0,0 +1,10 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export const APM_AGENT_CONFIGURATION_INDEX = '.apm-agent-configuration';
export const APM_CUSTOM_LINK_INDEX = '.apm-custom-link';
export const APM_SOURCE_MAP_INDEX = '.apm-source-map';

View file

@ -5,71 +5,8 @@
* 2.0.
*/
import { SavedObjectsClient } from '@kbn/core/server';
import {
APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
APM_INDEX_SETTINGS_SAVED_OBJECT_ID,
} from '../../../../common/apm_saved_object_constants';
import { APMConfig } from '../../..';
import { APMRouteHandlerResources } from '../../typings';
import { withApmSpan } from '../../../utils/with_apm_span';
import { APMIndices } from '../../../saved_objects/apm_indices';
export type ApmIndicesConfig = Readonly<{
error: string;
onboarding: string;
span: string;
transaction: string;
metric: string;
}>;
export const APM_AGENT_CONFIGURATION_INDEX = '.apm-agent-configuration';
export const APM_CUSTOM_LINK_INDEX = '.apm-custom-link';
export const APM_SOURCE_MAP_INDEX = '.apm-source-map';
type ISavedObjectsClient = Pick<SavedObjectsClient, 'get'>;
async function getApmIndicesSavedObject(
savedObjectsClient: ISavedObjectsClient
) {
const apmIndicesSavedObject = await withApmSpan(
'get_apm_indices_saved_object',
() =>
savedObjectsClient.get<Partial<APMIndices>>(
APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
APM_INDEX_SETTINGS_SAVED_OBJECT_ID
)
);
return apmIndicesSavedObject.attributes.apmIndices;
}
export function getApmIndicesConfig(config: APMConfig): ApmIndicesConfig {
return {
error: config.indices.error,
onboarding: config.indices.onboarding,
span: config.indices.span,
transaction: config.indices.transaction,
metric: config.indices.metric,
};
}
export async function getApmIndices({
config,
savedObjectsClient,
}: {
config: APMConfig;
savedObjectsClient: ISavedObjectsClient;
}): Promise<ApmIndicesConfig> {
try {
const apmIndicesSavedObject = await getApmIndicesSavedObject(
savedObjectsClient
);
const apmIndicesConfig = getApmIndicesConfig(config);
return { ...apmIndicesConfig, ...apmIndicesSavedObject };
} catch (error) {
return getApmIndicesConfig(config);
}
}
import { getApmIndicesSavedObject } from '@kbn/apm-data-access-plugin/server/saved_objects/apm_indices';
import { APMRouteHandlerResources } from '../../apm_routes/register_apm_server_routes';
export type ApmIndexSettingsResponse = Array<{
configurationName: 'transaction' | 'span' | 'error' | 'metric' | 'onboarding';
@ -77,35 +14,21 @@ export type ApmIndexSettingsResponse = Array<{
savedValue: string | undefined;
}>;
export async function getApmIndexSettings({
context,
config,
}: Pick<
APMRouteHandlerResources,
'context' | 'config'
>): Promise<ApmIndexSettingsResponse> {
let apmIndicesSavedObject: Awaited<
ReturnType<typeof getApmIndicesSavedObject>
>;
try {
const soClient = (await context.core).savedObjects.client;
apmIndicesSavedObject = await getApmIndicesSavedObject(soClient);
} catch (error: any) {
if (error.output && error.output.statusCode === 404) {
apmIndicesSavedObject = {};
} else {
throw error;
}
}
const apmIndicesConfig = getApmIndicesConfig(config);
export async function getApmIndexSettings(
resources: APMRouteHandlerResources
): Promise<ApmIndexSettingsResponse> {
const { apmIndicesFromConfigFile } = resources.plugins.apmDataAccess.setup;
const apmIndices = Object.keys(config.indices) as Array<
keyof typeof config.indices
const soClient = (await resources.context.core).savedObjects.client;
const apmIndicesSavedObject = await getApmIndicesSavedObject(soClient);
const apmIndicesKeys = Object.keys(apmIndicesFromConfigFile) as Array<
keyof typeof apmIndicesFromConfigFile
>;
return apmIndices.map((configurationName) => ({
return apmIndicesKeys.map((configurationName) => ({
configurationName,
defaultValue: apmIndicesConfig[configurationName], // value defined in kibana[.dev].yml
defaultValue: apmIndicesFromConfigFile[configurationName], // value defined in kibana[.dev].yml
savedValue: apmIndicesSavedObject?.[configurationName], // value saved via Saved Objects service
}));
}

View file

@ -7,27 +7,24 @@
import * as t from 'io-ts';
import { SavedObject } from '@kbn/core/server';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { createApmServerRoute } from '../../apm_routes/create_apm_server_route';
import {
getApmIndices,
getApmIndexSettings,
ApmIndexSettingsResponse,
ApmIndicesConfig,
} from './get_apm_indices';
import { saveApmIndices } from './save_apm_indices';
import { APMConfig } from '../../..';
// get list of apm indices and values
const apmIndexSettingsRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/settings/apm-index-settings',
options: { tags: ['access:apm'] },
handler: async ({
config,
context,
}): Promise<{
handler: async (
resources
): Promise<{
apmIndexSettings: ApmIndexSettingsResponse;
}> => {
const apmIndexSettings = await getApmIndexSettings({ config, context });
const apmIndexSettings = await getApmIndexSettings(resources);
return { apmIndexSettings };
},
});
@ -36,18 +33,13 @@ const apmIndexSettingsRoute = createApmServerRoute({
const apmIndicesRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/settings/apm-indices',
options: { tags: ['access:apm'] },
handler: async (resources): Promise<ApmIndicesConfig> => {
const { context, config } = resources;
const savedObjectsClient = (await context.core).savedObjects.client;
return await getApmIndices({
savedObjectsClient,
config,
});
handler: async (resources): Promise<APMIndices> => {
return await resources.getApmIndices();
},
});
type SaveApmIndicesBodySchema = {
[Property in keyof APMConfig['indices']]: t.StringC;
[Property in keyof APMIndices]: t.StringC;
};
// save ui indices

View file

@ -6,20 +6,20 @@
*/
import { SavedObjectsClientContract } from '@kbn/core/server';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import {
APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
APMIndicesSavedObjectBody,
APM_INDEX_SETTINGS_SAVED_OBJECT_ID,
} from '../../../../common/apm_saved_object_constants';
import { APMIndices } from '../../../saved_objects/apm_indices';
APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
} from '@kbn/apm-data-access-plugin/server/saved_objects/apm_indices';
import { withApmSpan } from '../../../utils/with_apm_span';
import { ApmIndicesConfig } from './get_apm_indices';
export function saveApmIndices(
savedObjectsClient: SavedObjectsClientContract,
apmIndices: Partial<ApmIndicesConfig>
apmIndices: Partial<APMIndices>
) {
return withApmSpan('save_apm_indices', () =>
savedObjectsClient.create<APMIndices>(
savedObjectsClient.create<APMIndicesSavedObjectBody>(
APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
{ apmIndices: removeEmpty(apmIndices), isSpaceAware: true },
{ id: APM_INDEX_SETTINGS_SAVED_OBJECT_ID, overwrite: true }
@ -28,7 +28,7 @@ export function saveApmIndices(
}
// remove empty/undefined values
function removeEmpty(apmIndices: Partial<ApmIndicesConfig>) {
function removeEmpty(apmIndices: Partial<APMIndices>) {
return Object.entries(apmIndices)
.map(([key, value]) => [key, value?.trim()])
.filter(([_, value]) => !!value)

View file

@ -11,7 +11,7 @@ import {
createOrUpdateIndex,
Mappings,
} from '@kbn/observability-plugin/server';
import { APM_CUSTOM_LINK_INDEX } from '../apm_indices/get_apm_indices';
import { APM_CUSTOM_LINK_INDEX } from '../apm_indices/apm_system_index_constants';
export const createApmCustomLinkIndex = async ({
client,

View file

@ -14,7 +14,7 @@ import {
APMIndexDocumentParams,
APMInternalESClient,
} from '../../../lib/helpers/create_es_client/create_internal_es_client';
import { APM_CUSTOM_LINK_INDEX } from '../apm_indices/get_apm_indices';
import { APM_CUSTOM_LINK_INDEX } from '../apm_indices/apm_system_index_constants';
export function createOrUpdateCustomLink({
customLinkId,

View file

@ -6,7 +6,7 @@
*/
import { APMInternalESClient } from '../../../lib/helpers/create_es_client/create_internal_es_client';
import { APM_CUSTOM_LINK_INDEX } from '../apm_indices/get_apm_indices';
import { APM_CUSTOM_LINK_INDEX } from '../apm_indices/apm_system_index_constants';
export function deleteCustomLink({
customLinkId,

View file

@ -14,7 +14,7 @@ import {
import { fromESFormat } from './helper';
import { filterOptionsRt } from './custom_link_types';
import { APMInternalESClient } from '../../../lib/helpers/create_es_client/create_internal_es_client';
import { APM_CUSTOM_LINK_INDEX } from '../apm_indices/get_apm_indices';
import { APM_CUSTOM_LINK_INDEX } from '../apm_indices/apm_system_index_constants';
export async function listCustomLinks({
internalESClient,

View file

@ -50,8 +50,9 @@ const listCustomLinksRoute = createApmServerRoute({
): Promise<{
customLinks: CustomLink[];
}> => {
const { context, params, request, config } = resources;
const { context, params, request } = resources;
const licensingContext = await context.licensing;
const apmIndices = await resources.getApmIndices();
if (!isActiveGoldLicense(licensingContext.license)) {
throw Boom.forbidden(INVALID_LICENSE);
@ -63,7 +64,7 @@ const listCustomLinksRoute = createApmServerRoute({
context,
request,
debug: resources.params.query._inspect,
config,
apmIndices,
});
// picks only the items listed in FILTER_OPTIONS
@ -83,8 +84,9 @@ const createCustomLinkRoute = createApmServerRoute({
}),
options: { tags: ['access:apm', 'access:apm_write'] },
handler: async (resources): Promise<void> => {
const { context, params, request, config } = resources;
const { context, params, request } = resources;
const licensingContext = await context.licensing;
const apmIndices = await resources.getApmIndices();
if (!isActiveGoldLicense(licensingContext.license)) {
throw Boom.forbidden(INVALID_LICENSE);
@ -94,7 +96,7 @@ const createCustomLinkRoute = createApmServerRoute({
context,
request,
debug: resources.params.query._inspect,
config,
apmIndices,
});
const customLink = params.body;
@ -119,8 +121,9 @@ const updateCustomLinkRoute = createApmServerRoute({
tags: ['access:apm', 'access:apm_write'],
},
handler: async (resources): Promise<void> => {
const { params, context, request, config } = resources;
const { params, context, request } = resources;
const licensingContext = await context.licensing;
const apmIndices = await resources.getApmIndices();
if (!isActiveGoldLicense(licensingContext.license)) {
throw Boom.forbidden(INVALID_LICENSE);
@ -130,7 +133,7 @@ const updateCustomLinkRoute = createApmServerRoute({
context,
request,
debug: resources.params.query._inspect,
config,
apmIndices,
});
const { id } = params.path;
@ -155,8 +158,9 @@ const deleteCustomLinkRoute = createApmServerRoute({
tags: ['access:apm', 'access:apm_write'],
},
handler: async (resources): Promise<{ result: string }> => {
const { context, params, request, config } = resources;
const { context, params, request } = resources;
const licensingContext = await context.licensing;
const apmIndices = await resources.getApmIndices();
if (!isActiveGoldLicense(licensingContext.license)) {
throw Boom.forbidden(INVALID_LICENSE);
@ -166,7 +170,7 @@ const deleteCustomLinkRoute = createApmServerRoute({
context,
request,
debug: resources.params.query._inspect,
config,
apmIndices,
});
const { id } = params.path;
const res = await deleteCustomLink({

View file

@ -8,7 +8,7 @@
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { Artifact } from '@kbn/fleet-plugin/server';
import { getUnzippedArtifactBody } from '../fleet/source_maps';
import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/get_apm_indices';
import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/apm_system_index_constants';
import { ApmSourceMap } from './create_apm_source_map_index_template';
import { getEncodedSourceMapContent, getSourceMapId } from './sourcemap_utils';

View file

@ -7,7 +7,7 @@
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { Logger } from '@kbn/core/server';
import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/get_apm_indices';
import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/apm_system_index_constants';
import { ApmSourceMap } from './create_apm_source_map_index_template';
import { SourceMap } from './route';
import {

View file

@ -8,7 +8,7 @@
import { IndicesPutIndexTemplateRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { ElasticsearchClient, Logger } from '@kbn/core/server';
import { createOrUpdateIndexTemplate } from '@kbn/observability-plugin/server';
import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/get_apm_indices';
import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/apm_system_index_constants';
const indexTemplate: IndicesPutIndexTemplateRequest = {
name: 'apm-source-map',

View file

@ -6,7 +6,7 @@
*/
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/get_apm_indices';
import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/apm_system_index_constants';
export async function deleteApmSourceMap({
internalESClient,

View file

@ -12,7 +12,7 @@ import { TaskManagerSetupContract } from '@kbn/task-manager-plugin/server';
import { CoreStart, Logger } from '@kbn/core/server';
import { getApmArtifactClient } from '../fleet/source_maps';
import { bulkCreateApmSourceMaps } from './bulk_create_apm_source_maps';
import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/get_apm_indices';
import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/apm_system_index_constants';
import { ApmSourceMap } from './create_apm_source_map_index_template';
import { APMPluginStartDependencies } from '../../types';
import { createApmSourceMapIndexTemplate } from './create_apm_source_map_index_template';

View file

@ -6,7 +6,7 @@
*/
import { isCrossClusterSearch } from './is_cross_cluster_search';
import { ApmIndicesConfig } from '@kbn/observability-plugin/common/typings';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { APMEventClient } from '../../lib/helpers/create_es_client/create_apm_event_client';
describe('isCrossClusterSearch', () => {
@ -17,7 +17,7 @@ describe('isCrossClusterSearch', () => {
span: 'traces-apm*',
metric: 'metrics-apm*',
error: 'logs-apm*',
} as ApmIndicesConfig,
} as APMIndices,
} as unknown as APMEventClient;
expect(isCrossClusterSearch(mockApmEventClient)).toBe(false);
@ -30,7 +30,7 @@ describe('isCrossClusterSearch', () => {
span: 'traces-apm*,test-apm*',
metric: 'metrics-apm*,test-apm*',
error: 'logs-apm*,test-apm*',
} as ApmIndicesConfig,
} as APMIndices,
} as unknown as APMEventClient;
expect(isCrossClusterSearch(mockApmEventClient)).toBe(false);
@ -44,7 +44,7 @@ describe('isCrossClusterSearch', () => {
metric: '',
error: '',
onboarding: 'apm-*,remote_cluster:apm-*',
} as ApmIndicesConfig,
} as APMIndices,
} as unknown as APMEventClient;
expect(isCrossClusterSearch(mockApmEventClient)).toBe(false);
@ -57,7 +57,7 @@ describe('isCrossClusterSearch', () => {
span: '',
metric: '',
error: '',
} as ApmIndicesConfig,
} as APMIndices,
} as unknown as APMEventClient;
expect(isCrossClusterSearch(mockApmEventClient)).toBe(true);
@ -70,7 +70,7 @@ describe('isCrossClusterSearch', () => {
span: 'traces-apm*,remote_cluster:traces-apm*',
metric: '',
error: '',
} as ApmIndicesConfig,
} as APMIndices,
} as unknown as APMEventClient;
expect(isCrossClusterSearch(mockApmEventClient)).toBe(true);
@ -83,7 +83,7 @@ describe('isCrossClusterSearch', () => {
span: '',
metric: 'metrics-apm*,remote_cluster:metrics-apm*',
error: '',
} as ApmIndicesConfig,
} as APMIndices,
} as unknown as APMEventClient;
expect(isCrossClusterSearch(mockApmEventClient)).toBe(true);
@ -96,7 +96,7 @@ describe('isCrossClusterSearch', () => {
span: '',
metric: '',
error: 'logs-apm*,remote_cluster:logs-apm*',
} as ApmIndicesConfig,
} as APMIndices,
} as unknown as APMEventClient;
expect(isCrossClusterSearch(mockApmEventClient)).toBe(true);

View file

@ -8,22 +8,13 @@
import {
CoreSetup,
CustomRequestHandlerContext,
Logger,
KibanaRequest,
CoreStart,
RouteConfigOptions,
} from '@kbn/core/server';
import { IRuleDataClient } from '@kbn/rule-registry-plugin/server';
import { AlertingApiRequestHandlerContext } from '@kbn/alerting-plugin/server';
import type { RacApiRequestHandlerContext } from '@kbn/rule-registry-plugin/server';
import { LicensingApiRequestHandlerContext } from '@kbn/licensing-plugin/server';
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server';
import { APMConfig } from '..';
import {
APMPluginSetupDependencies,
APMPluginStartDependencies,
} from '../types';
import { ApmFeatureFlags } from '../../common/apm_feature_flags';
export type ApmPluginRequestHandlerContext = CustomRequestHandlerContext<{
licensing: LicensingApiRequestHandlerContext;
@ -54,26 +45,3 @@ export interface APMCore {
setup: CoreSetup;
start: () => Promise<CoreStart>;
}
export interface APMRouteHandlerResources {
request: KibanaRequest;
context: ApmPluginRequestHandlerContext;
params: {
query: {
_inspect: boolean;
};
};
config: APMConfig;
featureFlags: ApmFeatureFlags;
logger: Logger;
core: APMCore;
plugins: {
[key in keyof APMPluginSetupDependencies]: {
setup: Required<APMPluginSetupDependencies>[key];
start: () => Promise<Required<APMPluginStartDependencies>[key]>;
};
};
ruleDataClient: IRuleDataClient;
telemetryUsageCounter?: TelemetryUsageCounter;
kibanaVersion: string;
}

View file

@ -5,7 +5,6 @@
* 2.0.
*/
export { apmIndices } from './apm_indices';
export { apmTelemetry } from './apm_telemetry';
export { apmServerSettings } from './apm_server_settings';
export { apmServiceGroups } from './apm_service_groups';

View file

@ -11,8 +11,8 @@ import {
TutorialSchema,
InstructionSetSchema,
} from '@kbn/home-plugin/server';
import { CloudSetup } from '@kbn/cloud-plugin/server';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import {
createNodeAgentInstructions,
createDjangoAgentInstructions,
@ -26,16 +26,15 @@ import {
createPhpAgentInstructions,
createOpenTelemetryAgentInstructions,
} from '../../../common/tutorial/instructions/apm_agent_instructions';
import { APMConfig } from '../..';
import { getOnPremApmServerInstructionSet } from './on_prem_apm_server_instruction_set';
export function createElasticCloudInstructions({
cloudSetup,
apmConfig,
apmIndices,
isFleetPluginEnabled,
}: {
cloudSetup?: CloudSetup;
apmConfig: APMConfig;
apmIndices: APMIndices;
isFleetPluginEnabled: boolean;
}): TutorialSchema['elasticCloud'] {
const apmServerUrl = cloudSetup?.apm.url;
@ -46,7 +45,7 @@ export function createElasticCloudInstructions({
}
instructionSets.push(
getOnPremApmServerInstructionSet({ apmConfig, isFleetPluginEnabled })
getOnPremApmServerInstructionSet({ apmIndices, isFleetPluginEnabled })
);
instructionSets.push(getApmAgentInstructionSet(cloudSetup));

View file

@ -10,7 +10,7 @@ import {
INSTRUCTION_VARIANT,
InstructionsSchema,
} from '@kbn/home-plugin/server';
import { APMConfig } from '../..';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import {
createDjangoAgentInstructions,
createDotNetAgentInstructions,
@ -27,15 +27,18 @@ import {
import { getOnPremApmServerInstructionSet } from './on_prem_apm_server_instruction_set';
export function onPremInstructions({
apmConfig,
apmIndices,
isFleetPluginEnabled,
}: {
apmConfig: APMConfig;
apmIndices: APMIndices;
isFleetPluginEnabled: boolean;
}): InstructionsSchema {
return {
instructionSets: [
getOnPremApmServerInstructionSet({ apmConfig, isFleetPluginEnabled }),
getOnPremApmServerInstructionSet({
apmIndices,
isFleetPluginEnabled,
}),
{
title: i18n.translate('xpack.apm.tutorial.apmAgents.title', {
defaultMessage: 'APM Agents',
@ -121,9 +124,9 @@ export function onPremInstructions({
),
esHitsCheck: {
index: [
apmConfig.indices.error,
apmConfig.indices.transaction,
apmConfig.indices.metric,
apmIndices.error,
apmIndices.transaction,
apmIndices.metric,
],
query: {
bool: {

View file

@ -10,7 +10,7 @@ import {
InstructionsSchema,
INSTRUCTION_VARIANT,
} from '@kbn/home-plugin/server';
import { APMConfig } from '../..';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import {
createDownloadServerDeb,
createDownloadServerOsx,
@ -29,10 +29,10 @@ const START_SERVER_UNIX_SYSV = createStartServerUnixSysv();
const START_SERVER_UNIX_BINARI = createStartServerUnixBinari();
export function getOnPremApmServerInstructionSet({
apmConfig,
apmIndices,
isFleetPluginEnabled,
}: {
apmConfig: APMConfig;
apmIndices: APMIndices;
isFleetPluginEnabled: boolean;
}): InstructionsSchema['instructionSets'][0] {
return {
@ -132,7 +132,7 @@ export function getOnPremApmServerInstructionSet({
}
),
esHitsCheck: {
index: apmConfig.indices.onboarding,
index: apmIndices.onboarding,
query: {
bool: {
filter: [{ term: { 'processor.event': 'onboarding' } }],

View file

@ -12,8 +12,8 @@ import {
TutorialSchema,
} from '@kbn/home-plugin/server';
import { CloudSetup } from '@kbn/cloud-plugin/server';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { APMConfig } from '..';
import { ApmIndicesConfig } from '../routes/settings/apm_indices/get_apm_indices';
import { createElasticCloudInstructions } from './envs/elastic_cloud';
import { onPremInstructions } from './envs/on_prem';
@ -31,7 +31,7 @@ export const tutorialProvider =
isFleetPluginEnabled,
}: {
apmConfig: APMConfig;
apmIndices: ApmIndicesConfig;
apmIndices: APMIndices;
cloud?: CloudSetup;
isFleetPluginEnabled: boolean;
}) =>
@ -90,9 +90,9 @@ It allows you to monitor the performance of thousands of applications in real ti
integrationBrowserCategories: ['observability', 'apm'],
artifacts,
customStatusCheckName: 'apm_fleet_server_status_check',
onPrem: onPremInstructions({ apmConfig, isFleetPluginEnabled }),
onPrem: onPremInstructions({ apmIndices, isFleetPluginEnabled }),
elasticCloud: createElasticCloudInstructions({
apmConfig,
apmIndices,
isFleetPluginEnabled,
cloudSetup: cloud,
}),

View file

@ -7,7 +7,6 @@
import { SharePluginSetup } from '@kbn/share-plugin/server';
import { Observable } from 'rxjs';
import { KibanaRequest } from '@kbn/core/server';
import {
RuleRegistryPluginSetupContract,
RuleRegistryPluginStartContract,
@ -16,6 +15,11 @@ import {
PluginSetup as DataPluginSetup,
PluginStart as DataPluginStart,
} from '@kbn/data-plugin/server';
import {
ApmDataAccessPluginSetup,
ApmDataAccessPluginStart,
} from '@kbn/apm-data-access-plugin/server';
import {
SpacesPluginSetup,
SpacesPluginStart,
@ -58,22 +62,14 @@ import {
CustomIntegrationsPluginStart,
} from '@kbn/custom-integrations-plugin/server';
import { APMConfig } from '.';
import { ApmIndicesConfig } from './routes/settings/apm_indices/get_apm_indices';
import { APMEventClient } from './lib/helpers/create_es_client/create_apm_event_client';
import { ApmPluginRequestHandlerContext } from './routes/typings';
export interface APMPluginSetup {
config$: Observable<APMConfig>;
getApmIndices: () => Promise<ApmIndicesConfig>;
createApmEventClient: (params: {
debug?: boolean;
request: KibanaRequest;
context: ApmPluginRequestHandlerContext;
}) => Promise<APMEventClient>;
}
export interface APMPluginSetupDependencies {
// required dependencies
apmDataAccess: ApmDataAccessPluginSetup;
data: DataPluginSetup;
features: FeaturesPluginSetup;
licensing: LicensingPluginSetup;
@ -98,6 +94,7 @@ export interface APMPluginSetupDependencies {
}
export interface APMPluginStartDependencies {
// required dependencies
apmDataAccess: ApmDataAccessPluginStart;
data: DataPluginStart;
features: FeaturesPluginStart;
licensing: LicensingPluginStart;

View file

@ -6,11 +6,11 @@
*/
import type { ESSearchRequest, ESSearchResponse } from '@kbn/es-types';
import type { APMIndices } from '@kbn/apm-data-access-plugin/server';
import { APMConfig } from '..';
import { APMEventClient } from '../lib/helpers/create_es_client/create_apm_event_client';
import { APMInternalESClient } from '../lib/helpers/create_es_client/create_internal_es_client';
import { ApmAlertsClient } from '../lib/helpers/get_apm_alerts_client';
import { ApmIndicesConfig } from '../routes/settings/apm_indices/get_apm_indices';
interface Options {
mockResponse?: (
@ -30,7 +30,7 @@ export async function inspectSearchParams(
mockApmEventClient: APMEventClient;
mockConfig: APMConfig;
mockInternalESClient: APMInternalESClient;
mockIndices: ApmIndicesConfig;
mockIndices: APMIndices;
mockApmAlertsClient: ApmAlertsClient;
}) => Promise<any>,
options: Options = {}
@ -53,7 +53,7 @@ export async function inspectSearchParams(
let error;
const mockApmEventClient = { search: spy } as any;
const indices: {
[Property in keyof APMConfig['indices']]: string;
[Property in keyof APMIndices]: string;
} = {
error: 'myIndex',
onboarding: 'myIndex',
@ -61,6 +61,7 @@ export async function inspectSearchParams(
transaction: 'myIndex',
metric: 'myIndex',
};
const mockConfig = new Proxy(
{},
{
@ -73,8 +74,6 @@ export async function inspectSearchParams(
switch (key) {
default:
return 'myIndex';
case 'indices':
return indices;
case 'ui':
return {
enabled: true,

View file

@ -76,7 +76,6 @@
"@kbn/babel-register",
"@kbn/core-saved-objects-migration-server-internal",
"@kbn/core-elasticsearch-server",
"@kbn/core-saved-objects-api-server",
"@kbn/safer-lodash-set",
"@kbn/shared-ux-router",
"@kbn/alerts-as-data-utils",
@ -96,7 +95,8 @@
"@kbn/logs-shared-plugin",
"@kbn/unified-field-list",
"@kbn/discover-plugin",
"@kbn/observability-ai-assistant-plugin"
"@kbn/observability-ai-assistant-plugin",
"@kbn/apm-data-access-plugin"
],
"exclude": ["target/**/*"]
}

View file

@ -0,0 +1,9 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export const PLUGIN_ID = 'apmDataAccess';
export const PLUGIN_NAME = 'apmDataAccess';

View file

@ -0,0 +1,14 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
const path = require('path');
module.exports = {
preset: '@kbn/test',
rootDir: path.resolve(__dirname, '../../..'),
roots: ['<rootDir>/x-pack/plugins/apm_data_access'],
};

View file

@ -0,0 +1,14 @@
{
"type": "plugin",
"id": "@kbn/apm-data-access-plugin",
"owner": "@elastic/apm-ui",
"plugin": {
"id": "apmDataAccess",
"server": true,
"browser": false,
"configPath": ["xpack", "apm_data_access"],
"requiredPlugins": ["data"],
"optionalPlugins": [],
"requiredBundles": []
}
}

View file

@ -0,0 +1,80 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server';
import { ApmDataAccessPlugin } from './plugin';
const configSchema = schema.object({
indices: schema.object({
transaction: schema.string({ defaultValue: 'traces-apm*,apm-*' }), // TODO: remove apm-* pattern in 9.0
span: schema.string({ defaultValue: 'traces-apm*,apm-*' }),
error: schema.string({ defaultValue: 'logs-apm*,apm-*' }),
metric: schema.string({ defaultValue: 'metrics-apm*,apm-*' }),
onboarding: schema.string({ defaultValue: 'apm-*' }), // Unused: to be deleted
}),
});
// plugin config
export const config: PluginConfigDescriptor<APMDataAccessConfig> = {
deprecations: ({ renameFromRoot, unused, deprecate }) => [
// deprecations
unused('indices.sourcemap', { level: 'warning' }),
deprecate('indices.onboarding', 'a future version', {
level: 'warning',
message: `Configuring "xpack.apm.indices.onboarding" is deprecated and will be removed in a future version. Please remove this setting.`,
}),
// deprecations due to removal of apm_oss plugin
renameFromRoot('apm_oss.transactionIndices', 'xpack.apm.indices.transaction', {
level: 'warning',
}),
renameFromRoot('apm_oss.spanIndices', 'xpack.apm.indices.span', {
level: 'warning',
}),
renameFromRoot('apm_oss.errorIndices', 'xpack.apm.indices.error', {
level: 'warning',
}),
renameFromRoot('apm_oss.metricsIndices', 'xpack.apm.indices.metric', {
level: 'warning',
}),
renameFromRoot('apm_oss.onboardingIndices', 'xpack.apm.indices.onboarding', {
level: 'warning',
}),
// rename from apm to apm_data_access plugin
renameFromRoot('xpack.apm.indices.transaction', 'xpack.apm_data_access.indices.transaction', {
level: 'warning',
silent: true,
}),
renameFromRoot('xpack.apm.indices.span', 'xpack.apm_data_access.indices.span', {
level: 'warning',
}),
renameFromRoot('xpack.apm.indices.error', 'xpack.apm_data_access.indices.error', {
level: 'warning',
}),
renameFromRoot('xpack.apm.indices.metric', 'xpack.apm_data_access.indices.metric', {
level: 'warning',
}),
renameFromRoot('xpack.apm.indices.sourcemap', 'xpack.apm_data_access.indices.sourcemap', {
level: 'warning',
}),
renameFromRoot('xpack.apm.indices.onboarding', 'xpack.apm_data_access.indices.onboarding', {
level: 'warning',
}),
],
schema: configSchema,
};
export type APMDataAccessConfig = TypeOf<typeof configSchema>;
export type APMIndices = APMDataAccessConfig['indices'];
export function plugin(initializerContext: PluginInitializerContext) {
return new ApmDataAccessPlugin(initializerContext);
}
export type { ApmDataAccessPluginSetup, ApmDataAccessPluginStart } from './types';

View file

@ -0,0 +1,59 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import {
PluginInitializerContext,
CoreSetup,
CoreStart,
Plugin,
SavedObjectsClientContract,
} from '@kbn/core/server';
import { APMDataAccessConfig } from '.';
import { ApmDataAccessPluginSetup, ApmDataAccessPluginStart } from './types';
import { migrateLegacyAPMIndicesToSpaceAware } from './saved_objects/migrations/migrate_legacy_apm_indices_to_space_aware';
import {
apmIndicesSavedObjectDefinition,
getApmIndicesSavedObject,
} from './saved_objects/apm_indices';
export class ApmDataAccessPlugin
implements Plugin<ApmDataAccessPluginSetup, ApmDataAccessPluginStart>
{
constructor(private readonly initContext: PluginInitializerContext) {
this.initContext = initContext;
}
public setup(core: CoreSetup): ApmDataAccessPluginSetup {
// retrieve APM indices from config
const apmDataAccessConfig = this.initContext.config.get<APMDataAccessConfig>();
const apmIndicesFromConfigFile = apmDataAccessConfig.indices;
// register saved object
core.savedObjects.registerType(apmIndicesSavedObjectDefinition);
// expose
return {
apmIndicesFromConfigFile,
getApmIndices: async (savedObjectsClient: SavedObjectsClientContract) => {
const apmIndicesFromSavedObject = await getApmIndicesSavedObject(savedObjectsClient);
return { ...apmIndicesFromConfigFile, ...apmIndicesFromSavedObject };
},
};
}
public start(core: CoreStart) {
const logger = this.initContext.logger.get();
// TODO: remove in 9.0
migrateLegacyAPMIndicesToSpaceAware({ coreStart: core, logger }).catch((e) => {
logger.error('Failed to run migration making APM indices space aware');
logger.error(e);
});
return {};
}
public stop() {}
}

View file

@ -8,9 +8,14 @@
import { SavedObjectsType } from '@kbn/core/server';
import { i18n } from '@kbn/i18n';
import { schema } from '@kbn/config-schema';
import { SavedObjectsErrorHelpers } from '@kbn/core/server';
import { SavedObjectsClientContract } from '@kbn/core/server';
import { updateApmOssIndexPaths } from './migrations/update_apm_oss_index_paths';
export interface APMIndices {
export const APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE = 'apm-indices';
export const APM_INDEX_SETTINGS_SAVED_OBJECT_ID = 'apm-indices';
export interface APMIndicesSavedObjectBody {
apmIndices?: {
error?: string;
onboarding?: string;
@ -21,8 +26,8 @@ export interface APMIndices {
isSpaceAware?: boolean;
}
export const apmIndices: SavedObjectsType = {
name: 'apm-indices',
export const apmIndicesSavedObjectDefinition: SavedObjectsType = {
name: APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
hidden: false,
namespaceType: 'single',
mappings: {
@ -33,7 +38,7 @@ export const apmIndices: SavedObjectsType = {
importableAndExportable: true,
icon: 'apmApp',
getTitle: () =>
i18n.translate('xpack.apm.apmSettings.index', {
i18n.translate('xpack.apmDataAccess.apmSettings.index', {
defaultMessage: 'APM Settings - Index',
}),
},
@ -67,3 +72,20 @@ export const apmIndices: SavedObjectsType = {
},
},
};
export async function getApmIndicesSavedObject(savedObjectsClient: SavedObjectsClientContract) {
try {
const apmIndicesSavedObject = await savedObjectsClient.get<Partial<APMIndicesSavedObjectBody>>(
APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE,
APM_INDEX_SETTINGS_SAVED_OBJECT_ID
);
return apmIndicesSavedObject.attributes.apmIndices;
} catch (error) {
// swallow error if saved object does not exist
if (SavedObjectsErrorHelpers.isNotFoundError(error)) {
return {};
}
throw error;
}
}

Some files were not shown because too many files have changed in this diff Show more