diff --git a/package.json b/package.json index df39dd8c65d7..983dddda5d4f 100644 --- a/package.json +++ b/package.json @@ -222,7 +222,7 @@ "deep-freeze-strict": "^1.1.1", "deepmerge": "^4.2.2", "del": "^5.1.0", - "elastic-apm-node": "^3.24.0", + "elastic-apm-node": "^3.25.0", "execa": "^4.0.2", "exit-hook": "^2.2.0", "expiry-js": "0.1.7", diff --git a/src/plugins/vis_types/timelion/common/types.ts b/src/plugins/vis_types/timelion/common/types.ts index 8ce4bd8b45f0..323539f69488 100644 --- a/src/plugins/vis_types/timelion/common/types.ts +++ b/src/plugins/vis_types/timelion/common/types.ts @@ -20,6 +20,7 @@ export interface TimelionFunctionArgs { multi?: boolean; types: TimelionFunctionArgsTypes[]; suggestions?: TimelionFunctionArgsSuggestion[]; + hidden?: boolean; } export interface ITimelionFunction { diff --git a/src/plugins/vis_types/timelion/public/components/timelion_expression_input_helpers.ts b/src/plugins/vis_types/timelion/public/components/timelion_expression_input_helpers.ts index 6c3cd8058627..676b5d91a803 100644 --- a/src/plugins/vis_types/timelion/public/components/timelion_expression_input_helpers.ts +++ b/src/plugins/vis_types/timelion/public/components/timelion_expression_input_helpers.ts @@ -42,7 +42,7 @@ function getArgumentsHelp( // ignore arguments that are already provided in function declaration const functionArgNames = functionArgs.map((arg) => arg.name); - return argsHelp.filter((arg) => !functionArgNames.includes(arg.name)); + return argsHelp.filter((arg) => !arg.hidden && !functionArgNames.includes(arg.name)); } async function extractSuggestionsFromParsedResult( diff --git a/src/plugins/vis_types/timelion/server/lib/classes/datasource.js b/src/plugins/vis_types/timelion/server/lib/classes/datasource.js index f0af22793c98..50129494bf84 100644 --- a/src/plugins/vis_types/timelion/server/lib/classes/datasource.js +++ b/src/plugins/vis_types/timelion/server/lib/classes/datasource.js @@ -47,6 +47,7 @@ export default class Datasource extends TimelionFunction { fitFunctions: _.keys(fitFunctions).join(', '), }, }), + hidden: Boolean(config.hideFitArg), }); // Wrap the original function so we can modify inputs/outputs with offset & fit diff --git a/src/plugins/vis_types/timelion/server/series_functions/es/index.js b/src/plugins/vis_types/timelion/server/series_functions/es/index.js index 663d7714774c..d613818d7c3e 100644 --- a/src/plugins/vis_types/timelion/server/series_functions/es/index.js +++ b/src/plugins/vis_types/timelion/server/series_functions/es/index.js @@ -13,6 +13,7 @@ import buildRequest from './lib/build_request'; import toSeriesList from './lib/agg_response_to_series_list'; export default new Datasource('es', { + hideFitArg: true, args: [ { name: 'q', diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index 518d4582de2b..9458180fdd22 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -105,7 +105,7 @@ export class ActionExecutor { name: `execute_action`, type: 'actions', labels: { - actionId, + actions_connector_id: actionId, }, }, async (span) => { @@ -135,7 +135,7 @@ export class ActionExecutor { if (span) { span.name = `execute_action ${actionTypeId}`; span.addLabels({ - actionTypeId, + actions_connector_type_id: actionTypeId, }); } diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts index f651f41ef0c1..fe95ec646387 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import apm from 'elastic-apm-node'; import type { PublicMethodsOf } from '@kbn/utility-types'; import { Dictionary, pickBy, mapValues, without, cloneDeep } from 'lodash'; import type { Request } from '@hapi/hapi'; @@ -529,6 +529,17 @@ export class TaskRunner< // Ensure API key is still valid and user has access try { alert = await rulesClient.get({ id: alertId }); + + if (apm.currentTransaction) { + apm.currentTransaction.name = `Execute Alerting Rule: "${alert.name}"`; + apm.currentTransaction.addLabels({ + alerting_rule_consumer: alert.consumer, + alerting_rule_name: alert.name, + alerting_rule_tags: alert.tags.join(', '), + alerting_rule_type_id: alert.alertTypeId, + alerting_rule_params: JSON.stringify(alert.params), + }); + } } catch (err) { throw new ErrorWithReason(AlertExecutionStatusErrorReasons.Read, err); } @@ -560,6 +571,13 @@ export class TaskRunner< schedule: taskSchedule, } = this.taskInstance; + if (apm.currentTransaction) { + apm.currentTransaction.name = `Execute Alerting Rule`; + apm.currentTransaction.addLabels({ + alerting_rule_id: alertId, + }); + } + const runDate = new Date(); const runDateString = runDate.toISOString(); this.logger.debug(`executing alert ${this.alertType.id}:${alertId} at ${runDateString}`); @@ -615,6 +633,14 @@ export class TaskRunner< executionStatus.lastExecutionDate = new Date(event.event.start); } + if (apm.currentTransaction) { + if (executionStatus.status === 'ok' || executionStatus.status === 'active') { + apm.currentTransaction.setOutcome('success'); + } else if (executionStatus.status === 'error' || executionStatus.status === 'unknown') { + apm.currentTransaction.setOutcome('failure'); + } + } + this.logger.debug( `alertExecutionStatus for ${this.alertType.id}:${alertId}: ${JSON.stringify(executionStatus)}` ); @@ -855,6 +881,12 @@ function generateNewAndRecoveredInstanceEvents< const recoveredAlertInstanceIds = Object.keys(recoveredAlertInstances); const newIds = without(currentAlertInstanceIds, ...originalAlertInstanceIds); + if (apm.currentTransaction) { + apm.currentTransaction.addLabels({ + alerting_new_alerts: newIds.length, + }); + } + for (const id of recoveredAlertInstanceIds) { const { group: actionGroup, subgroup: actionSubgroup } = recoveredAlertInstances[id].getLastScheduledActions() ?? {}; @@ -1035,6 +1067,14 @@ function logActiveAndRecoveredInstances< const { logger, activeAlertInstances, recoveredAlertInstances, alertLabel } = params; const activeInstanceIds = Object.keys(activeAlertInstances); const recoveredInstanceIds = Object.keys(recoveredAlertInstances); + + if (apm.currentTransaction) { + apm.currentTransaction.addLabels({ + alerting_active_alerts: activeInstanceIds.length, + alerting_recovered_alerts: recoveredInstanceIds.length, + }); + } + if (activeInstanceIds.length > 0) { logger.debug( `alert ${alertLabel} has ${activeInstanceIds.length} active alert instances: ${JSON.stringify( diff --git a/x-pack/plugins/task_manager/server/task_scheduling.test.ts b/x-pack/plugins/task_manager/server/task_scheduling.test.ts index 41a172bfb2f8..f593363c53bc 100644 --- a/x-pack/plugins/task_manager/server/task_scheduling.test.ts +++ b/x-pack/plugins/task_manager/server/task_scheduling.test.ts @@ -35,6 +35,9 @@ jest.mock('uuid', () => ({ jest.mock('elastic-apm-node', () => ({ currentTraceparent: 'parent', + currentTransaction: { + type: 'taskManager run', + }, })); describe('TaskScheduling', () => { diff --git a/x-pack/plugins/task_manager/server/task_scheduling.ts b/x-pack/plugins/task_manager/server/task_scheduling.ts index a89f66d9c772..abf1ea0f50ed 100644 --- a/x-pack/plugins/task_manager/server/task_scheduling.ts +++ b/x-pack/plugins/task_manager/server/task_scheduling.ts @@ -99,9 +99,15 @@ export class TaskScheduling { ...options, taskInstance: ensureDeprecatedFieldsAreCorrected(taskInstance, this.logger), }); + + const traceparent = + agent.currentTransaction && agent.currentTransaction.type !== 'request' + ? agent.currentTraceparent + : ''; + return await this.store.schedule({ ...modifiedTask, - traceparent: agent.currentTraceparent ?? '', + traceparent: traceparent || '', }); } diff --git a/x-pack/plugins/uptime/common/constants/rest_api.ts b/x-pack/plugins/uptime/common/constants/rest_api.ts index 26b2c7aad20a..bef84c41796d 100644 --- a/x-pack/plugins/uptime/common/constants/rest_api.ts +++ b/x-pack/plugins/uptime/common/constants/rest_api.ts @@ -35,4 +35,7 @@ export enum API_URLS { DELETE_RULE = '/api/alerting/rule/', RULES_FIND = '/api/alerting/rules/_find', CONNECTOR_TYPES = '/api/actions/connector_types', + + // Service end points + INDEX_TEMPLATES = '/api/uptime/service/index_templates', } diff --git a/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts index bb8e413b7588..029c6164c048 100644 --- a/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts @@ -24,6 +24,7 @@ import { UptimeESClient } from '../../lib'; import type { UptimeRouter } from '../../../types'; import { SecurityPluginStart } from '../../../../../security/server'; import { CloudSetup } from '../../../../../cloud/server'; +import { FleetStartContract } from '../../../../../fleet/server'; import { UptimeConfig } from '../../../../common/config'; export type UMElasticsearchQueryFn = ( @@ -41,7 +42,8 @@ export type UMSavedObjectsQueryFn = ( export interface UptimeCoreSetup { router: UptimeRouter; config: UptimeConfig; - cloud: CloudSetup; + cloud?: CloudSetup; + fleet: FleetStartContract; security: SecurityPluginStart; encryptedSavedObjects: EncryptedSavedObjectsPluginStart; } @@ -59,6 +61,7 @@ export interface UptimeCorePluginsSetup { export interface UptimeCorePluginsStart { security: SecurityPluginStart; + fleet: FleetStartContract; encryptedSavedObjects: EncryptedSavedObjectsPluginStart; } diff --git a/x-pack/plugins/uptime/server/plugin.ts b/x-pack/plugins/uptime/server/plugin.ts index a94f9650e32c..427649725711 100644 --- a/x-pack/plugins/uptime/server/plugin.ts +++ b/x-pack/plugins/uptime/server/plugin.ts @@ -12,6 +12,7 @@ import { Plugin as PluginType, ISavedObjectsRepository, Logger, + SavedObjectsClient, } from '../../../../src/core/server'; import { uptimeRuleFieldMap } from '../common/rules/uptime_rule_field_map'; import { initServerWithKibana } from './kibana.index'; @@ -25,17 +26,19 @@ import { registerUptimeSavedObjects, savedObjectsAdapter } from './lib/saved_obj import { mappingFromFieldMap } from '../../rule_registry/common/mapping_from_field_map'; import { Dataset } from '../../rule_registry/server'; import { UptimeConfig } from '../common/config'; +import { installSyntheticsIndexTemplates } from './rest_api/synthetics_service/install_index_templates'; export type UptimeRuleRegistry = ReturnType['ruleRegistry']; export class Plugin implements PluginType { private savedObjectsClient?: ISavedObjectsRepository; private initContext: PluginInitializerContext; - private logger?: Logger; + private logger: Logger; private server?: UptimeCoreSetup; - constructor(_initializerContext: PluginInitializerContext) { - this.initContext = _initializerContext; + constructor(initializerContext: PluginInitializerContext) { + this.initContext = initializerContext; + this.logger = initializerContext.logger.get(); } public setup(core: CoreSetup, plugins: UptimeCorePluginsSetup) { @@ -60,8 +63,8 @@ export class Plugin implements PluginType { }); this.server = { - router: core.http.createRouter(), config, + router: core.http.createRouter(), cloud: plugins.cloud, } as UptimeCoreSetup; @@ -83,8 +86,29 @@ export class Plugin implements PluginType { this.savedObjectsClient = core.savedObjects.createInternalRepository(); if (this.server) { this.server.security = plugins.security; + this.server.fleet = plugins.fleet; this.server.encryptedSavedObjects = plugins.encryptedSavedObjects; } + + if (this.server?.config?.unsafe?.service.enabled) { + const esClient = core.elasticsearch.client.asInternalUser; + installSyntheticsIndexTemplates({ + esClient, + server: this.server, + savedObjectsClient: new SavedObjectsClient(core.savedObjects.createInternalRepository()), + }).then( + (result) => { + if (result.name === 'synthetics' && result.install_status === 'installed') { + this.logger.info('Installed synthetics index templates'); + } else if (result.name === 'synthetics' && result.install_status === 'install_failed') { + this.logger.warn('Failed to install synthetics index templates'); + } + }, + () => { + this.logger.warn('Failed to install synthetics index templates'); + } + ); + } } public stop() {} diff --git a/x-pack/plugins/uptime/server/rest_api/index.ts b/x-pack/plugins/uptime/server/rest_api/index.ts index d5aadf079931..344dd4d203d8 100644 --- a/x-pack/plugins/uptime/server/rest_api/index.ts +++ b/x-pack/plugins/uptime/server/rest_api/index.ts @@ -27,6 +27,7 @@ import { createGetIndexStatusRoute } from './index_state'; import { createNetworkEventsRoute } from './network_events'; import { createJourneyFailedStepsRoute } from './pings/journeys'; import { createLastSuccessfulStepRoute } from './synthetics/last_successful_step'; +import { installIndexTemplatesRoute } from './synthetics_service/install_index_templates'; export * from './types'; export { createRouteWithAuth } from './create_route_with_auth'; @@ -51,4 +52,5 @@ export const restApiRoutes: UMRestApiRouteFactory[] = [ createJourneyFailedStepsRoute, createLastSuccessfulStepRoute, createJourneyScreenshotBlocksRoute, + installIndexTemplatesRoute, ]; diff --git a/x-pack/plugins/uptime/server/rest_api/synthetics_service/install_index_templates.ts b/x-pack/plugins/uptime/server/rest_api/synthetics_service/install_index_templates.ts new file mode 100644 index 000000000000..b40c6018f966 --- /dev/null +++ b/x-pack/plugins/uptime/server/rest_api/synthetics_service/install_index_templates.ts @@ -0,0 +1,43 @@ +/* + * 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 { ElasticsearchClient, SavedObjectsClientContract } from 'kibana/server'; +import { UMRestApiRouteFactory } from '../types'; +import { API_URLS } from '../../../common/constants'; +import { UptimeCoreSetup } from '../../lib/adapters'; + +export const installIndexTemplatesRoute: UMRestApiRouteFactory = () => ({ + method: 'GET', + path: API_URLS.INDEX_TEMPLATES, + validate: {}, + handler: async ({ server, request, savedObjectsClient, uptimeEsClient }): Promise => { + return installSyntheticsIndexTemplates({ + server, + savedObjectsClient, + esClient: uptimeEsClient.baseESClient, + }); + }, +}); + +export async function installSyntheticsIndexTemplates({ + esClient, + server, + savedObjectsClient, +}: { + server: UptimeCoreSetup; + esClient: ElasticsearchClient; + savedObjectsClient: SavedObjectsClientContract; +}) { + // no need to add error handling here since fleetSetupCompleted is already wrapped in try/catch and will log + // warning if setup fails to complete + await server.fleet.fleetSetupCompleted(); + + return await server.fleet.packageService.ensureInstalledPackage({ + esClient, + savedObjectsClient, + pkgName: 'synthetics', + }); +} diff --git a/x-pack/test/api_integration/apis/search/search.ts b/x-pack/test/api_integration/apis/search/search.ts index 45e8933bf715..d36121a102a2 100644 --- a/x-pack/test/api_integration/apis/search/search.ts +++ b/x-pack/test/api_integration/apis/search/search.ts @@ -250,7 +250,8 @@ export default function ({ getService }: FtrProviderContext) { }); }); - describe('delete', () => { + // FLAKY: https://github.com/elastic/kibana/issues/119272 + describe.skip('delete', () => { it('should return 404 when no search id provided', async () => { await supertest.delete(`/internal/search/ese`).set('kbn-xsrf', 'foo').send().expect(404); }); diff --git a/x-pack/test/functional/apps/infra/home_page.ts b/x-pack/test/functional/apps/infra/home_page.ts index dfb5ba1cba4f..9c53ba20d38d 100644 --- a/x-pack/test/functional/apps/infra/home_page.ts +++ b/x-pack/test/functional/apps/infra/home_page.ts @@ -35,7 +35,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); }); - describe('with metrics present', () => { + // FLAKY: https://github.com/elastic/kibana/issues/119763 + describe.skip('with metrics present', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); await pageObjects.common.navigateToApp('infraOps'); diff --git a/x-pack/test/functional/apps/uptime/synthetics_integration.ts b/x-pack/test/functional/apps/uptime/synthetics_integration.ts index 9346867a0f1d..83fc3c407961 100644 --- a/x-pack/test/functional/apps/uptime/synthetics_integration.ts +++ b/x-pack/test/functional/apps/uptime/synthetics_integration.ts @@ -170,7 +170,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); }); - describe('create new policy', () => { + // FLAKY: https://github.com/elastic/kibana/issues/103390 + describe.skip('create new policy', () => { let version: string; beforeEach(async () => { diff --git a/yarn.lock b/yarn.lock index 3d1ab34b02f8..44185306ca38 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12407,10 +12407,10 @@ elastic-apm-http-client@^10.3.0: readable-stream "^3.4.0" stream-chopper "^3.0.1" -elastic-apm-node@^3.24.0: - version "3.24.0" - resolved "https://registry.yarnpkg.com/elastic-apm-node/-/elastic-apm-node-3.24.0.tgz#d7acb3352f928a23c28ebabab2bd30098562814e" - integrity sha512-Fmj/W2chWQa2zb1FfMYK2ypLB4TcnKNX+1klaJFbytRYDLgeSfo0EC7egvI3a+bLPZSRL5053PXOp7slVTPO6Q== +elastic-apm-node@^3.25.0: + version "3.25.0" + resolved "https://registry.yarnpkg.com/elastic-apm-node/-/elastic-apm-node-3.25.0.tgz#3207c936429739cd07f64cbf76d7b5b4b8e0da3e" + integrity sha512-3K+uUQkKeaJarjPb/pDY3fldP7QeppgPPx8nJOkOrW+BvQK5YBMiWbf4S9fdx0yUUkWsVX6K+CAc401+Y1COkg== dependencies: "@elastic/ecs-pino-format" "^1.2.0" after-all-results "^2.0.0"