From 39a29cc7698578c4a9c3923141a54f63a97de4e2 Mon Sep 17 00:00:00 2001
From: Dario Gieselaar
Date: Mon, 29 Nov 2021 10:14:33 +0100
Subject: [PATCH 01/47] [APM] Generate stack monitoring data (#118302)
* Generate stack monitoring data
* Update file import
* Fix imports after bad merge from upstream
* A cluster stats generator
* Wiring kibana docs to ES docs
* Adding fields to get kibana cards rendering
* [apm-synthtrace] Export types Fields, ApmException, ApmSynthtraceEsClient
* [APM] Update integration tests with synthtrace changes
* [APM] Update Cypress E2E tests with synthtrace changes
* Fix lint errors
Co-authored-by: Milton Hultgren
Co-authored-by: Mat Schaffer
---
packages/elastic-apm-synthtrace/src/index.ts | 16 +-
.../src/lib/{ => apm}/apm_error.ts | 10 +-
.../src/lib/apm/apm_fields.ts | 78 +++++++
.../src/lib/{ => apm}/base_span.ts | 12 +-
.../src/lib/{ => apm}/browser.ts | 7 +-
.../client/apm_synthtrace_es_client.ts} | 39 ++--
.../get_chrome_user_agent_defaults.ts | 4 +-
.../defaults/get_observer_defaults.ts | 4 +-
.../src/lib/apm/index.ts | 34 +++
.../src/lib/{ => apm}/instance.ts | 7 +-
.../src/lib/{ => apm}/metricset.ts | 8 +-
.../src/lib/{ => apm}/rum_span.ts | 0
.../src/lib/{ => apm}/rum_transaction.ts | 0
.../src/lib/{ => apm}/service.ts | 5 +-
.../src/lib/{ => apm}/span.ts | 6 +-
.../src/lib/{ => apm}/transaction.ts | 6 +-
.../src/lib/{ => apm}/utils/aggregate.ts | 8 +-
.../apm_events_to_elasticsearch_output.ts} | 35 ++-
.../src/lib/{ => apm}/utils/create_picker.ts | 0
.../utils/get_apm_write_targets.ts} | 6 +-
.../{ => apm}/utils/get_breakdown_metrics.ts | 8 +-
.../utils/get_span_destination_metrics.ts | 4 +-
.../utils/get_transaction_metrics.ts | 4 +-
.../elastic-apm-synthtrace/src/lib/entity.ts | 77 +------
.../src/lib/serializable.ts | 6 +-
.../src/lib/stack_monitoring/cluster.ts | 38 ++++
.../src/lib/stack_monitoring/cluster_stats.ts | 30 +++
.../src/lib/stack_monitoring/index.ts | 12 +
.../src/lib/stack_monitoring/kibana.ts | 19 ++
.../src/lib/stack_monitoring/kibana_stats.ts | 26 +++
.../stack_monitoring_fields.ts | 29 +++
.../src/lib/utils/clean_write_targets.ts | 9 +-
.../src/lib/utils/dedot.ts | 16 ++
.../src/lib/utils/logger.ts | 67 ------
.../src/lib/utils/to_elasticsearch_output.ts | 44 ++++
.../src/scripts/examples/01_simple_trace.ts | 150 ++++++++-----
.../src/scripts/examples/02_kibana_stats.ts | 48 ++++
.../src/scripts/examples/03_monitoring.ts | 70 ++++++
.../elastic-apm-synthtrace/src/scripts/run.ts | 211 ++++++++----------
.../src/scripts/scenario.ts | 13 ++
.../src/scripts/utils/get_common_services.ts | 25 +++
.../src/scripts/utils/get_scenario.ts | 4 +-
...on_resources.ts => parse_run_cli_flags.ts} | 44 +---
.../utils/start_historical_data_upload.ts | 52 ++---
.../scripts/utils/start_live_data_upload.ts | 56 ++---
.../src/scripts/utils/upload_events.ts | 22 +-
.../src/scripts/utils/upload_next_batch.ts | 63 ++++--
...pm_events_to_elasticsearch_output.test.ts} | 14 +-
.../test/scenarios/01_simple_trace.test.ts | 4 +-
.../scenarios/02_transaction_metrics.test.ts | 6 +-
.../03_span_destination_metrics.test.ts | 6 +-
.../scenarios/04_breakdown_metrics.test.ts | 10 +-
.../05_transactions_with_errors.test.ts | 6 +-
.../scenarios/06_application_metrics.test.ts | 6 +-
.../cypress/fixtures/synthtrace/opbeans.ts | 20 +-
.../read_only_user/errors/generate_data.ts | 11 +-
.../header_filters/generate_data.ts | 11 +-
.../apm/ftr_e2e/cypress/plugins/index.ts | 5 +-
.../common/synthtrace_es_client_service.ts | 4 +-
.../tests/dependencies/generate_data.ts | 8 +-
.../tests/error_rate/service_apis.spec.ts | 8 +-
.../tests/errors/error_group_list.spec.ts | 6 +-
.../tests/errors/generate_data.ts | 7 +-
.../tests/latency/service_apis.spec.ts | 15 +-
.../observability_overview.spec.ts | 21 +-
.../instances_main_statistics.spec.ts | 6 +-
.../services/error_groups/generate_data.ts | 8 +-
.../tests/services/throughput.spec.ts | 22 +-
.../tests/services/top_services.spec.ts | 28 +--
.../throughput/dependencies_apis.spec.ts | 14 +-
.../tests/throughput/service_apis.spec.ts | 15 +-
...actions_groups_detailed_statistics.spec.ts | 8 +-
72 files changed, 1022 insertions(+), 679 deletions(-)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/apm_error.ts (74%)
create mode 100644 packages/elastic-apm-synthtrace/src/lib/apm/apm_fields.ts
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/base_span.ts (86%)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/browser.ts (86%)
rename packages/elastic-apm-synthtrace/src/lib/{client/synthtrace_es_client.ts => apm/client/apm_synthtrace_es_client.ts} (58%)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/defaults/get_chrome_user_agent_defaults.ts (84%)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/defaults/get_observer_defaults.ts (82%)
create mode 100644 packages/elastic-apm-synthtrace/src/lib/apm/index.ts
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/instance.ts (87%)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/metricset.ts (72%)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/rum_span.ts (100%)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/rum_transaction.ts (100%)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/service.ts (85%)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/span.ts (88%)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/transaction.ts (93%)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/utils/aggregate.ts (82%)
rename packages/elastic-apm-synthtrace/src/lib/{output/to_elasticsearch_output.ts => apm/utils/apm_events_to_elasticsearch_output.ts} (57%)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/utils/create_picker.ts (100%)
rename packages/elastic-apm-synthtrace/src/lib/{utils/get_write_targets.ts => apm/utils/get_apm_write_targets.ts} (90%)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/utils/get_breakdown_metrics.ts (95%)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/utils/get_span_destination_metrics.ts (90%)
rename packages/elastic-apm-synthtrace/src/lib/{ => apm}/utils/get_transaction_metrics.ts (94%)
create mode 100644 packages/elastic-apm-synthtrace/src/lib/stack_monitoring/cluster.ts
create mode 100644 packages/elastic-apm-synthtrace/src/lib/stack_monitoring/cluster_stats.ts
create mode 100644 packages/elastic-apm-synthtrace/src/lib/stack_monitoring/index.ts
create mode 100644 packages/elastic-apm-synthtrace/src/lib/stack_monitoring/kibana.ts
create mode 100644 packages/elastic-apm-synthtrace/src/lib/stack_monitoring/kibana_stats.ts
create mode 100644 packages/elastic-apm-synthtrace/src/lib/stack_monitoring/stack_monitoring_fields.ts
create mode 100644 packages/elastic-apm-synthtrace/src/lib/utils/dedot.ts
delete mode 100644 packages/elastic-apm-synthtrace/src/lib/utils/logger.ts
create mode 100644 packages/elastic-apm-synthtrace/src/lib/utils/to_elasticsearch_output.ts
create mode 100644 packages/elastic-apm-synthtrace/src/scripts/examples/02_kibana_stats.ts
create mode 100644 packages/elastic-apm-synthtrace/src/scripts/examples/03_monitoring.ts
create mode 100644 packages/elastic-apm-synthtrace/src/scripts/scenario.ts
create mode 100644 packages/elastic-apm-synthtrace/src/scripts/utils/get_common_services.ts
rename packages/elastic-apm-synthtrace/src/scripts/utils/{get_common_resources.ts => parse_run_cli_flags.ts} (59%)
rename packages/elastic-apm-synthtrace/src/test/{to_elasticsearch_output.test.ts => apm_events_to_elasticsearch_output.test.ts} (76%)
diff --git a/packages/elastic-apm-synthtrace/src/index.ts b/packages/elastic-apm-synthtrace/src/index.ts
index 931215c75fde4..381222ee10efc 100644
--- a/packages/elastic-apm-synthtrace/src/index.ts
+++ b/packages/elastic-apm-synthtrace/src/index.ts
@@ -6,17 +6,11 @@
* Side Public License, v 1.
*/
-export type { Exception } from './lib/entity';
-export { service } from './lib/service';
-export { browser } from './lib/browser';
export { timerange } from './lib/timerange';
-export { getTransactionMetrics } from './lib/utils/get_transaction_metrics';
-export { getSpanDestinationMetrics } from './lib/utils/get_span_destination_metrics';
-export { getObserverDefaults } from './lib/defaults/get_observer_defaults';
-export { getChromeUserAgentDefaults } from './lib/defaults/get_chrome_user_agent_defaults';
-export { toElasticsearchOutput } from './lib/output/to_elasticsearch_output';
-export { getBreakdownMetrics } from './lib/utils/get_breakdown_metrics';
+export { apm } from './lib/apm';
+export { stackMonitoring } from './lib/stack_monitoring';
export { cleanWriteTargets } from './lib/utils/clean_write_targets';
-export { getWriteTargets } from './lib/utils/get_write_targets';
-export { SynthtraceEsClient } from './lib/client/synthtrace_es_client';
export { createLogger, LogLevel } from './lib/utils/create_logger';
+
+export type { Fields } from './lib/entity';
+export type { ApmException, ApmSynthtraceEsClient } from './lib/apm';
diff --git a/packages/elastic-apm-synthtrace/src/lib/apm_error.ts b/packages/elastic-apm-synthtrace/src/lib/apm/apm_error.ts
similarity index 74%
rename from packages/elastic-apm-synthtrace/src/lib/apm_error.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/apm_error.ts
index 5a48093a26db2..334c0f296851d 100644
--- a/packages/elastic-apm-synthtrace/src/lib/apm_error.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/apm_error.ts
@@ -6,12 +6,12 @@
* Side Public License, v 1.
*/
-import { Fields } from './entity';
-import { Serializable } from './serializable';
-import { generateLongId, generateShortId } from './utils/generate_id';
+import { ApmFields } from './apm_fields';
+import { Serializable } from '../serializable';
+import { generateLongId, generateShortId } from '../utils/generate_id';
-export class ApmError extends Serializable {
- constructor(fields: Fields) {
+export class ApmError extends Serializable {
+ constructor(fields: ApmFields) {
super({
...fields,
'processor.event': 'error',
diff --git a/packages/elastic-apm-synthtrace/src/lib/apm/apm_fields.ts b/packages/elastic-apm-synthtrace/src/lib/apm/apm_fields.ts
new file mode 100644
index 0000000000000..a7a826d144d0e
--- /dev/null
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/apm_fields.ts
@@ -0,0 +1,78 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { Fields } from '../entity';
+
+export type ApmApplicationMetricFields = Partial<{
+ 'system.process.memory.size': number;
+ 'system.memory.actual.free': number;
+ 'system.memory.total': number;
+ 'system.cpu.total.norm.pct': number;
+ 'system.process.memory.rss.bytes': number;
+ 'system.process.cpu.total.norm.pct': number;
+}>;
+
+export type ApmUserAgentFields = Partial<{
+ 'user_agent.original': string;
+ 'user_agent.os.name': string;
+ 'user_agent.name': string;
+ 'user_agent.device.name': string;
+ 'user_agent.version': number;
+}>;
+
+export interface ApmException {
+ message: string;
+}
+
+export type ApmFields = Fields &
+ Partial<{
+ 'agent.name': string;
+ 'agent.version': string;
+ 'container.id': string;
+ 'ecs.version': string;
+ 'event.outcome': string;
+ 'event.ingested': number;
+ 'error.id': string;
+ 'error.exception': ApmException[];
+ 'error.grouping_name': string;
+ 'error.grouping_key': string;
+ 'host.name': string;
+ 'kubernetes.pod.uid': string;
+ 'metricset.name': string;
+ 'observer.version': string;
+ 'observer.version_major': number;
+ 'parent.id': string;
+ 'processor.event': string;
+ 'processor.name': string;
+ 'trace.id': string;
+ 'transaction.name': string;
+ 'transaction.type': string;
+ 'transaction.id': string;
+ 'transaction.duration.us': number;
+ 'transaction.duration.histogram': {
+ values: number[];
+ counts: number[];
+ };
+ 'transaction.sampled': true;
+ 'service.name': string;
+ 'service.environment': string;
+ 'service.node.name': string;
+ 'span.id': string;
+ 'span.name': string;
+ 'span.type': string;
+ 'span.subtype': string;
+ 'span.duration.us': number;
+ 'span.destination.service.name': string;
+ 'span.destination.service.resource': string;
+ 'span.destination.service.type': string;
+ 'span.destination.service.response_time.sum.us': number;
+ 'span.destination.service.response_time.count': number;
+ 'span.self_time.count': number;
+ 'span.self_time.sum.us': number;
+ }> &
+ ApmApplicationMetricFields;
diff --git a/packages/elastic-apm-synthtrace/src/lib/base_span.ts b/packages/elastic-apm-synthtrace/src/lib/apm/base_span.ts
similarity index 86%
rename from packages/elastic-apm-synthtrace/src/lib/base_span.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/base_span.ts
index f762bf730a717..ba2af8ce9ee53 100644
--- a/packages/elastic-apm-synthtrace/src/lib/base_span.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/base_span.ts
@@ -6,16 +6,16 @@
* Side Public License, v 1.
*/
-import { Fields } from './entity';
-import { Serializable } from './serializable';
+import { Serializable } from '../serializable';
import { Span } from './span';
import { Transaction } from './transaction';
-import { generateLongId } from './utils/generate_id';
+import { generateLongId } from '../utils/generate_id';
+import { ApmFields } from './apm_fields';
-export class BaseSpan extends Serializable {
+export class BaseSpan extends Serializable {
private readonly _children: BaseSpan[] = [];
- constructor(fields: Fields) {
+ constructor(fields: ApmFields) {
super({
...fields,
'event.outcome': 'unknown',
@@ -60,7 +60,7 @@ export class BaseSpan extends Serializable {
return this;
}
- serialize(): Fields[] {
+ serialize(): ApmFields[] {
return [this.fields, ...this._children.flatMap((child) => child.serialize())];
}
diff --git a/packages/elastic-apm-synthtrace/src/lib/browser.ts b/packages/elastic-apm-synthtrace/src/lib/apm/browser.ts
similarity index 86%
rename from packages/elastic-apm-synthtrace/src/lib/browser.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/browser.ts
index 0fd8b44b69851..ebba6a0e89a69 100644
--- a/packages/elastic-apm-synthtrace/src/lib/browser.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/browser.ts
@@ -6,11 +6,12 @@
* Side Public License, v 1.
*/
-import { Entity, UserAgentFields } from './entity';
+import { ApmFields, ApmUserAgentFields } from './apm_fields';
+import { Entity } from '../entity';
import { RumSpan } from './rum_span';
import { RumTransaction } from './rum_transaction';
-export class Browser extends Entity {
+export class Browser extends Entity {
transaction(transactionName: string, transactionType: string = 'page-load') {
return new RumTransaction({
...this.fields,
@@ -29,7 +30,7 @@ export class Browser extends Entity {
}
}
-export function browser(serviceName: string, production: string, userAgent: UserAgentFields) {
+export function browser(serviceName: string, production: string, userAgent: ApmUserAgentFields) {
return new Browser({
'agent.name': 'rum-js',
'service.name': serviceName,
diff --git a/packages/elastic-apm-synthtrace/src/lib/client/synthtrace_es_client.ts b/packages/elastic-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts
similarity index 58%
rename from packages/elastic-apm-synthtrace/src/lib/client/synthtrace_es_client.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts
index 546214f83c364..4a25d7009ad01 100644
--- a/packages/elastic-apm-synthtrace/src/lib/client/synthtrace_es_client.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts
@@ -7,45 +7,52 @@
*/
import { Client } from '@elastic/elasticsearch';
-import { uploadEvents } from '../../scripts/utils/upload_events';
-import { Fields } from '../entity';
-import { cleanWriteTargets } from '../utils/clean_write_targets';
+import { uploadEvents } from '../../../scripts/utils/upload_events';
+import { Fields } from '../../entity';
+import { cleanWriteTargets } from '../../utils/clean_write_targets';
import { getBreakdownMetrics } from '../utils/get_breakdown_metrics';
import { getSpanDestinationMetrics } from '../utils/get_span_destination_metrics';
import { getTransactionMetrics } from '../utils/get_transaction_metrics';
-import { getWriteTargets } from '../utils/get_write_targets';
-import { Logger } from '../utils/logger';
+import { getApmWriteTargets } from '../utils/get_apm_write_targets';
+import { Logger } from '../../utils/create_logger';
+import { apmEventsToElasticsearchOutput } from '../utils/apm_events_to_elasticsearch_output';
-export class SynthtraceEsClient {
+export class ApmSynthtraceEsClient {
constructor(private readonly client: Client, private readonly logger: Logger) {}
private getWriteTargets() {
- return getWriteTargets({ client: this.client });
+ return getApmWriteTargets({ client: this.client });
}
clean() {
return this.getWriteTargets().then((writeTargets) =>
- cleanWriteTargets({ client: this.client, writeTargets, logger: this.logger })
+ cleanWriteTargets({
+ client: this.client,
+ targets: Object.values(writeTargets),
+ logger: this.logger,
+ })
);
}
async index(events: Fields[]) {
- const eventsToIndex = [
- ...events,
- ...getTransactionMetrics(events),
- ...getSpanDestinationMetrics(events),
- ...getBreakdownMetrics(events),
- ];
-
const writeTargets = await this.getWriteTargets();
+ const eventsToIndex = apmEventsToElasticsearchOutput({
+ events: [
+ ...events,
+ ...getTransactionMetrics(events),
+ ...getSpanDestinationMetrics(events),
+ ...getBreakdownMetrics(events),
+ ],
+ writeTargets,
+ });
+
await uploadEvents({
batchSize: 1000,
client: this.client,
clientWorkers: 5,
events: eventsToIndex,
logger: this.logger,
- writeTargets,
});
return this.client.indices.refresh({
diff --git a/packages/elastic-apm-synthtrace/src/lib/defaults/get_chrome_user_agent_defaults.ts b/packages/elastic-apm-synthtrace/src/lib/apm/defaults/get_chrome_user_agent_defaults.ts
similarity index 84%
rename from packages/elastic-apm-synthtrace/src/lib/defaults/get_chrome_user_agent_defaults.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/defaults/get_chrome_user_agent_defaults.ts
index 0031456248c1a..9a919e505185c 100644
--- a/packages/elastic-apm-synthtrace/src/lib/defaults/get_chrome_user_agent_defaults.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/defaults/get_chrome_user_agent_defaults.ts
@@ -6,9 +6,9 @@
* Side Public License, v 1.
*/
-import { UserAgentFields } from '../entity';
+import { ApmUserAgentFields } from '../../apm/apm_fields';
-export function getChromeUserAgentDefaults(): UserAgentFields {
+export function getChromeUserAgentDefaults(): ApmUserAgentFields {
return {
'user_agent.original':
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36',
diff --git a/packages/elastic-apm-synthtrace/src/lib/defaults/get_observer_defaults.ts b/packages/elastic-apm-synthtrace/src/lib/apm/defaults/get_observer_defaults.ts
similarity index 82%
rename from packages/elastic-apm-synthtrace/src/lib/defaults/get_observer_defaults.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/defaults/get_observer_defaults.ts
index 67a4d5773b937..882029a50e47f 100644
--- a/packages/elastic-apm-synthtrace/src/lib/defaults/get_observer_defaults.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/defaults/get_observer_defaults.ts
@@ -6,9 +6,9 @@
* Side Public License, v 1.
*/
-import { Fields } from '../entity';
+import { ApmFields } from '../apm_fields';
-export function getObserverDefaults(): Fields {
+export function getObserverDefaults(): ApmFields {
return {
'observer.version': '7.16.0',
'observer.version_major': 7,
diff --git a/packages/elastic-apm-synthtrace/src/lib/apm/index.ts b/packages/elastic-apm-synthtrace/src/lib/apm/index.ts
new file mode 100644
index 0000000000000..f020d9a1282e8
--- /dev/null
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/index.ts
@@ -0,0 +1,34 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+import { service } from './service';
+import { browser } from './browser';
+import { getTransactionMetrics } from './utils/get_transaction_metrics';
+import { getSpanDestinationMetrics } from './utils/get_span_destination_metrics';
+import { getObserverDefaults } from './defaults/get_observer_defaults';
+import { getChromeUserAgentDefaults } from './defaults/get_chrome_user_agent_defaults';
+import { apmEventsToElasticsearchOutput } from './utils/apm_events_to_elasticsearch_output';
+import { getBreakdownMetrics } from './utils/get_breakdown_metrics';
+import { getApmWriteTargets } from './utils/get_apm_write_targets';
+import { ApmSynthtraceEsClient } from './client/apm_synthtrace_es_client';
+
+import type { ApmException } from './apm_fields';
+
+export const apm = {
+ service,
+ browser,
+ getTransactionMetrics,
+ getSpanDestinationMetrics,
+ getObserverDefaults,
+ getChromeUserAgentDefaults,
+ apmEventsToElasticsearchOutput,
+ getBreakdownMetrics,
+ getApmWriteTargets,
+ ApmSynthtraceEsClient,
+};
+
+export type { ApmSynthtraceEsClient, ApmException };
diff --git a/packages/elastic-apm-synthtrace/src/lib/instance.ts b/packages/elastic-apm-synthtrace/src/lib/apm/instance.ts
similarity index 87%
rename from packages/elastic-apm-synthtrace/src/lib/instance.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/instance.ts
index 08444fde48ba6..4051d7e8241da 100644
--- a/packages/elastic-apm-synthtrace/src/lib/instance.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/instance.ts
@@ -7,12 +7,13 @@
*/
import { ApmError } from './apm_error';
-import { ApplicationMetricFields, Entity } from './entity';
+import { Entity } from '../entity';
import { Metricset } from './metricset';
import { Span } from './span';
import { Transaction } from './transaction';
+import { ApmApplicationMetricFields, ApmFields } from './apm_fields';
-export class Instance extends Entity {
+export class Instance extends Entity {
transaction(transactionName: string, transactionType = 'request') {
return new Transaction({
...this.fields,
@@ -43,7 +44,7 @@ export class Instance extends Entity {
return this;
}
- appMetrics(metrics: ApplicationMetricFields) {
+ appMetrics(metrics: ApmApplicationMetricFields) {
return new Metricset({
...this.fields,
'metricset.name': 'app',
diff --git a/packages/elastic-apm-synthtrace/src/lib/metricset.ts b/packages/elastic-apm-synthtrace/src/lib/apm/metricset.ts
similarity index 72%
rename from packages/elastic-apm-synthtrace/src/lib/metricset.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/metricset.ts
index c1ebbea313123..88177e816a852 100644
--- a/packages/elastic-apm-synthtrace/src/lib/metricset.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/metricset.ts
@@ -6,11 +6,11 @@
* Side Public License, v 1.
*/
-import { Fields } from './entity';
-import { Serializable } from './serializable';
+import { Serializable } from '../serializable';
+import { ApmFields } from './apm_fields';
-export class Metricset extends Serializable {
- constructor(fields: Fields) {
+export class Metricset extends Serializable {
+ constructor(fields: ApmFields) {
super({
'processor.event': 'metric',
'processor.name': 'metric',
diff --git a/packages/elastic-apm-synthtrace/src/lib/rum_span.ts b/packages/elastic-apm-synthtrace/src/lib/apm/rum_span.ts
similarity index 100%
rename from packages/elastic-apm-synthtrace/src/lib/rum_span.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/rum_span.ts
diff --git a/packages/elastic-apm-synthtrace/src/lib/rum_transaction.ts b/packages/elastic-apm-synthtrace/src/lib/apm/rum_transaction.ts
similarity index 100%
rename from packages/elastic-apm-synthtrace/src/lib/rum_transaction.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/rum_transaction.ts
diff --git a/packages/elastic-apm-synthtrace/src/lib/service.ts b/packages/elastic-apm-synthtrace/src/lib/apm/service.ts
similarity index 85%
rename from packages/elastic-apm-synthtrace/src/lib/service.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/service.ts
index 859afa18aab03..16917821c7ee4 100644
--- a/packages/elastic-apm-synthtrace/src/lib/service.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/service.ts
@@ -6,10 +6,11 @@
* Side Public License, v 1.
*/
-import { Entity } from './entity';
+import { Entity } from '../entity';
+import { ApmFields } from './apm_fields';
import { Instance } from './instance';
-export class Service extends Entity {
+export class Service extends Entity {
instance(instanceName: string) {
return new Instance({
...this.fields,
diff --git a/packages/elastic-apm-synthtrace/src/lib/span.ts b/packages/elastic-apm-synthtrace/src/lib/apm/span.ts
similarity index 88%
rename from packages/elastic-apm-synthtrace/src/lib/span.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/span.ts
index 3c8d90f56b78e..91cbacadf59cc 100644
--- a/packages/elastic-apm-synthtrace/src/lib/span.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/span.ts
@@ -7,11 +7,11 @@
*/
import { BaseSpan } from './base_span';
-import { Fields } from './entity';
-import { generateShortId } from './utils/generate_id';
+import { generateShortId } from '../utils/generate_id';
+import { ApmFields } from './apm_fields';
export class Span extends BaseSpan {
- constructor(fields: Fields) {
+ constructor(fields: ApmFields) {
super({
...fields,
'processor.event': 'span',
diff --git a/packages/elastic-apm-synthtrace/src/lib/transaction.ts b/packages/elastic-apm-synthtrace/src/lib/apm/transaction.ts
similarity index 93%
rename from packages/elastic-apm-synthtrace/src/lib/transaction.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/transaction.ts
index 3a8d32e1843f8..47924e49e9b84 100644
--- a/packages/elastic-apm-synthtrace/src/lib/transaction.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/transaction.ts
@@ -8,14 +8,14 @@
import { ApmError } from './apm_error';
import { BaseSpan } from './base_span';
-import { Fields } from './entity';
-import { generateShortId } from './utils/generate_id';
+import { generateShortId } from '../utils/generate_id';
+import { ApmFields } from './apm_fields';
export class Transaction extends BaseSpan {
private _sampled: boolean = true;
private readonly _errors: ApmError[] = [];
- constructor(fields: Fields) {
+ constructor(fields: ApmFields) {
super({
...fields,
'processor.event': 'transaction',
diff --git a/packages/elastic-apm-synthtrace/src/lib/utils/aggregate.ts b/packages/elastic-apm-synthtrace/src/lib/apm/utils/aggregate.ts
similarity index 82%
rename from packages/elastic-apm-synthtrace/src/lib/utils/aggregate.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/utils/aggregate.ts
index 81b72f6fa01e9..505f7452fe5d9 100644
--- a/packages/elastic-apm-synthtrace/src/lib/utils/aggregate.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/utils/aggregate.ts
@@ -8,15 +8,15 @@
import moment from 'moment';
import { pickBy } from 'lodash';
import objectHash from 'object-hash';
-import { Fields } from '../entity';
+import { ApmFields } from '../apm_fields';
import { createPicker } from './create_picker';
-export function aggregate(events: Fields[], fields: string[]) {
+export function aggregate(events: ApmFields[], fields: string[]) {
const picker = createPicker(fields);
- const metricsets = new Map();
+ const metricsets = new Map();
- function getMetricsetKey(span: Fields) {
+ function getMetricsetKey(span: ApmFields) {
const timestamp = moment(span['@timestamp']).valueOf();
return {
'@timestamp': timestamp - (timestamp % (60 * 1000)),
diff --git a/packages/elastic-apm-synthtrace/src/lib/output/to_elasticsearch_output.ts b/packages/elastic-apm-synthtrace/src/lib/apm/utils/apm_events_to_elasticsearch_output.ts
similarity index 57%
rename from packages/elastic-apm-synthtrace/src/lib/output/to_elasticsearch_output.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/utils/apm_events_to_elasticsearch_output.ts
index 016f1c5362fb4..46456098df4a0 100644
--- a/packages/elastic-apm-synthtrace/src/lib/output/to_elasticsearch_output.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/utils/apm_events_to_elasticsearch_output.ts
@@ -6,16 +6,12 @@
* Side Public License, v 1.
*/
-import { set } from 'lodash';
-import { getObserverDefaults } from '../..';
-import { Fields } from '../entity';
+import { getObserverDefaults } from '../defaults/get_observer_defaults';
+import { ApmFields } from '../apm_fields';
+import { dedot } from '../../utils/dedot';
+import { ElasticsearchOutput } from '../../utils/to_elasticsearch_output';
-export interface ElasticsearchOutput {
- _index: string;
- _source: unknown;
-}
-
-export interface ElasticsearchOutputWriteTargets {
+export interface ApmElasticsearchOutputWriteTargets {
transaction: string;
span: string;
error: string;
@@ -30,16 +26,14 @@ const esDocumentDefaults = {
},
};
-// eslint-disable-next-line guard-for-in
-for (const key in observerDefaults) {
- set(esDocumentDefaults, key, observerDefaults[key as keyof typeof observerDefaults]);
-}
-export function toElasticsearchOutput({
+dedot(observerDefaults, esDocumentDefaults);
+
+export function apmEventsToElasticsearchOutput({
events,
writeTargets,
}: {
- events: Fields[];
- writeTargets: ElasticsearchOutputWriteTargets;
+ events: ApmFields[];
+ writeTargets: ApmElasticsearchOutputWriteTargets;
}): ElasticsearchOutput[] {
return events.map((event) => {
const values = {};
@@ -55,15 +49,12 @@ export function toElasticsearchOutput({
Object.assign(document, esDocumentDefaults);
- // eslint-disable-next-line guard-for-in
- for (const key in values) {
- const val = values[key as keyof typeof values];
- set(document, key, val);
- }
+ dedot(values, document);
return {
- _index: writeTargets[event['processor.event'] as keyof ElasticsearchOutputWriteTargets],
+ _index: writeTargets[event['processor.event'] as keyof ApmElasticsearchOutputWriteTargets],
_source: document,
+ timestamp: event['@timestamp']!,
};
});
}
diff --git a/packages/elastic-apm-synthtrace/src/lib/utils/create_picker.ts b/packages/elastic-apm-synthtrace/src/lib/apm/utils/create_picker.ts
similarity index 100%
rename from packages/elastic-apm-synthtrace/src/lib/utils/create_picker.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/utils/create_picker.ts
diff --git a/packages/elastic-apm-synthtrace/src/lib/utils/get_write_targets.ts b/packages/elastic-apm-synthtrace/src/lib/apm/utils/get_apm_write_targets.ts
similarity index 90%
rename from packages/elastic-apm-synthtrace/src/lib/utils/get_write_targets.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/utils/get_apm_write_targets.ts
index fbe11d295e099..f040ca46a9db9 100644
--- a/packages/elastic-apm-synthtrace/src/lib/utils/get_write_targets.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/utils/get_apm_write_targets.ts
@@ -7,13 +7,13 @@
*/
import { Client } from '@elastic/elasticsearch';
-import { ElasticsearchOutputWriteTargets } from '../../lib/output/to_elasticsearch_output';
+import { ApmElasticsearchOutputWriteTargets } from './apm_events_to_elasticsearch_output';
-export async function getWriteTargets({
+export async function getApmWriteTargets({
client,
}: {
client: Client;
-}): Promise {
+}): Promise {
const [indicesResponse, datastreamsResponse] = await Promise.all([
client.indices.getAlias({
index: 'apm-*',
diff --git a/packages/elastic-apm-synthtrace/src/lib/utils/get_breakdown_metrics.ts b/packages/elastic-apm-synthtrace/src/lib/apm/utils/get_breakdown_metrics.ts
similarity index 95%
rename from packages/elastic-apm-synthtrace/src/lib/utils/get_breakdown_metrics.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/utils/get_breakdown_metrics.ts
index 8eae0941c6bdd..4f29a31d5d278 100644
--- a/packages/elastic-apm-synthtrace/src/lib/utils/get_breakdown_metrics.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/utils/get_breakdown_metrics.ts
@@ -7,7 +7,7 @@
*/
import objectHash from 'object-hash';
import { groupBy, pickBy } from 'lodash';
-import { Fields } from '../entity';
+import { ApmFields } from '../apm_fields';
import { createPicker } from './create_picker';
const instanceFields = [
@@ -29,7 +29,7 @@ const metricsetPicker = createPicker([
'span.subtype',
]);
-export function getBreakdownMetrics(events: Fields[]) {
+export function getBreakdownMetrics(events: ApmFields[]) {
const txWithSpans = groupBy(
events.filter(
(event) => event['processor.event'] === 'span' || event['processor.event'] === 'transaction'
@@ -37,13 +37,13 @@ export function getBreakdownMetrics(events: Fields[]) {
(event) => event['transaction.id']
);
- const metricsets: Map = new Map();
+ const metricsets: Map = new Map();
Object.keys(txWithSpans).forEach((transactionId) => {
const txEvents = txWithSpans[transactionId];
const transaction = txEvents.find((event) => event['processor.event'] === 'transaction')!;
- const eventsById: Record = {};
+ const eventsById: Record = {};
const activityByParentId: Record> = {};
for (const event of txEvents) {
const id =
diff --git a/packages/elastic-apm-synthtrace/src/lib/utils/get_span_destination_metrics.ts b/packages/elastic-apm-synthtrace/src/lib/apm/utils/get_span_destination_metrics.ts
similarity index 90%
rename from packages/elastic-apm-synthtrace/src/lib/utils/get_span_destination_metrics.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/utils/get_span_destination_metrics.ts
index decf2f71a9be4..7adcdaa6ff940 100644
--- a/packages/elastic-apm-synthtrace/src/lib/utils/get_span_destination_metrics.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/utils/get_span_destination_metrics.ts
@@ -6,10 +6,10 @@
* Side Public License, v 1.
*/
-import { Fields } from '../entity';
+import { ApmFields } from '../apm_fields';
import { aggregate } from './aggregate';
-export function getSpanDestinationMetrics(events: Fields[]) {
+export function getSpanDestinationMetrics(events: ApmFields[]) {
const exitSpans = events.filter((event) => !!event['span.destination.service.resource']);
const metricsets = aggregate(exitSpans, [
diff --git a/packages/elastic-apm-synthtrace/src/lib/utils/get_transaction_metrics.ts b/packages/elastic-apm-synthtrace/src/lib/apm/utils/get_transaction_metrics.ts
similarity index 94%
rename from packages/elastic-apm-synthtrace/src/lib/utils/get_transaction_metrics.ts
rename to packages/elastic-apm-synthtrace/src/lib/apm/utils/get_transaction_metrics.ts
index 4d46461c6dcc9..1595e58957223 100644
--- a/packages/elastic-apm-synthtrace/src/lib/utils/get_transaction_metrics.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/apm/utils/get_transaction_metrics.ts
@@ -7,7 +7,7 @@
*/
import { sortBy } from 'lodash';
-import { Fields } from '../entity';
+import { ApmFields } from '../apm_fields';
import { aggregate } from './aggregate';
function sortAndCompressHistogram(histogram?: { values: number[]; counts: number[] }) {
@@ -28,7 +28,7 @@ function sortAndCompressHistogram(histogram?: { values: number[]; counts: number
);
}
-export function getTransactionMetrics(events: Fields[]) {
+export function getTransactionMetrics(events: ApmFields[]) {
const transactions = events
.filter((event) => event['processor.event'] === 'transaction')
.map((transaction) => {
diff --git a/packages/elastic-apm-synthtrace/src/lib/entity.ts b/packages/elastic-apm-synthtrace/src/lib/entity.ts
index c6e0c7193f8ba..f1b11a3905df7 100644
--- a/packages/elastic-apm-synthtrace/src/lib/entity.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/entity.ts
@@ -6,83 +6,18 @@
* Side Public License, v 1.
*/
-export type ApplicationMetricFields = Partial<{
- 'system.process.memory.size': number;
- 'system.memory.actual.free': number;
- 'system.memory.total': number;
- 'system.cpu.total.norm.pct': number;
- 'system.process.memory.rss.bytes': number;
- 'system.process.cpu.total.norm.pct': number;
-}>;
-
-export type UserAgentFields = Partial<{
- 'user_agent.original': string;
- 'user_agent.os.name': string;
- 'user_agent.name': string;
- 'user_agent.device.name': string;
- 'user_agent.version': number;
-}>;
-
-export interface Exception {
- message: string;
+export interface Fields {
+ '@timestamp'?: number;
}
-export type Fields = Partial<{
- '@timestamp': number;
- 'agent.name': string;
- 'agent.version': string;
- 'container.id': string;
- 'ecs.version': string;
- 'event.outcome': string;
- 'event.ingested': number;
- 'error.id': string;
- 'error.exception': Exception[];
- 'error.grouping_name': string;
- 'error.grouping_key': string;
- 'host.name': string;
- 'kubernetes.pod.uid': string;
- 'metricset.name': string;
- 'observer.version': string;
- 'observer.version_major': number;
- 'parent.id': string;
- 'processor.event': string;
- 'processor.name': string;
- 'trace.id': string;
- 'transaction.name': string;
- 'transaction.type': string;
- 'transaction.id': string;
- 'transaction.duration.us': number;
- 'transaction.duration.histogram': {
- values: number[];
- counts: number[];
- };
- 'transaction.sampled': true;
- 'service.name': string;
- 'service.environment': string;
- 'service.node.name': string;
- 'span.id': string;
- 'span.name': string;
- 'span.type': string;
- 'span.subtype': string;
- 'span.duration.us': number;
- 'span.destination.service.name': string;
- 'span.destination.service.resource': string;
- 'span.destination.service.type': string;
- 'span.destination.service.response_time.sum.us': number;
- 'span.destination.service.response_time.count': number;
- 'span.self_time.count': number;
- 'span.self_time.sum.us': number;
-}> &
- ApplicationMetricFields;
-
-export class Entity {
- constructor(public readonly fields: Fields) {
+export class Entity {
+ constructor(public readonly fields: TFields) {
this.fields = fields;
}
- defaults(defaults: Fields) {
+ defaults(defaults: TFields) {
Object.keys(defaults).forEach((key) => {
- const fieldName: keyof Fields = key as any;
+ const fieldName: keyof TFields = key as any;
if (!(fieldName in this.fields)) {
this.fields[fieldName] = defaults[fieldName] as any;
diff --git a/packages/elastic-apm-synthtrace/src/lib/serializable.ts b/packages/elastic-apm-synthtrace/src/lib/serializable.ts
index 3a92dc539855a..e9ffe3ae96994 100644
--- a/packages/elastic-apm-synthtrace/src/lib/serializable.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/serializable.ts
@@ -8,8 +8,8 @@
import { Entity, Fields } from './entity';
-export class Serializable extends Entity {
- constructor(fields: Fields) {
+export class Serializable extends Entity {
+ constructor(fields: TFields) {
super({
...fields,
});
@@ -19,7 +19,7 @@ export class Serializable extends Entity {
this.fields['@timestamp'] = time;
return this;
}
- serialize(): Fields[] {
+ serialize(): TFields[] {
return [this.fields];
}
}
diff --git a/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/cluster.ts b/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/cluster.ts
new file mode 100644
index 0000000000000..7a665522abba4
--- /dev/null
+++ b/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/cluster.ts
@@ -0,0 +1,38 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { Entity } from '../entity';
+import { generateShortId } from '../utils/generate_id';
+import { Kibana } from './kibana';
+import { StackMonitoringFields } from './stack_monitoring_fields';
+import { ClusterStats } from './cluster_stats';
+
+export class Cluster extends Entity {
+ kibana(name: string, index: string = '.kibana') {
+ return new Kibana({
+ cluster_uuid: this.fields.cluster_uuid,
+ 'kibana_stats.kibana.name': name,
+ 'kibana_stats.kibana.uuid': generateShortId(),
+ 'kibana_stats.kibana.index': index,
+ type: 'kibana_stats',
+ });
+ }
+
+ stats() {
+ return new ClusterStats({
+ ...this.fields,
+ });
+ }
+}
+
+export function cluster(name: string) {
+ return new Cluster({
+ cluster_name: name,
+ cluster_uuid: generateShortId(),
+ });
+}
diff --git a/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/cluster_stats.ts b/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/cluster_stats.ts
new file mode 100644
index 0000000000000..0995013cbcbb7
--- /dev/null
+++ b/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/cluster_stats.ts
@@ -0,0 +1,30 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { Serializable } from '../serializable';
+import { StackMonitoringFields } from './stack_monitoring_fields';
+
+export class ClusterStats extends Serializable {
+ constructor(fields: StackMonitoringFields) {
+ super(fields);
+
+ this.fields.type = 'cluster_stats';
+ this.fields['license.status'] = 'active';
+ }
+
+ timestamp(timestamp: number) {
+ super.timestamp(timestamp);
+ this.fields['cluster_stats.timestamp'] = new Date(timestamp).toISOString();
+ return this;
+ }
+
+ indices(count: number) {
+ this.fields['cluster_stats.indices.count'] = count;
+ return this;
+ }
+}
diff --git a/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/index.ts b/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/index.ts
new file mode 100644
index 0000000000000..ee926269ea36b
--- /dev/null
+++ b/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/index.ts
@@ -0,0 +1,12 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+import { cluster } from './cluster';
+
+export const stackMonitoring = {
+ cluster,
+};
diff --git a/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/kibana.ts b/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/kibana.ts
new file mode 100644
index 0000000000000..fec244bc19dc1
--- /dev/null
+++ b/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/kibana.ts
@@ -0,0 +1,19 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { Serializable } from '../serializable';
+import { StackMonitoringFields } from './stack_monitoring_fields';
+import { KibanaStats } from './kibana_stats';
+
+export class Kibana extends Serializable {
+ stats() {
+ return new KibanaStats({
+ ...this.fields,
+ });
+ }
+}
diff --git a/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/kibana_stats.ts b/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/kibana_stats.ts
new file mode 100644
index 0000000000000..495e5f013600e
--- /dev/null
+++ b/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/kibana_stats.ts
@@ -0,0 +1,26 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { Serializable } from '../serializable';
+import { StackMonitoringFields } from './stack_monitoring_fields';
+
+export class KibanaStats extends Serializable {
+ timestamp(timestamp: number) {
+ super.timestamp(timestamp);
+ this.fields['kibana_stats.timestamp'] = new Date(timestamp).toISOString();
+ this.fields['kibana_stats.response_times.max'] = 250;
+ this.fields['kibana_stats.kibana.status'] = 'green';
+ return this;
+ }
+
+ requests(disconnects: number, total: number) {
+ this.fields['kibana_stats.requests.disconnects'] = disconnects;
+ this.fields['kibana_stats.requests.total'] = total;
+ return this;
+ }
+}
diff --git a/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/stack_monitoring_fields.ts b/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/stack_monitoring_fields.ts
new file mode 100644
index 0000000000000..3e80d1e9f733f
--- /dev/null
+++ b/packages/elastic-apm-synthtrace/src/lib/stack_monitoring/stack_monitoring_fields.ts
@@ -0,0 +1,29 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { Fields } from '../entity';
+
+export type StackMonitoringFields = Fields &
+ Partial<{
+ cluster_name: string;
+ cluster_uuid: string;
+ type: string;
+
+ 'cluster_stats.timestamp': string;
+ 'cluster_stats.indices.count': number;
+ 'license.status': string;
+
+ 'kibana_stats.kibana.name': string;
+ 'kibana_stats.kibana.uuid': string;
+ 'kibana_stats.kibana.status': string;
+ 'kibana_stats.kibana.index': string;
+ 'kibana_stats.requests.disconnects': number;
+ 'kibana_stats.requests.total': number;
+ 'kibana_stats.timestamp': string;
+ 'kibana_stats.response_times.max': number;
+ }>;
diff --git a/packages/elastic-apm-synthtrace/src/lib/utils/clean_write_targets.ts b/packages/elastic-apm-synthtrace/src/lib/utils/clean_write_targets.ts
index 4a2ab281a2849..91b8e0084b27f 100644
--- a/packages/elastic-apm-synthtrace/src/lib/utils/clean_write_targets.ts
+++ b/packages/elastic-apm-synthtrace/src/lib/utils/clean_write_targets.ts
@@ -7,20 +7,17 @@
*/
import { Client } from '@elastic/elasticsearch';
-import { ElasticsearchOutputWriteTargets } from '../../lib/output/to_elasticsearch_output';
-import { Logger } from './logger';
+import { Logger } from './create_logger';
export async function cleanWriteTargets({
- writeTargets,
+ targets,
client,
logger,
}: {
- writeTargets: ElasticsearchOutputWriteTargets;
+ targets: string[];
client: Client;
logger: Logger;
}) {
- const targets = Object.values(writeTargets);
-
logger.info(`Cleaning indices: ${targets.join(', ')}`);
const response = await client.deleteByQuery({
diff --git a/packages/elastic-apm-synthtrace/src/lib/utils/dedot.ts b/packages/elastic-apm-synthtrace/src/lib/utils/dedot.ts
new file mode 100644
index 0000000000000..4f38a7025f3b5
--- /dev/null
+++ b/packages/elastic-apm-synthtrace/src/lib/utils/dedot.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+import { set } from 'lodash';
+
+export function dedot(source: Record, target: Record) {
+ // eslint-disable-next-line guard-for-in
+ for (const key in source) {
+ const val = source[key as keyof typeof source];
+ set(target, key, val);
+ }
+}
diff --git a/packages/elastic-apm-synthtrace/src/lib/utils/logger.ts b/packages/elastic-apm-synthtrace/src/lib/utils/logger.ts
deleted file mode 100644
index 4afdda74105cf..0000000000000
--- a/packages/elastic-apm-synthtrace/src/lib/utils/logger.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-import { isPromise } from 'util/types';
-
-export enum LogLevel {
- trace = 0,
- debug = 1,
- info = 2,
- error = 3,
-}
-
-function getTimeString() {
- return `[${new Date().toLocaleTimeString()}]`;
-}
-
-export function createLogger(logLevel: LogLevel) {
- function logPerf(name: string, start: bigint) {
- // eslint-disable-next-line no-console
- console.debug(
- getTimeString(),
- `${name}: ${Number(process.hrtime.bigint() - start) / 1000000}ms`
- );
- }
- return {
- perf: (name: string, cb: () => T): T => {
- if (logLevel <= LogLevel.trace) {
- const start = process.hrtime.bigint();
- const val = cb();
- if (isPromise(val)) {
- val.then(() => {
- logPerf(name, start);
- });
- } else {
- logPerf(name, start);
- }
- return val;
- }
- return cb();
- },
- debug: (...args: any[]) => {
- if (logLevel <= LogLevel.debug) {
- // eslint-disable-next-line no-console
- console.debug(getTimeString(), ...args);
- }
- },
- info: (...args: any[]) => {
- if (logLevel <= LogLevel.info) {
- // eslint-disable-next-line no-console
- console.log(getTimeString(), ...args);
- }
- },
- error: (...args: any[]) => {
- if (logLevel <= LogLevel.error) {
- // eslint-disable-next-line no-console
- console.log(getTimeString(), ...args);
- }
- },
- };
-}
-
-export type Logger = ReturnType;
diff --git a/packages/elastic-apm-synthtrace/src/lib/utils/to_elasticsearch_output.ts b/packages/elastic-apm-synthtrace/src/lib/utils/to_elasticsearch_output.ts
new file mode 100644
index 0000000000000..58bafffaff692
--- /dev/null
+++ b/packages/elastic-apm-synthtrace/src/lib/utils/to_elasticsearch_output.ts
@@ -0,0 +1,44 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { Fields } from '../entity';
+import { dedot } from './dedot';
+
+export interface ElasticsearchOutput {
+ _index: string;
+ _source: unknown;
+ timestamp: number;
+}
+
+export function eventsToElasticsearchOutput({
+ events,
+ writeTarget,
+}: {
+ events: Fields[];
+ writeTarget: string;
+}): ElasticsearchOutput[] {
+ return events.map((event) => {
+ const values = {};
+
+ const timestamp = event['@timestamp']!;
+
+ Object.assign(values, event, {
+ '@timestamp': new Date(timestamp).toISOString(),
+ });
+
+ const document = {};
+
+ dedot(values, document);
+
+ return {
+ _index: writeTarget,
+ _source: document,
+ timestamp,
+ };
+ });
+}
diff --git a/packages/elastic-apm-synthtrace/src/scripts/examples/01_simple_trace.ts b/packages/elastic-apm-synthtrace/src/scripts/examples/01_simple_trace.ts
index 8c1f24bd5e64f..559c636cfaeec 100644
--- a/packages/elastic-apm-synthtrace/src/scripts/examples/01_simple_trace.ts
+++ b/packages/elastic-apm-synthtrace/src/scripts/examples/01_simple_trace.ts
@@ -6,75 +6,103 @@
* Side Public License, v 1.
*/
-import { service, timerange, getTransactionMetrics, getSpanDestinationMetrics } from '../..';
-import { getBreakdownMetrics } from '../../lib/utils/get_breakdown_metrics';
+import { apm, timerange } from '../../index';
+import { apmEventsToElasticsearchOutput } from '../../lib/apm/utils/apm_events_to_elasticsearch_output';
+import { getApmWriteTargets } from '../../lib/apm/utils/get_apm_write_targets';
+import { Scenario } from '../scenario';
+import { getCommonServices } from '../utils/get_common_services';
-export default function ({ from, to }: { from: number; to: number }) {
- const numServices = 3;
+const scenario: Scenario = async ({ target, logLevel }) => {
+ const { client, logger } = getCommonServices({ target, logLevel });
+ const writeTargets = await getApmWriteTargets({ client });
- const range = timerange(from, to);
+ return {
+ generate: ({ from, to }) => {
+ const numServices = 3;
- const transactionName = '240rpm/75% 1000ms';
+ const range = timerange(from, to);
- const successfulTimestamps = range.interval('1s').rate(3);
+ const transactionName = '240rpm/75% 1000ms';
- const failedTimestamps = range.interval('1s').rate(1);
+ const successfulTimestamps = range.interval('1s').rate(3);
- return new Array(numServices).fill(undefined).flatMap((_, index) => {
- const instance = service(`opbeans-go-${index}`, 'production', 'go').instance('instance');
+ const failedTimestamps = range.interval('1s').rate(1);
- const successfulTraceEvents = successfulTimestamps.flatMap((timestamp) =>
- instance
- .transaction(transactionName)
- .timestamp(timestamp)
- .duration(1000)
- .success()
- .children(
- instance
- .span('GET apm-*/_search', 'db', 'elasticsearch')
- .duration(1000)
- .success()
- .destination('elasticsearch')
- .timestamp(timestamp),
- instance.span('custom_operation', 'custom').duration(100).success().timestamp(timestamp)
- )
- .serialize()
- );
+ return new Array(numServices).fill(undefined).flatMap((_, index) => {
+ const events = logger.perf('generating_apm_events', () => {
+ const instance = apm
+ .service(`opbeans-go-${index}`, 'production', 'go')
+ .instance('instance');
- const failedTraceEvents = failedTimestamps.flatMap((timestamp) =>
- instance
- .transaction(transactionName)
- .timestamp(timestamp)
- .duration(1000)
- .failure()
- .errors(
- instance.error('[ResponseError] index_not_found_exception').timestamp(timestamp + 50)
- )
- .serialize()
- );
+ const successfulTraceEvents = successfulTimestamps.flatMap((timestamp) =>
+ instance
+ .transaction(transactionName)
+ .timestamp(timestamp)
+ .duration(1000)
+ .success()
+ .children(
+ instance
+ .span('GET apm-*/_search', 'db', 'elasticsearch')
+ .duration(1000)
+ .success()
+ .destination('elasticsearch')
+ .timestamp(timestamp),
+ instance
+ .span('custom_operation', 'custom')
+ .duration(100)
+ .success()
+ .timestamp(timestamp)
+ )
+ .serialize()
+ );
- const metricsets = range
- .interval('30s')
- .rate(1)
- .flatMap((timestamp) =>
- instance
- .appMetrics({
- 'system.memory.actual.free': 800,
- 'system.memory.total': 1000,
- 'system.cpu.total.norm.pct': 0.6,
- 'system.process.cpu.total.norm.pct': 0.7,
+ const failedTraceEvents = failedTimestamps.flatMap((timestamp) =>
+ instance
+ .transaction(transactionName)
+ .timestamp(timestamp)
+ .duration(1000)
+ .failure()
+ .errors(
+ instance
+ .error('[ResponseError] index_not_found_exception')
+ .timestamp(timestamp + 50)
+ )
+ .serialize()
+ );
+
+ const metricsets = range
+ .interval('30s')
+ .rate(1)
+ .flatMap((timestamp) =>
+ instance
+ .appMetrics({
+ 'system.memory.actual.free': 800,
+ 'system.memory.total': 1000,
+ 'system.cpu.total.norm.pct': 0.6,
+ 'system.process.cpu.total.norm.pct': 0.7,
+ })
+ .timestamp(timestamp)
+ .serialize()
+ );
+ return [...successfulTraceEvents, ...failedTraceEvents, ...metricsets];
+ });
+
+ return logger.perf('apm_events_to_es_output', () =>
+ apmEventsToElasticsearchOutput({
+ events: [
+ ...events,
+ ...logger.perf('get_transaction_metrics', () => apm.getTransactionMetrics(events)),
+ ...logger.perf('get_span_destination_metrics', () =>
+ apm.getSpanDestinationMetrics(events)
+ ),
+ ...logger.perf('get_breakdown_metrics', () => apm.getBreakdownMetrics(events)),
+ ],
+ writeTargets,
})
- .timestamp(timestamp)
- .serialize()
- );
- const events = successfulTraceEvents.concat(failedTraceEvents);
+ );
+ });
+ },
+ };
+};
- return [
- ...events,
- ...metricsets,
- ...getTransactionMetrics(events),
- ...getSpanDestinationMetrics(events),
- ...getBreakdownMetrics(events),
- ];
- });
-}
+export default scenario;
diff --git a/packages/elastic-apm-synthtrace/src/scripts/examples/02_kibana_stats.ts b/packages/elastic-apm-synthtrace/src/scripts/examples/02_kibana_stats.ts
new file mode 100644
index 0000000000000..2ba3c4a29c52b
--- /dev/null
+++ b/packages/elastic-apm-synthtrace/src/scripts/examples/02_kibana_stats.ts
@@ -0,0 +1,48 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { stackMonitoring, timerange } from '../../index';
+import { eventsToElasticsearchOutput } from '../../lib/utils/to_elasticsearch_output';
+import { Scenario } from '../scenario';
+import { getCommonServices } from '../utils/get_common_services';
+
+const scenario: Scenario = async ({ target, writeTarget, logLevel }) => {
+ const { logger } = getCommonServices({ target, logLevel });
+
+ if (!writeTarget) {
+ throw new Error('Write target is not defined');
+ }
+
+ return {
+ generate: ({ from, to }) => {
+ const kibanaStats = stackMonitoring.cluster('cluster-01').kibana('kibana-01').stats();
+
+ const range = timerange(from, to);
+ return range
+ .interval('30s')
+ .rate(1)
+ .flatMap((timestamp) => {
+ const events = logger.perf('generating_sm_events', () => {
+ return kibanaStats.timestamp(timestamp).requests(10, 20).serialize();
+ });
+
+ return logger.perf('sm_events_to_es_output', () => {
+ const smEvents = eventsToElasticsearchOutput({ events, writeTarget });
+ smEvents.forEach((event: any) => {
+ const ts = event._source['@timestamp'];
+ delete event._source['@timestamp'];
+ event._source.timestamp = ts;
+ });
+ return smEvents;
+ });
+ });
+ },
+ };
+};
+
+export default scenario;
diff --git a/packages/elastic-apm-synthtrace/src/scripts/examples/03_monitoring.ts b/packages/elastic-apm-synthtrace/src/scripts/examples/03_monitoring.ts
new file mode 100644
index 0000000000000..53dcd820f5519
--- /dev/null
+++ b/packages/elastic-apm-synthtrace/src/scripts/examples/03_monitoring.ts
@@ -0,0 +1,70 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+// Run with: node ./src/scripts/run ./src/scripts/examples/03_monitoring.ts --target=http://elastic:changeme@localhost:9200
+
+import { stackMonitoring, timerange } from '../../index';
+import {
+ ElasticsearchOutput,
+ eventsToElasticsearchOutput,
+} from '../../lib/utils/to_elasticsearch_output';
+import { Scenario } from '../scenario';
+import { getCommonServices } from '../utils/get_common_services';
+import { StackMonitoringFields } from '../../lib/stack_monitoring/stack_monitoring_fields';
+
+// TODO (mat): move this into a function like utils/apm_events_to_elasticsearch_output.ts
+function smEventsToElasticsearchOutput(
+ events: StackMonitoringFields[],
+ writeTarget: string
+): ElasticsearchOutput[] {
+ const smEvents = eventsToElasticsearchOutput({ events, writeTarget });
+ smEvents.forEach((event: any) => {
+ const ts = event._source['@timestamp'];
+ delete event._source['@timestamp'];
+ event._source.timestamp = ts;
+ });
+ return smEvents;
+}
+
+const scenario: Scenario = async ({ target, logLevel }) => {
+ const { logger } = getCommonServices({ target, logLevel });
+
+ return {
+ generate: ({ from, to }) => {
+ const cluster = stackMonitoring.cluster('test-cluster');
+ const clusterStats = cluster.stats();
+ const kibanaStats = cluster.kibana('kibana-01').stats();
+
+ const range = timerange(from, to);
+ return range
+ .interval('10s')
+ .rate(1)
+ .flatMap((timestamp) => {
+ const clusterEvents = logger.perf('generating_es_events', () => {
+ return clusterStats.timestamp(timestamp).indices(115).serialize();
+ });
+ const clusterOutputs = smEventsToElasticsearchOutput(
+ clusterEvents,
+ '.monitoring-es-7-synthtrace'
+ );
+
+ const kibanaEvents = logger.perf('generating_kb_events', () => {
+ return kibanaStats.timestamp(timestamp).requests(10, 20).serialize();
+ });
+ const kibanaOutputs = smEventsToElasticsearchOutput(
+ kibanaEvents,
+ '.monitoring-kibana-7-synthtrace'
+ );
+
+ return [...clusterOutputs, ...kibanaOutputs];
+ });
+ },
+ };
+};
+
+export default scenario;
diff --git a/packages/elastic-apm-synthtrace/src/scripts/run.ts b/packages/elastic-apm-synthtrace/src/scripts/run.ts
index aa427d8e211ae..4078c848aa480 100644
--- a/packages/elastic-apm-synthtrace/src/scripts/run.ts
+++ b/packages/elastic-apm-synthtrace/src/scripts/run.ts
@@ -7,136 +7,109 @@
*/
import datemath from '@elastic/datemath';
import yargs from 'yargs/yargs';
-import { cleanWriteTargets } from '../lib/utils/clean_write_targets';
+import { Argv } from 'yargs';
import { intervalToMs } from './utils/interval_to_ms';
-import { getCommonResources } from './utils/get_common_resources';
import { startHistoricalDataUpload } from './utils/start_historical_data_upload';
import { startLiveDataUpload } from './utils/start_live_data_upload';
+import { parseRunCliFlags } from './utils/parse_run_cli_flags';
+import { getCommonServices } from './utils/get_common_services';
-yargs(process.argv.slice(2))
- .command(
- '*',
- 'Generate data and index into Elasticsearch',
- (y) => {
- return y
- .positional('file', {
- describe: 'File that contains the trace scenario',
- demandOption: true,
- string: true,
- })
- .option('target', {
- describe: 'Elasticsearch target, including username/password',
- demandOption: true,
- string: true,
- })
- .option('from', {
- description: 'The start of the time window',
- })
- .option('to', {
- description: 'The end of the time window',
- })
- .option('live', {
- description: 'Generate and index data continuously',
- boolean: true,
- })
- .option('clean', {
- describe: 'Clean APM indices before indexing new data',
- default: false,
- boolean: true,
- })
- .option('workers', {
- describe: 'Amount of Node.js worker threads',
- default: 5,
- })
- .option('bucketSize', {
- describe: 'Size of bucket for which to generate data',
- default: '15m',
- })
- .option('interval', {
- describe: 'The interval at which to index data',
- default: '10s',
- })
- .option('clientWorkers', {
- describe: 'Number of concurrently connected ES clients',
- default: 5,
- })
- .option('batchSize', {
- describe: 'Number of documents per bulk index request',
- default: 1000,
- })
- .option('logLevel', {
- describe: 'Log level',
- default: 'info',
- })
- .conflicts('to', 'live');
- },
- async (argv) => {
- const file = String(argv.file || argv._[0]);
+function options(y: Argv) {
+ return y
+ .positional('file', {
+ describe: 'File that contains the trace scenario',
+ demandOption: true,
+ string: true,
+ })
+ .option('target', {
+ describe: 'Elasticsearch target, including username/password',
+ demandOption: true,
+ string: true,
+ })
+ .option('from', {
+ description: 'The start of the time window',
+ })
+ .option('to', {
+ description: 'The end of the time window',
+ })
+ .option('live', {
+ description: 'Generate and index data continuously',
+ boolean: true,
+ })
+ .option('clean', {
+ describe: 'Clean APM indices before indexing new data',
+ default: false,
+ boolean: true,
+ })
+ .option('workers', {
+ describe: 'Amount of Node.js worker threads',
+ default: 5,
+ })
+ .option('bucketSize', {
+ describe: 'Size of bucket for which to generate data',
+ default: '15m',
+ })
+ .option('interval', {
+ describe: 'The interval at which to index data',
+ default: '10s',
+ })
+ .option('clientWorkers', {
+ describe: 'Number of concurrently connected ES clients',
+ default: 5,
+ })
+ .option('batchSize', {
+ describe: 'Number of documents per bulk index request',
+ default: 1000,
+ })
+ .option('logLevel', {
+ describe: 'Log level',
+ default: 'info',
+ })
+ .option('writeTarget', {
+ describe: 'Target to index',
+ string: true,
+ })
+ .conflicts('to', 'live');
+}
+
+export type RunCliFlags = ReturnType['argv'];
- const { target, workers, clean, clientWorkers, batchSize } = argv;
+yargs(process.argv.slice(2))
+ .command('*', 'Generate data and index into Elasticsearch', options, async (argv) => {
+ const runOptions = parseRunCliFlags(argv);
- const { scenario, intervalInMs, bucketSizeInMs, logger, writeTargets, client, logLevel } =
- await getCommonResources({
- ...argv,
- file,
- });
+ const { logger } = getCommonServices(runOptions);
- if (clean) {
- await cleanWriteTargets({ writeTargets, client, logger });
- }
+ const to = datemath.parse(String(argv.to ?? 'now'))!.valueOf();
+ const from = argv.from
+ ? datemath.parse(String(argv.from))!.valueOf()
+ : to - intervalToMs('15m');
- const to = datemath.parse(String(argv.to ?? 'now'))!.valueOf();
- const from = argv.from
- ? datemath.parse(String(argv.from))!.valueOf()
- : to - intervalToMs('15m');
+ const live = argv.live;
- const live = argv.live;
+ logger.info(
+ `Starting data generation\n: ${JSON.stringify(
+ {
+ ...runOptions,
+ from: new Date(from).toISOString(),
+ to: new Date(to).toISOString(),
+ },
+ null,
+ 2
+ )}`
+ );
- logger.info(
- `Starting data generation\n: ${JSON.stringify(
- {
- intervalInMs,
- bucketSizeInMs,
- workers,
- target,
- writeTargets,
- from: new Date(from).toISOString(),
- to: new Date(to).toISOString(),
- live,
- },
- null,
- 2
- )}`
- );
+ startHistoricalDataUpload({
+ ...runOptions,
+ from,
+ to,
+ });
- startHistoricalDataUpload({
- from,
- to,
- file,
- bucketSizeInMs,
- client,
- workers,
- clientWorkers,
- batchSize,
- writeTargets,
- logger,
- logLevel,
- target,
+ if (live) {
+ startLiveDataUpload({
+ ...runOptions,
+ start: to,
});
-
- if (live) {
- startLiveDataUpload({
- bucketSizeInMs,
- client,
- intervalInMs,
- logger,
- scenario,
- start: to,
- clientWorkers,
- batchSize,
- writeTargets,
- });
- }
}
- )
+ })
.parse();
diff --git a/packages/elastic-apm-synthtrace/src/scripts/scenario.ts b/packages/elastic-apm-synthtrace/src/scripts/scenario.ts
new file mode 100644
index 0000000000000..c134c08cd8354
--- /dev/null
+++ b/packages/elastic-apm-synthtrace/src/scripts/scenario.ts
@@ -0,0 +1,13 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { ElasticsearchOutput } from '../lib/utils/to_elasticsearch_output';
+import { RunOptions } from './utils/parse_run_cli_flags';
+
+type Generate = (range: { from: number; to: number }) => ElasticsearchOutput[];
+export type Scenario = (options: RunOptions) => Promise<{ generate: Generate }>;
diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/get_common_services.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/get_common_services.ts
new file mode 100644
index 0000000000000..0dee6dbc951eb
--- /dev/null
+++ b/packages/elastic-apm-synthtrace/src/scripts/utils/get_common_services.ts
@@ -0,0 +1,25 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { Client } from '@elastic/elasticsearch';
+import { createLogger, LogLevel } from '../../lib/utils/create_logger';
+
+export function getCommonServices({ target, logLevel }: { target: string; logLevel: LogLevel }) {
+ const client = new Client({
+ node: target,
+ });
+
+ const logger = createLogger(logLevel);
+
+ return {
+ logger,
+ client,
+ };
+}
+
+export type RunServices = ReturnType;
diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/get_scenario.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/get_scenario.ts
index f8c59cff4febc..43f9e4f5e9988 100644
--- a/packages/elastic-apm-synthtrace/src/scripts/utils/get_scenario.ts
+++ b/packages/elastic-apm-synthtrace/src/scripts/utils/get_scenario.ts
@@ -6,10 +6,8 @@
* Side Public License, v 1.
*/
import Path from 'path';
-import { Fields } from '../../lib/entity';
import { Logger } from '../../lib/utils/create_logger';
-
-export type Scenario = (options: { from: number; to: number }) => Fields[];
+import { Scenario } from '../scenario';
export function getScenario({ file, logger }: { file: unknown; logger: Logger }) {
const location = Path.join(process.cwd(), String(file));
diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/get_common_resources.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/parse_run_cli_flags.ts
similarity index 59%
rename from packages/elastic-apm-synthtrace/src/scripts/utils/get_common_resources.ts
rename to packages/elastic-apm-synthtrace/src/scripts/utils/parse_run_cli_flags.ts
index baa1d8758c3c4..5c081707bb75c 100644
--- a/packages/elastic-apm-synthtrace/src/scripts/utils/get_common_resources.ts
+++ b/packages/elastic-apm-synthtrace/src/scripts/utils/parse_run_cli_flags.ts
@@ -6,25 +6,16 @@
* Side Public License, v 1.
*/
-import { Client } from '@elastic/elasticsearch';
-import { getScenario } from './get_scenario';
-import { getWriteTargets } from '../../lib/utils/get_write_targets';
+import { pick } from 'lodash';
+import { LogLevel } from '../../lib/utils/create_logger';
+import { RunCliFlags } from '../run';
import { intervalToMs } from './interval_to_ms';
-import { createLogger, LogLevel } from '../../lib/utils/create_logger';
-export async function getCommonResources({
- file,
- interval,
- bucketSize,
- target,
- logLevel,
-}: {
- file: string;
- interval: string;
- bucketSize: string;
- target: string;
- logLevel: string;
-}) {
+export function parseRunCliFlags(flags: RunCliFlags) {
+ const { file, _, logLevel, interval, bucketSize } = flags;
+
+ const parsedFile = String(file || _[0]);
+
let parsedLogLevel = LogLevel.info;
switch (logLevel) {
case 'trace':
@@ -44,8 +35,6 @@ export async function getCommonResources({
break;
}
- const logger = createLogger(parsedLogLevel);
-
const intervalInMs = intervalToMs(interval);
if (!intervalInMs) {
throw new Error('Invalid interval');
@@ -57,22 +46,13 @@ export async function getCommonResources({
throw new Error('Invalid bucket size');
}
- const client = new Client({
- node: target,
- });
-
- const [scenario, writeTargets] = await Promise.all([
- getScenario({ file, logger }),
- getWriteTargets({ client }),
- ]);
-
return {
- scenario,
- writeTargets,
- logger,
- client,
+ ...pick(flags, 'target', 'workers', 'clientWorkers', 'batchSize', 'writeTarget'),
intervalInMs,
bucketSizeInMs,
logLevel: parsedLogLevel,
+ file: parsedFile,
};
}
+
+export type RunOptions = ReturnType;
diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/start_historical_data_upload.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/start_historical_data_upload.ts
index dc568170a9744..dd848d9f66c63 100644
--- a/packages/elastic-apm-synthtrace/src/scripts/utils/start_historical_data_upload.ts
+++ b/packages/elastic-apm-synthtrace/src/scripts/utils/start_historical_data_upload.ts
@@ -5,41 +5,30 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
-import { Client } from '@elastic/elasticsearch';
import pLimit from 'p-limit';
import Path from 'path';
import { Worker } from 'worker_threads';
-import { ElasticsearchOutputWriteTargets } from '../../lib/output/to_elasticsearch_output';
-import { Logger, LogLevel } from '../../lib/utils/create_logger';
+import { getCommonServices } from './get_common_services';
+import { RunOptions } from './parse_run_cli_flags';
+import { WorkerData } from './upload_next_batch';
export async function startHistoricalDataUpload({
from,
to,
+ intervalInMs,
bucketSizeInMs,
workers,
clientWorkers,
batchSize,
- writeTargets,
logLevel,
- logger,
target,
file,
-}: {
- from: number;
- to: number;
- bucketSizeInMs: number;
- client: Client;
- workers: number;
- clientWorkers: number;
- batchSize: number;
- writeTargets: ElasticsearchOutputWriteTargets;
- logger: Logger;
- logLevel: LogLevel;
- target: string;
- file: string;
-}) {
+ writeTarget,
+}: RunOptions & { from: number; to: number }) {
let requestedUntil: number = from;
+ const { logger } = getCommonServices({ target, logLevel });
+
function processNextBatch() {
const bucketFrom = requestedUntil;
const bucketTo = Math.min(to, bucketFrom + bucketSizeInMs);
@@ -56,17 +45,22 @@ export async function startHistoricalDataUpload({
).toISOString()}`
);
+ const workerData: WorkerData = {
+ bucketFrom,
+ bucketTo,
+ file,
+ logLevel,
+ batchSize,
+ bucketSizeInMs,
+ clientWorkers,
+ intervalInMs,
+ target,
+ workers,
+ writeTarget,
+ };
+
const worker = new Worker(Path.join(__dirname, './upload_next_batch.js'), {
- workerData: {
- bucketFrom,
- bucketTo,
- logLevel,
- writeTargets,
- target,
- file,
- clientWorkers,
- batchSize,
- },
+ workerData,
});
logger.perf('created_worker', () => {
diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/start_live_data_upload.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/start_live_data_upload.ts
index cec0970420d16..3610ffae3c7e6 100644
--- a/packages/elastic-apm-synthtrace/src/scripts/utils/start_live_data_upload.ts
+++ b/packages/elastic-apm-synthtrace/src/scripts/utils/start_live_data_upload.ts
@@ -6,44 +6,49 @@
* Side Public License, v 1.
*/
-import { Client } from '@elastic/elasticsearch';
import { partition } from 'lodash';
-import { Fields } from '../../lib/entity';
-import { ElasticsearchOutputWriteTargets } from '../../lib/output/to_elasticsearch_output';
-import { Scenario } from './get_scenario';
-import { Logger } from '../../lib/utils/create_logger';
+import { getScenario } from './get_scenario';
import { uploadEvents } from './upload_events';
+import { RunOptions } from './parse_run_cli_flags';
+import { getCommonServices } from './get_common_services';
+import { ElasticsearchOutput } from '../../lib/utils/to_elasticsearch_output';
-export function startLiveDataUpload({
+export async function startLiveDataUpload({
+ file,
start,
bucketSizeInMs,
intervalInMs,
clientWorkers,
batchSize,
- writeTargets,
- scenario,
- client,
- logger,
-}: {
- start: number;
- bucketSizeInMs: number;
- intervalInMs: number;
- clientWorkers: number;
- batchSize: number;
- writeTargets: ElasticsearchOutputWriteTargets;
- scenario: Scenario;
- client: Client;
- logger: Logger;
-}) {
- let queuedEvents: Fields[] = [];
+ target,
+ logLevel,
+ workers,
+ writeTarget,
+}: RunOptions & { start: number }) {
+ let queuedEvents: ElasticsearchOutput[] = [];
let requestedUntil: number = start;
+ const { logger, client } = getCommonServices({ target, logLevel });
+
+ const scenario = await getScenario({ file, logger });
+ const { generate } = await scenario({
+ batchSize,
+ bucketSizeInMs,
+ clientWorkers,
+ file,
+ intervalInMs,
+ logLevel,
+ target,
+ workers,
+ writeTarget,
+ });
+
function uploadNextBatch() {
const end = new Date().getTime();
if (end > requestedUntil) {
const bucketFrom = requestedUntil;
const bucketTo = requestedUntil + bucketSizeInMs;
- const nextEvents = scenario({ from: bucketFrom, to: bucketTo });
+ const nextEvents = generate({ from: bucketFrom, to: bucketTo });
logger.debug(
`Requesting ${new Date(bucketFrom).toISOString()} to ${new Date(
bucketTo
@@ -55,7 +60,7 @@ export function startLiveDataUpload({
const [eventsToUpload, eventsToRemainInQueue] = partition(
queuedEvents,
- (event) => event['@timestamp']! <= end
+ (event) => event.timestamp <= end
);
logger.info(`Uploading until ${new Date(end).toISOString()}, events: ${eventsToUpload.length}`);
@@ -64,11 +69,10 @@ export function startLiveDataUpload({
uploadEvents({
events: eventsToUpload,
- client,
clientWorkers,
batchSize,
- writeTargets,
logger,
+ client,
});
}
diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts
index 7382948525986..d68a1b88132bb 100644
--- a/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts
+++ b/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts
@@ -9,11 +9,7 @@ import { Client } from '@elastic/elasticsearch';
import { chunk } from 'lodash';
import pLimit from 'p-limit';
import { inspect } from 'util';
-import { Fields } from '../../lib/entity';
-import {
- ElasticsearchOutputWriteTargets,
- toElasticsearchOutput,
-} from '../../lib/output/to_elasticsearch_output';
+import { ElasticsearchOutput } from '../../lib/utils/to_elasticsearch_output';
import { Logger } from '../../lib/utils/create_logger';
export function uploadEvents({
@@ -21,24 +17,23 @@ export function uploadEvents({
client,
clientWorkers,
batchSize,
- writeTargets,
logger,
}: {
- events: Fields[];
+ events: ElasticsearchOutput[];
client: Client;
clientWorkers: number;
batchSize: number;
- writeTargets: ElasticsearchOutputWriteTargets;
logger: Logger;
}) {
- const esDocuments = logger.perf('to_elasticsearch_output', () => {
- return toElasticsearchOutput({ events, writeTargets });
- });
const fn = pLimit(clientWorkers);
- const batches = chunk(esDocuments, batchSize);
+ const batches = chunk(events, batchSize);
+
+ if (!batches.length) {
+ return;
+ }
- logger.debug(`Uploading ${esDocuments.length} in ${batches.length} batches`);
+ logger.debug(`Uploading ${events.length} in ${batches.length} batches`);
const time = new Date().getTime();
@@ -47,7 +42,6 @@ export function uploadEvents({
fn(() => {
return logger.perf('bulk_upload', () =>
client.bulk({
- require_alias: true,
refresh: false,
body: batch.flatMap((doc) => {
return [{ index: { _index: doc._index } }, doc._source];
diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/upload_next_batch.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/upload_next_batch.ts
index 2fe5f9b6a6d61..c25fc7ca9f1c2 100644
--- a/packages/elastic-apm-synthtrace/src/scripts/utils/upload_next_batch.ts
+++ b/packages/elastic-apm-synthtrace/src/scripts/utils/upload_next_batch.ts
@@ -9,22 +9,37 @@
// add this to workerExample.js file.
import { Client } from '@elastic/elasticsearch';
import { workerData } from 'worker_threads';
-import { ElasticsearchOutputWriteTargets } from '../../lib/output/to_elasticsearch_output';
import { getScenario } from './get_scenario';
import { createLogger, LogLevel } from '../../lib/utils/create_logger';
import { uploadEvents } from './upload_events';
-const { bucketFrom, bucketTo, file, logLevel, target, writeTargets, clientWorkers, batchSize } =
- workerData as {
- bucketFrom: number;
- bucketTo: number;
- file: string;
- logLevel: LogLevel;
- target: string;
- writeTargets: ElasticsearchOutputWriteTargets;
- clientWorkers: number;
- batchSize: number;
- };
+export interface WorkerData {
+ bucketFrom: number;
+ bucketTo: number;
+ file: string;
+ logLevel: LogLevel;
+ clientWorkers: number;
+ batchSize: number;
+ intervalInMs: number;
+ bucketSizeInMs: number;
+ target: string;
+ workers: number;
+ writeTarget?: string;
+}
+
+const {
+ bucketFrom,
+ bucketTo,
+ file,
+ logLevel,
+ clientWorkers,
+ batchSize,
+ intervalInMs,
+ bucketSizeInMs,
+ workers,
+ target,
+ writeTarget,
+} = workerData as WorkerData;
async function uploadNextBatch() {
if (bucketFrom === bucketTo) {
@@ -38,8 +53,20 @@ async function uploadNextBatch() {
const scenario = await logger.perf('get_scenario', () => getScenario({ file, logger }));
+ const { generate } = await scenario({
+ intervalInMs,
+ bucketSizeInMs,
+ logLevel,
+ file,
+ clientWorkers,
+ batchSize,
+ target,
+ workers,
+ writeTarget,
+ });
+
const events = logger.perf('execute_scenario', () =>
- scenario({ from: bucketFrom, to: bucketTo })
+ generate({ from: bucketFrom, to: bucketTo })
);
return uploadEvents({
@@ -47,7 +74,6 @@ async function uploadNextBatch() {
client,
clientWorkers,
batchSize,
- writeTargets,
logger,
});
}
@@ -56,6 +82,11 @@ uploadNextBatch()
.then(() => {
process.exit(0);
})
- .catch(() => {
- process.exit(1);
+ .catch((error) => {
+ // eslint-disable-next-line
+ console.log(error);
+ // make sure error shows up in console before process is killed
+ setTimeout(() => {
+ process.exit(1);
+ }, 100);
});
diff --git a/packages/elastic-apm-synthtrace/src/test/to_elasticsearch_output.test.ts b/packages/elastic-apm-synthtrace/src/test/apm_events_to_elasticsearch_output.test.ts
similarity index 76%
rename from packages/elastic-apm-synthtrace/src/test/to_elasticsearch_output.test.ts
rename to packages/elastic-apm-synthtrace/src/test/apm_events_to_elasticsearch_output.test.ts
index 02d17f6b561ae..b8d0302558925 100644
--- a/packages/elastic-apm-synthtrace/src/test/to_elasticsearch_output.test.ts
+++ b/packages/elastic-apm-synthtrace/src/test/apm_events_to_elasticsearch_output.test.ts
@@ -6,8 +6,8 @@
* Side Public License, v 1.
*/
-import { Fields } from '../lib/entity';
-import { toElasticsearchOutput } from '../lib/output/to_elasticsearch_output';
+import { apmEventsToElasticsearchOutput } from '../lib/apm/utils/apm_events_to_elasticsearch_output';
+import { ApmFields } from '../lib/apm/apm_fields';
const writeTargets = {
transaction: 'apm-8.0.0-transaction',
@@ -16,8 +16,8 @@ const writeTargets = {
error: 'apm-8.0.0-error',
};
-describe('output to elasticsearch', () => {
- let event: Fields;
+describe('output apm events to elasticsearch', () => {
+ let event: ApmFields;
beforeEach(() => {
event = {
@@ -29,13 +29,13 @@ describe('output to elasticsearch', () => {
});
it('properly formats @timestamp', () => {
- const doc = toElasticsearchOutput({ events: [event], writeTargets })[0] as any;
+ const doc = apmEventsToElasticsearchOutput({ events: [event], writeTargets })[0] as any;
expect(doc._source['@timestamp']).toEqual('2020-12-31T23:00:00.000Z');
});
it('formats a nested object', () => {
- const doc = toElasticsearchOutput({ events: [event], writeTargets })[0] as any;
+ const doc = apmEventsToElasticsearchOutput({ events: [event], writeTargets })[0] as any;
expect(doc._source.processor).toEqual({
event: 'transaction',
@@ -44,7 +44,7 @@ describe('output to elasticsearch', () => {
});
it('formats all fields consistently', () => {
- const doc = toElasticsearchOutput({ events: [event], writeTargets })[0] as any;
+ const doc = apmEventsToElasticsearchOutput({ events: [event], writeTargets })[0] as any;
expect(doc._source).toMatchInlineSnapshot(`
Object {
diff --git a/packages/elastic-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts b/packages/elastic-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts
index fc20202e210ff..b38d34266f3ac 100644
--- a/packages/elastic-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts
+++ b/packages/elastic-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts
@@ -6,14 +6,14 @@
* Side Public License, v 1.
*/
-import { service } from '../../lib/service';
+import { apm } from '../../lib/apm';
import { timerange } from '../../lib/timerange';
describe('simple trace', () => {
let events: Array>;
beforeEach(() => {
- const javaService = service('opbeans-java', 'production', 'java');
+ const javaService = apm.service('opbeans-java', 'production', 'java');
const javaInstance = javaService.instance('instance-1');
const range = timerange(
diff --git a/packages/elastic-apm-synthtrace/src/test/scenarios/02_transaction_metrics.test.ts b/packages/elastic-apm-synthtrace/src/test/scenarios/02_transaction_metrics.test.ts
index 58b28f71b9afc..d074bcbf6c1fd 100644
--- a/packages/elastic-apm-synthtrace/src/test/scenarios/02_transaction_metrics.test.ts
+++ b/packages/elastic-apm-synthtrace/src/test/scenarios/02_transaction_metrics.test.ts
@@ -6,15 +6,15 @@
* Side Public License, v 1.
*/
-import { service } from '../../lib/service';
+import { apm } from '../../lib/apm';
import { timerange } from '../../lib/timerange';
-import { getTransactionMetrics } from '../../lib/utils/get_transaction_metrics';
+import { getTransactionMetrics } from '../../lib/apm/utils/get_transaction_metrics';
describe('transaction metrics', () => {
let events: Array>;
beforeEach(() => {
- const javaService = service('opbeans-java', 'production', 'java');
+ const javaService = apm.service('opbeans-java', 'production', 'java');
const javaInstance = javaService.instance('instance-1');
const range = timerange(
diff --git a/packages/elastic-apm-synthtrace/src/test/scenarios/03_span_destination_metrics.test.ts b/packages/elastic-apm-synthtrace/src/test/scenarios/03_span_destination_metrics.test.ts
index 0bf59f044bf03..fe4734c65739c 100644
--- a/packages/elastic-apm-synthtrace/src/test/scenarios/03_span_destination_metrics.test.ts
+++ b/packages/elastic-apm-synthtrace/src/test/scenarios/03_span_destination_metrics.test.ts
@@ -6,15 +6,15 @@
* Side Public License, v 1.
*/
-import { service } from '../../lib/service';
+import { apm } from '../../lib/apm';
import { timerange } from '../../lib/timerange';
-import { getSpanDestinationMetrics } from '../../lib/utils/get_span_destination_metrics';
+import { getSpanDestinationMetrics } from '../../lib/apm/utils/get_span_destination_metrics';
describe('span destination metrics', () => {
let events: Array>;
beforeEach(() => {
- const javaService = service('opbeans-java', 'production', 'java');
+ const javaService = apm.service('opbeans-java', 'production', 'java');
const javaInstance = javaService.instance('instance-1');
const range = timerange(
diff --git a/packages/elastic-apm-synthtrace/src/test/scenarios/04_breakdown_metrics.test.ts b/packages/elastic-apm-synthtrace/src/test/scenarios/04_breakdown_metrics.test.ts
index 469f56b99c5f2..817f0aad9f5e4 100644
--- a/packages/elastic-apm-synthtrace/src/test/scenarios/04_breakdown_metrics.test.ts
+++ b/packages/elastic-apm-synthtrace/src/test/scenarios/04_breakdown_metrics.test.ts
@@ -6,13 +6,13 @@
* Side Public License, v 1.
*/
import { sumBy } from 'lodash';
-import { Fields } from '../../lib/entity';
-import { service } from '../../lib/service';
+import { apm } from '../../lib/apm';
import { timerange } from '../../lib/timerange';
-import { getBreakdownMetrics } from '../../lib/utils/get_breakdown_metrics';
+import { getBreakdownMetrics } from '../../lib/apm/utils/get_breakdown_metrics';
+import { ApmFields } from '../../lib/apm/apm_fields';
describe('breakdown metrics', () => {
- let events: Fields[];
+ let events: ApmFields[];
const LIST_RATE = 2;
const LIST_SPANS = 2;
@@ -21,7 +21,7 @@ describe('breakdown metrics', () => {
const INTERVALS = 6;
beforeEach(() => {
- const javaService = service('opbeans-java', 'production', 'java');
+ const javaService = apm.service('opbeans-java', 'production', 'java');
const javaInstance = javaService.instance('instance-1');
const start = new Date('2021-01-01T00:00:00.000Z').getTime();
diff --git a/packages/elastic-apm-synthtrace/src/test/scenarios/05_transactions_with_errors.test.ts b/packages/elastic-apm-synthtrace/src/test/scenarios/05_transactions_with_errors.test.ts
index 63fdb691e8e5c..b9b12aeab0754 100644
--- a/packages/elastic-apm-synthtrace/src/test/scenarios/05_transactions_with_errors.test.ts
+++ b/packages/elastic-apm-synthtrace/src/test/scenarios/05_transactions_with_errors.test.ts
@@ -6,15 +6,15 @@
* Side Public License, v 1.
*/
import { pick } from 'lodash';
-import { service } from '../../index';
-import { Instance } from '../../lib/instance';
+import { apm } from '../../lib/apm';
+import { Instance } from '../../lib/apm/instance';
describe('transactions with errors', () => {
let instance: Instance;
const timestamp = new Date('2021-01-01T00:00:00.000Z').getTime();
beforeEach(() => {
- instance = service('opbeans-java', 'production', 'java').instance('instance');
+ instance = apm.service('opbeans-java', 'production', 'java').instance('instance');
});
it('generates error events', () => {
const events = instance
diff --git a/packages/elastic-apm-synthtrace/src/test/scenarios/06_application_metrics.test.ts b/packages/elastic-apm-synthtrace/src/test/scenarios/06_application_metrics.test.ts
index 59ca8f0edbe88..7bae1e51f1ab3 100644
--- a/packages/elastic-apm-synthtrace/src/test/scenarios/06_application_metrics.test.ts
+++ b/packages/elastic-apm-synthtrace/src/test/scenarios/06_application_metrics.test.ts
@@ -6,15 +6,15 @@
* Side Public License, v 1.
*/
import { pick } from 'lodash';
-import { service } from '../../index';
-import { Instance } from '../../lib/instance';
+import { apm } from '../../lib/apm';
+import { Instance } from '../../lib/apm/instance';
describe('application metrics', () => {
let instance: Instance;
const timestamp = new Date('2021-01-01T00:00:00.000Z').getTime();
beforeEach(() => {
- instance = service('opbeans-java', 'production', 'java').instance('instance');
+ instance = apm.service('opbeans-java', 'production', 'java').instance('instance');
});
it('generates application metricsets', () => {
const events = instance
diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/synthtrace/opbeans.ts b/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/synthtrace/opbeans.ts
index bd01c83b9cc6e..a6d2454de99fd 100644
--- a/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/synthtrace/opbeans.ts
+++ b/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/synthtrace/opbeans.ts
@@ -4,28 +4,24 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import {
- service,
- browser,
- timerange,
- getChromeUserAgentDefaults,
-} from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
export function opbeans({ from, to }: { from: number; to: number }) {
const range = timerange(from, to);
- const opbeansJava = service('opbeans-java', 'production', 'java')
+ const opbeansJava = apm
+ .service('opbeans-java', 'production', 'java')
.instance('opbeans-java-prod-1')
.podId('opbeans-java-prod-1-pod');
- const opbeansNode = service('opbeans-node', 'production', 'nodejs').instance(
- 'opbeans-node-prod-1'
- );
+ const opbeansNode = apm
+ .service('opbeans-node', 'production', 'nodejs')
+ .instance('opbeans-node-prod-1');
- const opbeansRum = browser(
+ const opbeansRum = apm.browser(
'opbeans-rum',
'production',
- getChromeUserAgentDefaults()
+ apm.getChromeUserAgentDefaults()
);
return [
diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/generate_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/generate_data.ts
index 7f1c14ac25513..7215d2f435e1a 100644
--- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/generate_data.ts
+++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/generate_data.ts
@@ -4,18 +4,19 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { service, timerange } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
export function generateData({ from, to }: { from: number; to: number }) {
const range = timerange(from, to);
- const opbeansJava = service('opbeans-java', 'production', 'java')
+ const opbeansJava = apm
+ .service('opbeans-java', 'production', 'java')
.instance('opbeans-java-prod-1')
.podId('opbeans-java-prod-1-pod');
- const opbeansNode = service('opbeans-node', 'production', 'nodejs').instance(
- 'opbeans-node-prod-1'
- );
+ const opbeansNode = apm
+ .service('opbeans-node', 'production', 'nodejs')
+ .instance('opbeans-node-prod-1');
return [
...range
diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/header_filters/generate_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/header_filters/generate_data.ts
index 9ebaa1747d909..d4a2cdf103027 100644
--- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/header_filters/generate_data.ts
+++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/header_filters/generate_data.ts
@@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { service, timerange } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
export function generateData({
from,
@@ -17,13 +17,14 @@ export function generateData({
}) {
const range = timerange(from, to);
- const service1 = service(specialServiceName, 'production', 'java')
+ const service1 = apm
+ .service(specialServiceName, 'production', 'java')
.instance('service-1-prod-1')
.podId('service-1-prod-1-pod');
- const opbeansNode = service('opbeans-node', 'production', 'nodejs').instance(
- 'opbeans-node-prod-1'
- );
+ const opbeansNode = apm
+ .service('opbeans-node', 'production', 'nodejs')
+ .instance('opbeans-node-prod-1');
return [
...range
diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/plugins/index.ts b/x-pack/plugins/apm/ftr_e2e/cypress/plugins/index.ts
index 350d90ccb3fe4..90cf964691274 100644
--- a/x-pack/plugins/apm/ftr_e2e/cypress/plugins/index.ts
+++ b/x-pack/plugins/apm/ftr_e2e/cypress/plugins/index.ts
@@ -6,8 +6,7 @@
*/
import Fs from 'fs';
import { Client, HttpConnection } from '@elastic/elasticsearch';
-import { SynthtraceEsClient } from '@elastic/apm-synthtrace';
-import { createLogger, LogLevel } from '@elastic/apm-synthtrace';
+import { apm, createLogger, LogLevel } from '@elastic/apm-synthtrace';
import { CA_CERT_PATH } from '@kbn/dev-utils';
// ***********************************************************
@@ -41,7 +40,7 @@ const plugin: Cypress.PluginConfig = (on, config) => {
...(isCloud ? { tls: { ca: Fs.readFileSync(CA_CERT_PATH, 'utf-8') } } : {}),
});
- const synthtraceEsClient = new SynthtraceEsClient(
+ const synthtraceEsClient = new apm.ApmSynthtraceEsClient(
client,
createLogger(LogLevel.info)
);
diff --git a/x-pack/test/apm_api_integration/common/synthtrace_es_client_service.ts b/x-pack/test/apm_api_integration/common/synthtrace_es_client_service.ts
index 14e746a55a3d1..0ff00d415e7ac 100644
--- a/x-pack/test/apm_api_integration/common/synthtrace_es_client_service.ts
+++ b/x-pack/test/apm_api_integration/common/synthtrace_es_client_service.ts
@@ -5,11 +5,11 @@
* 2.0.
*/
-import { SynthtraceEsClient, createLogger, LogLevel } from '@elastic/apm-synthtrace';
+import { apm, createLogger, LogLevel } from '@elastic/apm-synthtrace';
import { InheritedFtrProviderContext } from './ftr_provider_context';
export async function synthtraceEsClientService(context: InheritedFtrProviderContext) {
const es = context.getService('es');
- return new SynthtraceEsClient(es, createLogger(LogLevel.info));
+ return new apm.ApmSynthtraceEsClient(es, createLogger(LogLevel.info));
}
diff --git a/x-pack/test/apm_api_integration/tests/dependencies/generate_data.ts b/x-pack/test/apm_api_integration/tests/dependencies/generate_data.ts
index e36e99b447aa3..21af5d91d14e1 100644
--- a/x-pack/test/apm_api_integration/tests/dependencies/generate_data.ts
+++ b/x-pack/test/apm_api_integration/tests/dependencies/generate_data.ts
@@ -4,8 +4,8 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { service, timerange } from '@elastic/apm-synthtrace';
-import type { SynthtraceEsClient } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
+import type { ApmSynthtraceEsClient } from '@elastic/apm-synthtrace';
export const dataConfig = {
rate: 20,
@@ -26,11 +26,11 @@ export async function generateData({
start,
end,
}: {
- synthtraceEsClient: SynthtraceEsClient;
+ synthtraceEsClient: ApmSynthtraceEsClient;
start: number;
end: number;
}) {
- const instance = service('synth-go', 'production', 'go').instance('instance-a');
+ const instance = apm.service('synth-go', 'production', 'go').instance('instance-a');
const { rate, transaction, span } = dataConfig;
await synthtraceEsClient.index(
diff --git a/x-pack/test/apm_api_integration/tests/error_rate/service_apis.spec.ts b/x-pack/test/apm_api_integration/tests/error_rate/service_apis.spec.ts
index 7aca21f4fc7f6..f1aefa06304a1 100644
--- a/x-pack/test/apm_api_integration/tests/error_rate/service_apis.spec.ts
+++ b/x-pack/test/apm_api_integration/tests/error_rate/service_apis.spec.ts
@@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { service, timerange } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
import expect from '@kbn/expect';
import { mean, meanBy, sumBy } from 'lodash';
import { LatencyAggregationType } from '../../../../plugins/apm/common/latency_aggregation_types';
@@ -121,9 +121,9 @@ export default function ApiTest({ getService }: FtrProviderContext) {
const GO_PROD_ID_RATE = 50;
const GO_PROD_ID_ERROR_RATE = 50;
before(async () => {
- const serviceGoProdInstance = service(serviceName, 'production', 'go').instance(
- 'instance-a'
- );
+ const serviceGoProdInstance = apm
+ .service(serviceName, 'production', 'go')
+ .instance('instance-a');
const transactionNameProductList = 'GET /api/product/list';
const transactionNameProductId = 'GET /api/product/:id';
diff --git a/x-pack/test/apm_api_integration/tests/errors/error_group_list.spec.ts b/x-pack/test/apm_api_integration/tests/errors/error_group_list.spec.ts
index ce27183e84ca1..421b536c6d5a5 100644
--- a/x-pack/test/apm_api_integration/tests/errors/error_group_list.spec.ts
+++ b/x-pack/test/apm_api_integration/tests/errors/error_group_list.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
import expect from '@kbn/expect';
-import { service, timerange } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
import {
APIClientRequestParamsOf,
APIReturnType,
@@ -72,7 +72,9 @@ export default function ApiTest({ getService }: FtrProviderContext) {
};
before(async () => {
- const serviceInstance = service(serviceName, 'production', 'go').instance('instance-a');
+ const serviceInstance = apm
+ .service(serviceName, 'production', 'go')
+ .instance('instance-a');
await synthtraceEsClient.index([
...timerange(start, end)
diff --git a/x-pack/test/apm_api_integration/tests/errors/generate_data.ts b/x-pack/test/apm_api_integration/tests/errors/generate_data.ts
index f7874b1c61495..b9ac77ca34425 100644
--- a/x-pack/test/apm_api_integration/tests/errors/generate_data.ts
+++ b/x-pack/test/apm_api_integration/tests/errors/generate_data.ts
@@ -4,7 +4,8 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { service, SynthtraceEsClient, timerange } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
+import type { ApmSynthtraceEsClient } from '@elastic/apm-synthtrace';
export const config = {
appleTransaction: {
@@ -25,12 +26,12 @@ export async function generateData({
start,
end,
}: {
- synthtraceEsClient: SynthtraceEsClient;
+ synthtraceEsClient: ApmSynthtraceEsClient;
serviceName: string;
start: number;
end: number;
}) {
- const serviceGoProdInstance = service(serviceName, 'production', 'go').instance('instance-a');
+ const serviceGoProdInstance = apm.service(serviceName, 'production', 'go').instance('instance-a');
const interval = '1m';
diff --git a/x-pack/test/apm_api_integration/tests/latency/service_apis.spec.ts b/x-pack/test/apm_api_integration/tests/latency/service_apis.spec.ts
index e87f03efeeefe..1c0185c396557 100644
--- a/x-pack/test/apm_api_integration/tests/latency/service_apis.spec.ts
+++ b/x-pack/test/apm_api_integration/tests/latency/service_apis.spec.ts
@@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { service, timerange } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
import expect from '@kbn/expect';
import { meanBy, sumBy } from 'lodash';
import { LatencyAggregationType } from '../../../../plugins/apm/common/latency_aggregation_types';
@@ -123,12 +123,13 @@ export default function ApiTest({ getService }: FtrProviderContext) {
const GO_PROD_DURATION = 1000;
const GO_DEV_DURATION = 500;
before(async () => {
- const serviceGoProdInstance = service(serviceName, 'production', 'go').instance(
- 'instance-a'
- );
- const serviceGoDevInstance = service(serviceName, 'development', 'go').instance(
- 'instance-b'
- );
+ const serviceGoProdInstance = apm
+ .service(serviceName, 'production', 'go')
+ .instance('instance-a');
+ const serviceGoDevInstance = apm
+ .service(serviceName, 'development', 'go')
+ .instance('instance-b');
+
await synthtraceEsClient.index([
...timerange(start, end)
.interval('1m')
diff --git a/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.spec.ts b/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.spec.ts
index 6b6d61fdb1d35..4c1e1850c177e 100644
--- a/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.spec.ts
+++ b/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.spec.ts
@@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { service, timerange } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
import expect from '@kbn/expect';
import { meanBy, sumBy } from 'lodash';
import { FtrProviderContext } from '../../common/ftr_provider_context';
@@ -92,15 +92,16 @@ export default function ApiTest({ getService }: FtrProviderContext) {
const GO_DEV_RATE = 5;
const JAVA_PROD_RATE = 45;
before(async () => {
- const serviceGoProdInstance = service('synth-go', 'production', 'go').instance(
- 'instance-a'
- );
- const serviceGoDevInstance = service('synth-go', 'development', 'go').instance(
- 'instance-b'
- );
- const serviceJavaInstance = service('synth-java', 'production', 'java').instance(
- 'instance-c'
- );
+ const serviceGoProdInstance = apm
+ .service('synth-go', 'production', 'go')
+ .instance('instance-a');
+ const serviceGoDevInstance = apm
+ .service('synth-go', 'development', 'go')
+ .instance('instance-b');
+
+ const serviceJavaInstance = apm
+ .service('synth-java', 'production', 'java')
+ .instance('instance-c');
await synthtraceEsClient.index([
...timerange(start, end)
diff --git a/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.spec.ts b/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.spec.ts
index 5800ddf00480a..a60da5f2bd5c0 100644
--- a/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.spec.ts
+++ b/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.spec.ts
@@ -8,7 +8,7 @@
import expect from '@kbn/expect';
import { pick, sortBy } from 'lodash';
import moment from 'moment';
-import { service, timerange } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
import { APIReturnType } from '../../../../plugins/apm/public/services/rest/createCallApmApi';
import { isFiniteNumber } from '../../../../plugins/apm/common/utils/is_finite_number';
import { FtrProviderContext } from '../../common/ftr_provider_context';
@@ -298,8 +298,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
const rangeEnd = new Date('2021-01-01T12:15:00.000Z').getTime() - 1;
before(async () => {
- const goService = service('opbeans-go', 'production', 'go');
- const javaService = service('opbeans-java', 'production', 'java');
+ const goService = apm.service('opbeans-go', 'production', 'go');
+ const javaService = apm.service('opbeans-java', 'production', 'java');
const goInstanceA = goService.instance('go-instance-a');
const goInstanceB = goService.instance('go-instance-b');
diff --git a/x-pack/test/apm_api_integration/tests/services/error_groups/generate_data.ts b/x-pack/test/apm_api_integration/tests/services/error_groups/generate_data.ts
index f02f1e7493ff0..ef77cd4003a16 100644
--- a/x-pack/test/apm_api_integration/tests/services/error_groups/generate_data.ts
+++ b/x-pack/test/apm_api_integration/tests/services/error_groups/generate_data.ts
@@ -4,8 +4,8 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { service, timerange } from '@elastic/apm-synthtrace';
-import type { SynthtraceEsClient } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
+import type { ApmSynthtraceEsClient } from '@elastic/apm-synthtrace';
export const config = {
PROD_LIST_RATE: 75,
@@ -22,12 +22,12 @@ export async function generateData({
start,
end,
}: {
- synthtraceEsClient: SynthtraceEsClient;
+ synthtraceEsClient: ApmSynthtraceEsClient;
serviceName: string;
start: number;
end: number;
}) {
- const serviceGoProdInstance = service(serviceName, 'production', 'go').instance('instance-a');
+ const serviceGoProdInstance = apm.service(serviceName, 'production', 'go').instance('instance-a');
const transactionNameProductList = 'GET /api/product/list';
const transactionNameProductId = 'GET /api/product/:id';
diff --git a/x-pack/test/apm_api_integration/tests/services/throughput.spec.ts b/x-pack/test/apm_api_integration/tests/services/throughput.spec.ts
index 077119156c641..87c1f5a04ed25 100644
--- a/x-pack/test/apm_api_integration/tests/services/throughput.spec.ts
+++ b/x-pack/test/apm_api_integration/tests/services/throughput.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { service, timerange } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
import expect from '@kbn/expect';
import { first, last, meanBy } from 'lodash';
import moment from 'moment';
@@ -73,16 +73,16 @@ export default function ApiTest({ getService }: FtrProviderContext) {
const JAVA_PROD_RATE = 45;
before(async () => {
- const serviceGoProdInstance = service(serviceName, 'production', 'go').instance(
- 'instance-a'
- );
- const serviceGoDevInstance = service(serviceName, 'development', 'go').instance(
- 'instance-b'
- );
-
- const serviceJavaInstance = service('synth-java', 'development', 'java').instance(
- 'instance-c'
- );
+ const serviceGoProdInstance = apm
+ .service(serviceName, 'production', 'go')
+ .instance('instance-a');
+ const serviceGoDevInstance = apm
+ .service(serviceName, 'development', 'go')
+ .instance('instance-b');
+
+ const serviceJavaInstance = apm
+ .service('synth-java', 'development', 'java')
+ .instance('instance-c');
await synthtraceEsClient.index([
...timerange(start, end)
diff --git a/x-pack/test/apm_api_integration/tests/services/top_services.spec.ts b/x-pack/test/apm_api_integration/tests/services/top_services.spec.ts
index 375206d0a0bc0..d4dacadfee034 100644
--- a/x-pack/test/apm_api_integration/tests/services/top_services.spec.ts
+++ b/x-pack/test/apm_api_integration/tests/services/top_services.spec.ts
@@ -7,7 +7,7 @@
import expect from '@kbn/expect';
import { sortBy } from 'lodash';
-import { service, timerange } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
import { APIReturnType } from '../../../../plugins/apm/public/services/rest/createCallApmApi';
import { PromiseReturnType } from '../../../../plugins/observability/typings/common';
import { FtrProviderContext } from '../../common/ftr_provider_context';
@@ -65,21 +65,17 @@ export default function ApiTest({ getService }: FtrProviderContext) {
const transactionInterval = range.interval('1s');
const metricInterval = range.interval('30s');
- const multipleEnvServiceProdInstance = service(
- 'multiple-env-service',
- 'production',
- 'go'
- ).instance('multiple-env-service-production');
-
- const multipleEnvServiceDevInstance = service(
- 'multiple-env-service',
- 'development',
- 'go'
- ).instance('multiple-env-service-development');
-
- const metricOnlyInstance = service('metric-only-service', 'production', 'java').instance(
- 'metric-only-production'
- );
+ const multipleEnvServiceProdInstance = apm
+ .service('multiple-env-service', 'production', 'go')
+ .instance('multiple-env-service-production');
+
+ const multipleEnvServiceDevInstance = apm
+ .service('multiple-env-service', 'development', 'go')
+ .instance('multiple-env-service-development');
+
+ const metricOnlyInstance = apm
+ .service('metric-only-service', 'production', 'java')
+ .instance('metric-only-production');
const config = {
multiple: {
diff --git a/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.spec.ts b/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.spec.ts
index 1b2c919f538a7..bc2118f55f650 100644
--- a/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.spec.ts
+++ b/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.spec.ts
@@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { service, timerange } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
import expect from '@kbn/expect';
import { meanBy, sumBy } from 'lodash';
import { BackendNode, ServiceNode } from '../../../../plugins/apm/common/connections';
@@ -94,12 +94,12 @@ export default function ApiTest({ getService }: FtrProviderContext) {
const GO_PROD_RATE = 75;
const JAVA_PROD_RATE = 25;
before(async () => {
- const serviceGoProdInstance = service('synth-go', 'production', 'go').instance(
- 'instance-a'
- );
- const serviceJavaInstance = service('synth-java', 'development', 'java').instance(
- 'instance-c'
- );
+ const serviceGoProdInstance = apm
+ .service('synth-go', 'production', 'go')
+ .instance('instance-a');
+ const serviceJavaInstance = apm
+ .service('synth-java', 'development', 'java')
+ .instance('instance-c');
await synthtraceEsClient.index([
...timerange(start, end)
diff --git a/x-pack/test/apm_api_integration/tests/throughput/service_apis.spec.ts b/x-pack/test/apm_api_integration/tests/throughput/service_apis.spec.ts
index 7318fc449fcdb..3492d2967a356 100644
--- a/x-pack/test/apm_api_integration/tests/throughput/service_apis.spec.ts
+++ b/x-pack/test/apm_api_integration/tests/throughput/service_apis.spec.ts
@@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { service, timerange } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
import expect from '@kbn/expect';
import { meanBy, sumBy } from 'lodash';
import { LatencyAggregationType } from '../../../../plugins/apm/common/latency_aggregation_types';
@@ -109,12 +109,13 @@ export default function ApiTest({ getService }: FtrProviderContext) {
const GO_PROD_RATE = 80;
const GO_DEV_RATE = 20;
before(async () => {
- const serviceGoProdInstance = service(serviceName, 'production', 'go').instance(
- 'instance-a'
- );
- const serviceGoDevInstance = service(serviceName, 'development', 'go').instance(
- 'instance-b'
- );
+ const serviceGoProdInstance = apm
+ .service(serviceName, 'production', 'go')
+ .instance('instance-a');
+ const serviceGoDevInstance = apm
+ .service(serviceName, 'development', 'go')
+ .instance('instance-b');
+
await synthtraceEsClient.index([
...timerange(start, end)
.interval('1m')
diff --git a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.spec.ts b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.spec.ts
index 72a0cdbbee48f..be60c655ce50d 100644
--- a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.spec.ts
+++ b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.spec.ts
@@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { service, timerange } from '@elastic/apm-synthtrace';
+import { apm, timerange } from '@elastic/apm-synthtrace';
import expect from '@kbn/expect';
import { first, isEmpty, last, meanBy } from 'lodash';
import moment from 'moment';
@@ -84,9 +84,9 @@ export default function ApiTest({ getService }: FtrProviderContext) {
const GO_PROD_RATE = 75;
const GO_PROD_ERROR_RATE = 25;
before(async () => {
- const serviceGoProdInstance = service(serviceName, 'production', 'go').instance(
- 'instance-a'
- );
+ const serviceGoProdInstance = apm
+ .service(serviceName, 'production', 'go')
+ .instance('instance-a');
const transactionName = 'GET /api/product/list';
From e570b8783de73ad95c8d041e9871d569606b431b Mon Sep 17 00:00:00 2001
From: Tim Roes
Date: Mon, 29 Nov 2021 11:55:44 +0100
Subject: [PATCH 02/47] Show information when doc summary cuts fields (#119744)
* Show information when doc summary cuts fields
* Fix jest tests
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../get_render_cell_value.test.tsx | 2 +-
.../doc_table/lib/row_formatter.tsx | 7 +++++--
.../discover/public/utils/format_hit.test.ts | 4 ++++
.../discover/public/utils/format_hit.ts | 20 +++++++++++++++++--
src/plugins/discover/server/ui_settings.ts | 2 +-
.../translations/translations/ja-JP.json | 1 -
.../translations/translations/zh-CN.json | 1 -
7 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/src/plugins/discover/public/components/discover_grid/get_render_cell_value.test.tsx b/src/plugins/discover/public/components/discover_grid/get_render_cell_value.test.tsx
index 260cbf42c4d8e..e97a2b2901f33 100644
--- a/src/plugins/discover/public/components/discover_grid/get_render_cell_value.test.tsx
+++ b/src/plugins/discover/public/components/discover_grid/get_render_cell_value.test.tsx
@@ -23,7 +23,7 @@ jest.mock('../../../../kibana_react/public', () => ({
jest.mock('../../kibana_services', () => ({
getServices: () => ({
uiSettings: {
- get: jest.fn(),
+ get: jest.fn((key) => key === 'discover:maxDocFieldsDisplayed' && 200),
},
fieldFormats: {
getDefaultInstance: jest.fn(() => ({ convert: (value: unknown) => (value ? value : '-') })),
diff --git a/src/plugins/discover/public/components/doc_table/lib/row_formatter.tsx b/src/plugins/discover/public/components/doc_table/lib/row_formatter.tsx
index 0ec611a307513..53ede4e3f710e 100644
--- a/src/plugins/discover/public/components/doc_table/lib/row_formatter.tsx
+++ b/src/plugins/discover/public/components/doc_table/lib/row_formatter.tsx
@@ -16,14 +16,17 @@ import { formatHit } from '../../../utils/format_hit';
import './row_formatter.scss';
interface Props {
- defPairs: Array<[string, string]>;
+ defPairs: Array;
}
const TemplateComponent = ({ defPairs }: Props) => {
return (
{defPairs.map((pair, idx) => (
- - {pair[0]}:
+ -
+ {pair[0]}
+ {!!pair[1] && ':'}
+
- {
(dataViewMock.getFormatterForField as jest.Mock).mockReturnValue({
convert: (value: unknown) => `formatted:${value}`,
});
+ (discoverServiceMock.uiSettings.get as jest.Mock).mockImplementation(
+ (key) => key === MAX_DOC_FIELDS_DISPLAYED && 220
+ );
});
afterEach(() => {
@@ -72,6 +75,7 @@ describe('formatHit', () => {
expect(formatted).toEqual([
['extension', 'formatted:png'],
['message', 'formatted:foobar'],
+ ['and 3 more fields', ''],
]);
});
diff --git a/src/plugins/discover/public/utils/format_hit.ts b/src/plugins/discover/public/utils/format_hit.ts
index b1bbfcd5aa878..4a06162714a2a 100644
--- a/src/plugins/discover/public/utils/format_hit.ts
+++ b/src/plugins/discover/public/utils/format_hit.ts
@@ -7,6 +7,7 @@
*/
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
+import { i18n } from '@kbn/i18n';
import { DataView, flattenHit } from '../../../data/common';
import { MAX_DOC_FIELDS_DISPLAYED } from '../../common';
import { getServices } from '../kibana_services';
@@ -14,7 +15,7 @@ import { formatFieldValue } from './format_value';
const formattedHitCache = new WeakMap();
-type FormattedHit = Array<[fieldName: string, formattedValue: string]>;
+type FormattedHit = Array;
/**
* Returns a formatted document in form of key/value pairs of the fields name and a formatted value.
@@ -61,7 +62,22 @@ export function formatHit(
}
});
const maxEntries = getServices().uiSettings.get(MAX_DOC_FIELDS_DISPLAYED);
- const formatted = [...highlightPairs, ...sourcePairs].slice(0, maxEntries);
+ const pairs = [...highlightPairs, ...sourcePairs];
+ const formatted =
+ // If document has more formatted fields than configured via MAX_DOC_FIELDS_DISPLAYED we cut
+ // off additional fields and instead show a summary how many more field exists.
+ pairs.length <= maxEntries
+ ? pairs
+ : [
+ ...pairs.slice(0, maxEntries),
+ [
+ i18n.translate('discover.utils.formatHit.moreFields', {
+ defaultMessage: 'and {count} more {count, plural, one {field} other {fields}}',
+ values: { count: pairs.length - maxEntries },
+ }),
+ '',
+ ] as const,
+ ];
formattedHitCache.set(hit, formatted);
return formatted;
}
diff --git a/src/plugins/discover/server/ui_settings.ts b/src/plugins/discover/server/ui_settings.ts
index e9aa51a7384b2..a58770ed1c1d8 100644
--- a/src/plugins/discover/server/ui_settings.ts
+++ b/src/plugins/discover/server/ui_settings.ts
@@ -49,7 +49,7 @@ export const getUiSettings: () => Record = () => ({
}),
value: 200,
description: i18n.translate('discover.advancedSettings.maxDocFieldsDisplayedText', {
- defaultMessage: 'Maximum number of fields rendered in the document column',
+ defaultMessage: 'Maximum number of fields rendered in the document summary',
}),
category: ['discover'],
schema: schema.number(),
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index b983eaaeaae47..9fc49535e18ef 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -1583,7 +1583,6 @@
"discover.advancedSettings.docTableHideTimeColumnTitle": "「時刻」列を非表示",
"discover.advancedSettings.fieldsPopularLimitText": "最も頻繁に使用されるフィールドのトップNを表示します",
"discover.advancedSettings.fieldsPopularLimitTitle": "頻繁に使用されるフィールドの制限",
- "discover.advancedSettings.maxDocFieldsDisplayedText": "ドキュメント列でレンダリングされたフィールドの最大数",
"discover.advancedSettings.maxDocFieldsDisplayedTitle": "表示される最大ドキュメントフィールド数",
"discover.advancedSettings.sampleSizeText": "表に表示する行数です",
"discover.advancedSettings.sampleSizeTitle": "行数",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 8b0686d0a309f..102051ac2a9df 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -1595,7 +1595,6 @@
"discover.advancedSettings.docTableHideTimeColumnTitle": "隐藏“时间”列",
"discover.advancedSettings.fieldsPopularLimitText": "要显示的排名前 N 最常见字段",
"discover.advancedSettings.fieldsPopularLimitTitle": "常见字段限制",
- "discover.advancedSettings.maxDocFieldsDisplayedText": "在文档列中渲染的最大字段数目",
"discover.advancedSettings.maxDocFieldsDisplayedTitle": "显示的最大文档字段数",
"discover.advancedSettings.sampleSizeText": "要在表中显示的行数目",
"discover.advancedSettings.sampleSizeTitle": "行数目",
From ee3cb46a682c918004b51cf2237e699c0b7b8936 Mon Sep 17 00:00:00 2001
From: Faisal Kanout
Date: Mon, 29 Nov 2021 15:03:33 +0300
Subject: [PATCH 03/47] [8.0][RAC] 117686 replace alert workflow status in
alerts view (#118723)
* Add AlertStatus types
* Add alert status filter component
* Remove Filter in action from the t grid table
* Update group buttons to applied Alert status filter instead of Workflow status
* Keep the Alert status button in sync when typing and first page load
* Fix data test object name and translation keys label
* Add possibility to hide the bulk actions
* Update how hide the bulk actions
* Fix showCheckboxes hardcoded "true". Instead use the leadingControlColumns props
* Hide the leading checkboxes in the T Grid with the bulk actions
* Update showCheckboxes to false
* Fix test as the leading checkboxes are hidden
* Update tests
* Get back disabledCellActions as it's required by T Grid
* Update tests to skip test related to Workflow action buttons
* Skip workflow tests
* Revert fix showCheckboxes
* Remove unused imports
* Revert the o11y tests as the checkBoxes fix is reverted
* Reactive the tests effected by checkBoxes
* Skip alert workflow status
* [Code review] use predefined types
* Remove unused prop
* Use the alert-data index name in the RegEx
* Detect * in KQL as "show al"l alert filter
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../plugins/observability/common/typings.ts | 13 +++
.../pages/alerts/alerts_status_filter.tsx | 79 +++++++++++++++
.../pages/alerts/alerts_table_t_grid.tsx | 98 +++++++++----------
.../public/pages/alerts/index.tsx | 86 ++++++++++------
.../apps/observability/alerts/index.ts | 2 +-
.../alerts/state_synchronization.ts | 12 +--
.../observability/alerts/workflow_status.ts | 3 +-
7 files changed, 202 insertions(+), 91 deletions(-)
create mode 100644 x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx
diff --git a/x-pack/plugins/observability/common/typings.ts b/x-pack/plugins/observability/common/typings.ts
index bccb0f4491009..1e247fd06739f 100644
--- a/x-pack/plugins/observability/common/typings.ts
+++ b/x-pack/plugins/observability/common/typings.ts
@@ -7,6 +7,10 @@
import * as t from 'io-ts';
export type Maybe = T | null | undefined;
+import {
+ ALERT_STATUS_ACTIVE,
+ ALERT_STATUS_RECOVERED,
+} from '@kbn/rule-data-utils/alerts_as_data_status';
export const alertWorkflowStatusRt = t.keyof({
open: null,
@@ -25,3 +29,12 @@ export interface ApmIndicesConfig {
apmAgentConfigurationIndex: string;
apmCustomLinkIndex: string;
}
+export type AlertStatusFilterButton =
+ | typeof ALERT_STATUS_ACTIVE
+ | typeof ALERT_STATUS_RECOVERED
+ | '';
+export interface AlertStatusFilter {
+ status: AlertStatusFilterButton;
+ query: string;
+ label: string;
+}
diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx
new file mode 100644
index 0000000000000..38c753bbebf3b
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx
@@ -0,0 +1,79 @@
+/*
+ * 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 { EuiButtonGroup, EuiButtonGroupOptionProps } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import React from 'react';
+import {
+ ALERT_STATUS_ACTIVE,
+ ALERT_STATUS_RECOVERED,
+} from '@kbn/rule-data-utils/alerts_as_data_status';
+import { ALERT_STATUS } from '@kbn/rule-data-utils/technical_field_names';
+import { AlertStatusFilterButton } from '../../../common/typings';
+import { AlertStatusFilter } from '../../../common/typings';
+
+export interface AlertStatusFilterProps {
+ status: AlertStatusFilterButton;
+ onChange: (id: string, value: string) => void;
+}
+
+export const allAlerts: AlertStatusFilter = {
+ status: '',
+ query: '',
+ label: i18n.translate('xpack.observability.alerts.alertStatusFilter.showAll', {
+ defaultMessage: 'Show all',
+ }),
+};
+
+export const activeAlerts: AlertStatusFilter = {
+ status: ALERT_STATUS_ACTIVE,
+ query: `${ALERT_STATUS}: "${ALERT_STATUS_ACTIVE}"`,
+ label: i18n.translate('xpack.observability.alerts.alertStatusFilter.active', {
+ defaultMessage: 'Active',
+ }),
+};
+
+export const recoveredAlerts: AlertStatusFilter = {
+ status: ALERT_STATUS_RECOVERED,
+ query: `${ALERT_STATUS}: "${ALERT_STATUS_RECOVERED}"`,
+ label: i18n.translate('xpack.observability.alerts.alertStatusFilter.recovered', {
+ defaultMessage: 'Recovered',
+ }),
+};
+
+const options: EuiButtonGroupOptionProps[] = [
+ {
+ id: allAlerts.status,
+ label: allAlerts.label,
+ value: allAlerts.query,
+ 'data-test-subj': 'alert-status-filter-show-all-button',
+ },
+ {
+ id: activeAlerts.status,
+ label: activeAlerts.label,
+ value: activeAlerts.query,
+ 'data-test-subj': 'alert-status-filter-active-button',
+ },
+ {
+ id: recoveredAlerts.status,
+ label: recoveredAlerts.label,
+ value: recoveredAlerts.query,
+ 'data-test-subj': 'alert-status-filter-recovered-button',
+ },
+];
+
+export function AlertsStatusFilter({ status, onChange }: AlertStatusFilterProps) {
+ return (
+
+ );
+}
diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx
index 69a6672db6e98..4b64ae07ddf06 100644
--- a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx
@@ -13,8 +13,6 @@
import {
ALERT_DURATION,
ALERT_REASON,
- ALERT_RULE_CONSUMER,
- ALERT_RULE_PRODUCER,
ALERT_STATUS,
ALERT_WORKFLOW_STATUS,
TIMESTAMP,
@@ -34,11 +32,8 @@ import {
import styled from 'styled-components';
import React, { Suspense, useMemo, useState, useCallback, useEffect } from 'react';
import usePrevious from 'react-use/lib/usePrevious';
-import { get, pick } from 'lodash';
-import {
- getAlertsPermissions,
- useGetUserAlertsPermissions,
-} from '../../hooks/use_alert_permission';
+import { pick } from 'lodash';
+import { getAlertsPermissions } from '../../hooks/use_alert_permission';
import type {
TimelinesUIStart,
TGridType,
@@ -46,13 +41,14 @@ import type {
TGridModel,
SortDirection,
} from '../../../../timelines/public';
-import { useStatusBulkActionItems } from '../../../../timelines/public';
+
import type { TopAlert } from './';
import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
import type {
ActionProps,
AlertWorkflowStatus,
ColumnHeaderOptions,
+ ControlColumnProps,
RowRenderer,
} from '../../../../timelines/common';
@@ -60,7 +56,6 @@ import { getRenderCellValue } from './render_cell_value';
import { observabilityAppId, observabilityFeatureId } from '../../../common';
import { useGetUserCasesPermissions } from '../../hooks/use_get_user_cases_permissions';
import { usePluginContext } from '../../hooks/use_plugin_context';
-import { getDefaultCellActions } from './default_cell_actions';
import { LazyAlertsFlyout } from '../..';
import { parseAlert } from './parse_alert';
import { CoreStart } from '../../../../../../src/core/public';
@@ -75,7 +70,6 @@ interface AlertsTableTGridProps {
kuery: string;
workflowStatus: AlertWorkflowStatus;
setRefetch: (ref: () => void) => void;
- addToQuery: (value: string) => void;
}
interface ObservabilityActionsProps extends ActionProps {
@@ -154,21 +148,21 @@ function ObservabilityActions({
const [openActionsPopoverId, setActionsPopover] = useState(null);
const {
timelines,
- application: { capabilities },
+ application: {},
} = useKibana().services;
const parseObservabilityAlert = useMemo(
() => parseAlert(observabilityRuleTypeRegistry),
[observabilityRuleTypeRegistry]
);
- const alertDataConsumer = useMemo(
- () => get(dataFieldEs, ALERT_RULE_CONSUMER, [''])[0],
- [dataFieldEs]
- );
- const alertDataProducer = useMemo(
- () => get(dataFieldEs, ALERT_RULE_PRODUCER, [''])[0],
- [dataFieldEs]
- );
+ // const alertDataConsumer = useMemo(
+ // () => get(dataFieldEs, ALERT_RULE_CONSUMER, [''])[0],
+ // [dataFieldEs]
+ // );
+ // const alertDataProducer = useMemo(
+ // () => get(dataFieldEs, ALERT_RULE_PRODUCER, [''])[0],
+ // [dataFieldEs]
+ // );
const alert = parseObservabilityAlert(dataFieldEs);
const { prepend } = core.http.basePath;
@@ -194,27 +188,29 @@ function ObservabilityActions({
};
}, [data, eventId, ecsData]);
- const onAlertStatusUpdated = useCallback(() => {
- setActionsPopover(null);
- if (refetch) {
- refetch();
- }
- }, [setActionsPopover, refetch]);
-
- const alertPermissions = useGetUserAlertsPermissions(
- capabilities,
- alertDataConsumer === 'alerts' ? alertDataProducer : alertDataConsumer
- );
-
- const statusActionItems = useStatusBulkActionItems({
- eventIds: [eventId],
- currentStatus,
- indexName: ecsData._index ?? '',
- setEventsLoading,
- setEventsDeleted,
- onUpdateSuccess: onAlertStatusUpdated,
- onUpdateFailure: onAlertStatusUpdated,
- });
+ // Hide the WorkFlow filter, but keep its code as required in https://github.com/elastic/kibana/issues/117686
+
+ // const onAlertStatusUpdated = useCallback(() => {
+ // setActionsPopover(null);
+ // if (refetch) {
+ // refetch();
+ // }
+ // }, [setActionsPopover, refetch]);
+
+ // const alertPermissions = useGetUserAlertsPermissions(
+ // capabilities,
+ // alertDataConsumer === 'alerts' ? alertDataProducer : alertDataConsumer
+ // );
+
+ // const statusActionItems = useStatusBulkActionItems({
+ // eventIds: [eventId],
+ // currentStatus,
+ // indexName: ecsData._index ?? '',
+ // setEventsLoading,
+ // setEventsDeleted,
+ // onUpdateSuccess: onAlertStatusUpdated,
+ // onUpdateFailure: onAlertStatusUpdated,
+ // });
const ruleId = alert.fields['kibana.alert.rule.uuid'] ?? null;
const linkToRule = ruleId ? prepend(paths.management.ruleDetails(ruleId)) : null;
@@ -239,7 +235,8 @@ function ObservabilityActions({
}),
]
: []),
- ...(alertPermissions.crud ? statusActionItems : []),
+ // Hide the WorkFlow filter, but keep its code as required in https://github.com/elastic/kibana/issues/117686
+ // ...(alertPermissions.crud ? statusActionItems : []),
...(!!linkToRule
? [
);
}
+// Hide the WorkFlow filter, but keep its code as required in https://github.com/elastic/kibana/issues/117686
const FIELDS_WITHOUT_CELL_ACTIONS = [
'@timestamp',
@@ -330,7 +320,7 @@ const FIELDS_WITHOUT_CELL_ACTIONS = [
];
export function AlertsTableTGrid(props: AlertsTableTGridProps) {
- const { indexNames, rangeFrom, rangeTo, kuery, workflowStatus, setRefetch, addToQuery } = props;
+ const { indexNames, rangeFrom, rangeTo, kuery, workflowStatus, setRefetch } = props;
const prevWorkflowStatus = usePrevious(workflowStatus);
const {
timelines,
@@ -382,7 +372,7 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) {
}
}, []);
- const leadingControlColumns = useMemo(() => {
+ const leadingControlColumns: ControlColumnProps[] = useMemo(() => {
return [
{
id: 'expand',
@@ -428,7 +418,8 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) {
type,
columns: tGridState?.columns ?? columns,
deletedEventIds,
- defaultCellActions: getDefaultCellActions({ addToQuery }),
+ // Hide the WorkFlow filter, but keep its code as required in https://github.com/elastic/kibana/issues/117686
+ // defaultCellActions: getDefaultCellActions({ addToQuery }),
disabledCellActions: FIELDS_WITHOUT_CELL_ACTIONS,
end: rangeTo,
filters: [],
@@ -462,7 +453,6 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) {
};
}, [
casePermissions,
- addToQuery,
rangeTo,
hasAlertsCrudPermissions,
indexNames,
diff --git a/x-pack/plugins/observability/public/pages/alerts/index.tsx b/x-pack/plugins/observability/public/pages/alerts/index.tsx
index a3c060f5dc5df..2636463bcfd7a 100644
--- a/x-pack/plugins/observability/public/pages/alerts/index.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/index.tsx
@@ -9,10 +9,13 @@ import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { IndexPatternBase } from '@kbn/es-query';
import { i18n } from '@kbn/i18n';
-import React, { useCallback, useRef } from 'react';
+import React, { useCallback, useRef, useState, useEffect } from 'react';
import useAsync from 'react-use/lib/useAsync';
+import { AlertStatus } from '@kbn/rule-data-utils/alerts_as_data_status';
+import { ALERT_STATUS } from '@kbn/rule-data-utils/technical_field_names';
+
+import { AlertStatusFilterButton } from '../../../common/typings';
import { ParsedTechnicalFields } from '../../../../rule_registry/common/parse_technical_fields';
-import type { AlertWorkflowStatus } from '../../../common/typings';
import { ExperimentalBadge } from '../../components/shared/experimental_badge';
import { useBreadcrumbs } from '../../hooks/use_breadcrumbs';
import { useFetcher } from '../../hooks/use_fetcher';
@@ -26,7 +29,7 @@ import { AlertsSearchBar } from './alerts_search_bar';
import { AlertsTableTGrid } from './alerts_table_t_grid';
import { Provider, alertsPageStateContainer, useAlertsPageStateContainer } from './state_container';
import './styles.scss';
-import { WorkflowStatusFilter } from './workflow_status_filter';
+import { AlertsStatusFilter } from './alerts_status_filter';
import { AlertsDisclaimer } from './alerts_disclaimer';
export interface TopAlert {
@@ -36,25 +39,29 @@ export interface TopAlert {
link?: string;
active: boolean;
}
-
+const regExpEscape = (str: string) => str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
const NO_INDEX_NAMES: string[] = [];
const NO_INDEX_PATTERNS: IndexPatternBase[] = [];
+const BASE_ALERT_REGEX = new RegExp(`\\s*${regExpEscape(ALERT_STATUS)}\\s*:\\s*"(.*?|\\*?)"`);
+const ALERT_STATUS_REGEX = new RegExp(
+ `\\s*and\\s*${regExpEscape(ALERT_STATUS)}\\s*:\\s*(".+?"|\\*?)|${regExpEscape(
+ ALERT_STATUS
+ )}\\s*:\\s*(".+?"|\\*?)`,
+ 'gm'
+);
function AlertsPage() {
const { core, plugins, ObservabilityPageTemplate } = usePluginContext();
+ const [alertFilterStatus, setAlertFilterStatus] = useState('' as AlertStatusFilterButton);
const { prepend } = core.http.basePath;
const refetch = useRef<() => void>();
const timefilterService = useTimefilterService();
- const {
- rangeFrom,
- setRangeFrom,
- rangeTo,
- setRangeTo,
- kuery,
- setKuery,
- workflowStatus,
- setWorkflowStatus,
- } = useAlertsPageStateContainer();
+ const { rangeFrom, setRangeFrom, rangeTo, setRangeTo, kuery, setKuery, workflowStatus } =
+ useAlertsPageStateContainer();
+
+ useEffect(() => {
+ syncAlertStatusFilterStatus(kuery as string);
+ }, [kuery]);
useBreadcrumbs([
{
@@ -103,36 +110,56 @@ function AlertsPage() {
];
}, [indexNames]);
- const setWorkflowStatusFilter = useCallback(
- (value: AlertWorkflowStatus) => {
- setWorkflowStatus(value);
- },
- [setWorkflowStatus]
- );
+ // Keep the Workflow status code commented (no delete) as requested: https://github.com/elastic/kibana/issues/117686
+
+ // const setWorkflowStatusFilter = useCallback(
+ // (value: AlertWorkflowStatus) => {
+ // setWorkflowStatus(value);
+ // },
+ // [setWorkflowStatus]
+ // );
const onQueryChange = useCallback(
({ dateRange, query }) => {
if (rangeFrom === dateRange.from && rangeTo === dateRange.to && kuery === (query ?? '')) {
return refetch.current && refetch.current();
}
-
timefilterService.setTime(dateRange);
setRangeFrom(dateRange.from);
setRangeTo(dateRange.to);
setKuery(query);
+ syncAlertStatusFilterStatus(query as string);
},
[rangeFrom, setRangeFrom, rangeTo, setRangeTo, kuery, setKuery, timefilterService]
);
- const addToQuery = useCallback(
- (value: string) => {
- let output = value;
- if (kuery !== '') {
- output = `${kuery} and ${value}`;
+ const syncAlertStatusFilterStatus = (query: string) => {
+ const [, alertStatus] = BASE_ALERT_REGEX.exec(query) || [];
+ if (!alertStatus) {
+ setAlertFilterStatus('');
+ return;
+ }
+ setAlertFilterStatus(alertStatus.toLowerCase() as AlertStatus);
+ };
+ const setAlertStatusFilter = useCallback(
+ (id: string, query: string) => {
+ setAlertFilterStatus(id as AlertStatusFilterButton);
+ // Updating the KQL query bar alongside with user inputs is tricky.
+ // To avoid issue, this function always remove the AlertFilter and add it
+ // at the end of the query, each time the filter is added/updated/removed (Show All)
+ // NOTE: This (query appending) will be changed entirely: https://github.com/elastic/kibana/issues/116135
+ let output = kuery;
+ if (kuery === '') {
+ output = query;
+ } else {
+ // console.log(ALERT_STATUS_REGEX);
+ const queryWithoutAlertFilter = kuery.replace(ALERT_STATUS_REGEX, '');
+ output = `${queryWithoutAlertFilter} and ${query}`;
}
onQueryChange({
dateRange: { from: rangeFrom, to: rangeTo },
- query: output,
+ // Clean up the kuery from unwanted trailing/ahead ANDs after appending and removing filters.
+ query: output.replace(/^\s*and\s*|\s*and\s*$/gm, ''),
});
},
[kuery, onQueryChange, rangeFrom, rangeTo]
@@ -194,7 +221,9 @@ function AlertsPage() {
-
+ {/* Keep the Workflow status code commented (no delete) as requested: https://github.com/elastic/kibana/issues/117686*/}
+ {/* */}
+
@@ -207,7 +236,6 @@ function AlertsPage() {
kuery={kuery}
workflowStatus={workflowStatus}
setRefetch={setRefetch}
- addToQuery={addToQuery}
/>
diff --git a/x-pack/test/observability_functional/apps/observability/alerts/index.ts b/x-pack/test/observability_functional/apps/observability/alerts/index.ts
index bd5f2ada4990d..4d2f4b971f080 100644
--- a/x-pack/test/observability_functional/apps/observability/alerts/index.ts
+++ b/x-pack/test/observability_functional/apps/observability/alerts/index.ts
@@ -186,7 +186,7 @@ export default ({ getService }: FtrProviderContext) => {
});
});
- describe('Cell actions', () => {
+ describe.skip('Cell actions', () => {
beforeEach(async () => {
await retry.try(async () => {
const cells = await observability.alerts.common.getTableCells();
diff --git a/x-pack/test/observability_functional/apps/observability/alerts/state_synchronization.ts b/x-pack/test/observability_functional/apps/observability/alerts/state_synchronization.ts
index 5a03f72e540b3..c351b45b2ea93 100644
--- a/x-pack/test/observability_functional/apps/observability/alerts/state_synchronization.ts
+++ b/x-pack/test/observability_functional/apps/observability/alerts/state_synchronization.ts
@@ -39,7 +39,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
await assertAlertsPageState({
kuery: 'kibana.alert.evaluation.threshold > 75',
- workflowStatus: 'Closed',
+ // workflowStatus: 'Closed',
timeRange: '~ a month ago - ~ 10 days ago',
});
});
@@ -55,7 +55,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
await assertAlertsPageState({
kuery: '',
- workflowStatus: 'Open',
+ // workflowStatus: 'Open',
timeRange: 'Last 15 minutes',
});
});
@@ -77,15 +77,15 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
async function assertAlertsPageState(expected: {
kuery: string;
- workflowStatus: string;
+ // workflowStatus: string;
timeRange: string;
}) {
expect(await (await observability.alerts.common.getQueryBar()).getVisibleText()).to.be(
expected.kuery
);
- expect(await observability.alerts.common.getWorkflowStatusFilterValue()).to.be(
- expected.workflowStatus
- );
+ // expect(await observability.alerts.common.getWorkflowStatusFilterValue()).to.be(
+ // expected.workflowStatus
+ // );
const timeRange = await observability.alerts.common.getTimeRange();
expect(timeRange).to.be(expected.timeRange);
}
diff --git a/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts b/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts
index 4976c1c225aba..9f6c781306749 100644
--- a/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts
+++ b/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts
@@ -13,7 +13,8 @@ const OPEN_ALERTS_ROWS_COUNT = 33;
export default ({ getService }: FtrProviderContext) => {
const esArchiver = getService('esArchiver');
- describe('alert workflow status', function () {
+ // Keep the Workflow status code commented (no delete) as requested: https://github.com/elastic/kibana/issues/117686
+ describe.skip('alert workflow status', function () {
this.tags('includeFirefox');
const observability = getService('observability');
From d2410a9852d99bced0a871e10170b10ee5e64863 Mon Sep 17 00:00:00 2001
From: Dzmitry Lemechko
Date: Mon, 29 Nov 2021 13:17:46 +0100
Subject: [PATCH 04/47] [load testing] run pupeteeer scenario based on
simulation class (#119778)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
x-pack/test/load/runner.ts | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/x-pack/test/load/runner.ts b/x-pack/test/load/runner.ts
index e9750bd19881a..ba40bcf294e57 100644
--- a/x-pack/test/load/runner.ts
+++ b/x-pack/test/load/runner.ts
@@ -57,16 +57,20 @@ export async function GatlingTestRunner({ getService }: FtrProviderContext) {
const log = getService('log');
await withProcRunner(log, async (procs) => {
- await procs.run('node build/index.js', {
- cmd: 'node',
- args: ['build/index.js'],
- cwd: puppeteerProjectRootPath,
- env: {
- ...process.env,
- },
- wait: true,
- });
for (let i = 0; i < simulationClasses.length; i++) {
+ await procs.run('node build/index.js', {
+ cmd: 'node',
+ args: [
+ 'build/index.js',
+ `--simulation='${simulationClasses[i]}'`,
+ `--config='./config.json'`,
+ ],
+ cwd: puppeteerProjectRootPath,
+ env: {
+ ...process.env,
+ },
+ wait: true,
+ });
await procs.run('gatling: test', {
cmd: 'mvn',
args: [
From 1c1d607fc2212805629478fab5e6763742069e64 Mon Sep 17 00:00:00 2001
From: "Lucas F. da Costa"
Date: Mon, 29 Nov 2021 13:29:22 +0000
Subject: [PATCH 05/47] [Uptime] Inform users when they can't create ML jobs
(closes #107994) (#117684)
Previously, if users weren't able to create an ML job, they would simply
be shown a grayed-out button.
Showing this disabled button without explaining _why_ they cannot create
ML jobs could be confusing. Therefore, this commit adds a proper callout
explaining which roles and privileges are necessary.
---
.../components/monitor/ml/ml_flyout.test.tsx | 74 +++++++++++++------
.../components/monitor/ml/ml_flyout.tsx | 15 ++++
.../components/monitor/ml/translations.tsx | 7 ++
.../uptime/public/lib/helper/rtl_helpers.tsx | 22 +++++-
4 files changed, 96 insertions(+), 22 deletions(-)
diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.test.tsx
index c2c4baf0751c4..8669bc180f42f 100644
--- a/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.test.tsx
+++ b/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.test.tsx
@@ -10,13 +10,23 @@ import { MLFlyoutView } from './ml_flyout';
import { UptimeSettingsContext } from '../../../contexts';
import { CLIENT_DEFAULTS } from '../../../../common/constants';
import * as redux from 'react-redux';
-import { render } from '../../../lib/helper/rtl_helpers';
+import { render, forNearestButton } from '../../../lib/helper/rtl_helpers';
import * as labels from './translations';
describe('ML Flyout component', () => {
const createJob = () => {};
const onClose = () => {};
const { DATE_RANGE_START, DATE_RANGE_END } = CLIENT_DEFAULTS;
+ const defaultContextValue = {
+ isDevMode: true,
+ basePath: '',
+ dateRangeStart: DATE_RANGE_START,
+ dateRangeEnd: DATE_RANGE_END,
+ isApmAvailable: true,
+ isInfraAvailable: true,
+ isLogsAvailable: true,
+ config: {},
+ };
beforeEach(() => {
const spy = jest.spyOn(redux, 'useDispatch');
@@ -32,16 +42,8 @@ describe('ML Flyout component', () => {
// return false value for no license
spy1.mockReturnValue(false);
- const value = {
- isDevMode: true,
- basePath: '',
- dateRangeStart: DATE_RANGE_START,
- dateRangeEnd: DATE_RANGE_END,
- isApmAvailable: true,
- isInfraAvailable: true,
- isLogsAvailable: true,
- config: {},
- };
+ const value = { ...defaultContextValue };
+
const { findByText, findAllByText } = render(
{
});
it('able to create job if valid license is available', async () => {
- const value = {
- isDevMode: true,
- basePath: '',
- dateRangeStart: DATE_RANGE_START,
- dateRangeEnd: DATE_RANGE_END,
- isApmAvailable: true,
- isInfraAvailable: true,
- isLogsAvailable: true,
- config: {},
- };
+ const value = { ...defaultContextValue };
+
const { queryByText } = render(
{
expect(queryByText(labels.START_TRAIL)).not.toBeInTheDocument();
});
+
+ describe("when users don't have Machine Learning privileges", () => {
+ it('shows an informative callout about the need for ML privileges', async () => {
+ const value = { ...defaultContextValue };
+
+ const { queryByText } = render(
+
+
+
+ );
+
+ expect(
+ queryByText('You must have the Kibana privileges for Machine Learning to use this feature.')
+ ).toBeInTheDocument();
+ });
+
+ it('disables the job creation button', async () => {
+ const value = { ...defaultContextValue };
+
+ const { queryByText } = render(
+
+
+
+ );
+
+ expect(forNearestButton(queryByText)(labels.CREATE_NEW_JOB)).toBeDisabled();
+ });
+ });
});
diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.tsx b/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.tsx
index 5500324e4bdd8..c367b60a65016 100644
--- a/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.tsx
+++ b/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.tsx
@@ -19,6 +19,7 @@ import {
EuiSpacer,
EuiText,
EuiTitle,
+ EuiCallOut,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { useSelector } from 'react-redux';
@@ -69,6 +70,20 @@ export function MLFlyoutView({ isCreatingJob, onClickCreate, onClose, canCreateM
+ {!canCreateMLJob && (
+
+
+
+
+
+ )}
diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/translations.tsx b/x-pack/plugins/uptime/public/components/monitor/ml/translations.tsx
index 1fc4093a67d83..86ca94d5b6499 100644
--- a/x-pack/plugins/uptime/public/components/monitor/ml/translations.tsx
+++ b/x-pack/plugins/uptime/public/components/monitor/ml/translations.tsx
@@ -179,3 +179,10 @@ export const ENABLE_MANAGE_JOB = i18n.translate(
'You can enable anomaly detection job or if job is already there you can manage the job or alert.',
}
);
+
+export const ADD_JOB_PERMISSIONS_NEEDED = i18n.translate(
+ 'xpack.uptime.ml.enableAnomalyDetectionPanel.add_job_permissions_needed',
+ {
+ defaultMessage: 'Permissions needed',
+ }
+);
diff --git a/x-pack/plugins/uptime/public/lib/helper/rtl_helpers.tsx b/x-pack/plugins/uptime/public/lib/helper/rtl_helpers.tsx
index fe7fd0918450b..84d2566304336 100644
--- a/x-pack/plugins/uptime/public/lib/helper/rtl_helpers.tsx
+++ b/x-pack/plugins/uptime/public/lib/helper/rtl_helpers.tsx
@@ -8,7 +8,12 @@
import React, { ReactElement } from 'react';
import { of } from 'rxjs';
// eslint-disable-next-line import/no-extraneous-dependencies
-import { render as reactTestLibRender, RenderOptions } from '@testing-library/react';
+import {
+ render as reactTestLibRender,
+ MatcherFunction,
+ RenderOptions,
+ Nullish,
+} from '@testing-library/react';
import { Router } from 'react-router-dom';
import { createMemoryHistory, History } from 'history';
import { CoreStart } from 'kibana/public';
@@ -209,3 +214,18 @@ const getHistoryFromUrl = (url: Url) => {
initialEntries: [url.path + stringifyUrlParams(url.queryParams)],
});
};
+
+// This function allows us to query for the nearest button with test
+// no matter whether it has nested tags or not (as EuiButton elements do).
+export const forNearestButton =
+ (getByText: (f: MatcherFunction) => HTMLElement | null) =>
+ (text: string): HTMLElement | null =>
+ getByText((_content: string, node: Nullish) => {
+ if (!node) return false;
+ const noOtherButtonHasText = Array.from(node.children).every(
+ (child) => child && (child.textContent !== text || child.tagName.toLowerCase() !== 'button')
+ );
+ return (
+ noOtherButtonHasText && node.textContent === text && node.tagName.toLowerCase() === 'button'
+ );
+ });
From 1b3112ee96aa9e4337d7a7c2eef985602755802c Mon Sep 17 00:00:00 2001
From: Tiago Costa
Date: Mon, 29 Nov 2021 13:33:09 +0000
Subject: [PATCH 06/47] skip flaky suite (#88177)
---
x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts
index d657db443e4ec..bb89fa8f683fa 100644
--- a/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts
+++ b/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts
@@ -16,7 +16,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const retry = getService('retry');
- describe('overview page alert flyout controls', function () {
+ // FLAKY: https://github.com/elastic/kibana/issues/88177
+ describe.skip('overview page alert flyout controls', function () {
const DEFAULT_DATE_START = 'Sep 10, 2019 @ 12:40:08.078';
const DEFAULT_DATE_END = 'Sep 11, 2019 @ 19:40:08.078';
let alerts: any;
From 776e091865340441798b8b918f8c442bdf16f14a Mon Sep 17 00:00:00 2001
From: Tiago Costa
Date: Mon, 29 Nov 2021 13:37:55 +0000
Subject: [PATCH 07/47] skip flaky suite (#92567)
---
.../security_solution_endpoint/apps/endpoint/policy_details.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts
index 61773aaf825fa..7562f69f673c9 100644
--- a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts
+++ b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts
@@ -337,7 +337,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
});
});
- describe('and the save button is clicked', () => {
+ // FLAKY: https://github.com/elastic/kibana/issues/92567
+ describe.skip('and the save button is clicked', () => {
let policyInfo: PolicyTestResourceInfo;
beforeEach(async () => {
From 43253ecafa1365eae45d31dd284d0a0bf273bc4d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?=
Date: Mon, 29 Nov 2021 14:40:01 +0100
Subject: [PATCH 08/47] [APM] Fix bug in documentation on `span.destination`
metrics (#119789)
---
x-pack/plugins/apm/dev_docs/apm_queries.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/x-pack/plugins/apm/dev_docs/apm_queries.md b/x-pack/plugins/apm/dev_docs/apm_queries.md
index e6021fa31b9f7..4dd9a807eb249 100644
--- a/x-pack/plugins/apm/dev_docs/apm_queries.md
+++ b/x-pack/plugins/apm/dev_docs/apm_queries.md
@@ -461,6 +461,7 @@ GET apm-*-metric-*,metrics-apm*/_search?terminate_after=1000
"aggs": {
"throughput": {
"rate": {
+ "field": "span.destination.service.response_time.count",
"unit": "minute"
}
}
From c394b5744bd075863e5169f4d1f2d5cbc4ddc5eb Mon Sep 17 00:00:00 2001
From: Tiago Costa
Date: Mon, 29 Nov 2021 13:46:09 +0000
Subject: [PATCH 09/47] skip flaky suite (#119660)
---
x-pack/test/api_integration/apis/search/session.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/x-pack/test/api_integration/apis/search/session.ts b/x-pack/test/api_integration/apis/search/session.ts
index 1fa65172cdee3..868c91cd9ed12 100644
--- a/x-pack/test/api_integration/apis/search/session.ts
+++ b/x-pack/test/api_integration/apis/search/session.ts
@@ -16,7 +16,8 @@ export default function ({ getService }: FtrProviderContext) {
const retry = getService('retry');
const spacesService = getService('spaces');
- describe('search session', () => {
+ // FLAKY: https://github.com/elastic/kibana/issues/119660
+ describe.skip('search session', () => {
describe('session management', () => {
it('should fail to create a session with no name', async () => {
const sessionId = `my-session-${Math.random()}`;
From 1915a8ddfce1840e67c079ef63133172d6550e30 Mon Sep 17 00:00:00 2001
From: Joe Reuter
Date: Mon, 29 Nov 2021 14:56:37 +0100
Subject: [PATCH 10/47] fix existing fields query (#119508)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
x-pack/plugins/lens/server/routes/existing_fields.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/x-pack/plugins/lens/server/routes/existing_fields.ts b/x-pack/plugins/lens/server/routes/existing_fields.ts
index d3a79dc7d8bfc..3a57a77a97726 100644
--- a/x-pack/plugins/lens/server/routes/existing_fields.ts
+++ b/x-pack/plugins/lens/server/routes/existing_fields.ts
@@ -183,6 +183,7 @@ async function fetchIndexPatternStats({
{
range: {
[timeFieldName]: {
+ format: 'strict_date_optional_time',
gte: fromDate,
lte: toDate,
},
From c6d41d07d727c1257f482880f22564bae30449fb Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Mon, 29 Nov 2021 15:36:52 +0100
Subject: [PATCH 11/47] [Dashboard/Reporting] Removal of Reporting injected CSS
and JS (#111958)
* checkpoint 1: dashboard reading screenshot mode values is screenshot mode and screenshot layout
* checkpoint 2: dashboard handling preserve layout
* temp setting up print viewport
* slight clean up, detect a new view mode "print"
* fix types
* adde todo comment
* added "print" route to dashboard that does not rely on screenshotMode service
* updated jest tests and added screenshot mode public mock
* try to respect embed settings
* fix lint
* remove print mode from share data
* re-add ViewMode.VIEW to share data
* updated TODO comment
* remove injected print css
* remove double declaration of ScreenshotModePluginStart
* re-add missing import :facepalm:
* fix types issues
* changed css injection removal to use only viewMode.PRINT rather than a new route
* turn off defer below fold when in print mode
* elastic@ email address
* address some CI checks that were failing
* use .includes instead of || to check view mode
Co-authored-by: Michael Dokolin
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Devon A Thomson
Co-authored-by: Michael Dokolin
---
src/plugins/dashboard/kibana.json | 1 +
.../actions/add_to_library_action.test.tsx | 2 +
.../actions/clone_panel_action.test.tsx | 2 +
.../actions/expand_panel_action.test.tsx | 2 +
.../actions/export_csv_action.test.tsx | 2 +
.../library_notification_action.test.tsx | 2 +
.../library_notification_popover.test.tsx | 2 +
.../actions/replace_panel_action.test.tsx | 2 +
.../unlink_from_library_action.test.tsx | 2 +
.../public/application/dashboard_app.tsx | 26 ++--
.../public/application/dashboard_router.tsx | 2 +-
.../embeddable/dashboard_container.test.tsx | 2 +
.../embeddable/dashboard_container.tsx | 2 +
.../embeddable/grid/dashboard_grid.test.tsx | 2 +
.../embeddable/grid/dashboard_grid.tsx | 7 +-
.../embeddable/grid/dashboard_grid_item.tsx | 9 +-
.../embeddable/viewport/_index.scss | 1 +
.../embeddable/viewport/_print_viewport.scss | 9 ++
.../viewport/dashboard_viewport.test.tsx | 2 +
.../hooks/use_dashboard_app_state.test.tsx | 1 -
.../hooks/use_dashboard_app_state.ts | 11 +-
.../test_helpers/make_default_services.ts | 2 +
.../dashboard/public/dashboard_constants.ts | 1 +
src/plugins/dashboard/public/locator.ts | 1 +
src/plugins/dashboard/public/plugin.tsx | 19 ++-
.../public/services/screenshot_mode.ts | 14 ++
src/plugins/dashboard/public/types.ts | 4 +-
src/plugins/embeddable/common/types.ts | 1 +
.../public/lib/panel/embeddable_panel.tsx | 2 +-
src/plugins/newsfeed/public/plugin.test.ts | 7 +-
.../common/get_set_browser_screenshot_mode.ts | 30 ++++-
src/plugins/screenshot_mode/common/index.ts | 5 +
src/plugins/screenshot_mode/public/mocks.ts | 2 +
src/plugins/screenshot_mode/public/plugin.ts | 3 +-
src/plugins/screenshot_mode/public/types.ts | 5 +
src/plugins/screenshot_mode/server/plugin.ts | 3 +-
src/plugins/screenshot_mode/server/types.ts | 6 +-
.../chromium/driver/chromium_driver.ts | 8 +-
x-pack/plugins/reporting/server/core.ts | 11 +-
.../server/lib/layouts/preserve_layout.css | 7 +-
.../server/lib/layouts/preserve_layout.ts | 2 +-
.../reporting/server/lib/layouts/print.css | 122 ------------------
.../server/lib/layouts/print_layout.ts | 41 +-----
.../lib/screenshots/observable_handler.ts | 1 +
.../server/lib/screenshots/open_url.ts | 8 +-
45 files changed, 197 insertions(+), 199 deletions(-)
create mode 100644 src/plugins/dashboard/public/application/embeddable/viewport/_print_viewport.scss
create mode 100644 src/plugins/dashboard/public/services/screenshot_mode.ts
delete mode 100644 x-pack/plugins/reporting/server/lib/layouts/print.css
diff --git a/src/plugins/dashboard/kibana.json b/src/plugins/dashboard/kibana.json
index cb6a5383688dc..2be6e9b269e71 100644
--- a/src/plugins/dashboard/kibana.json
+++ b/src/plugins/dashboard/kibana.json
@@ -13,6 +13,7 @@
"navigation",
"savedObjects",
"share",
+ "screenshotMode",
"uiActions",
"urlForwarding",
"presentationUtil",
diff --git a/src/plugins/dashboard/public/application/actions/add_to_library_action.test.tsx b/src/plugins/dashboard/public/application/actions/add_to_library_action.test.tsx
index fa484de2180b4..40f6f872535f9 100644
--- a/src/plugins/dashboard/public/application/actions/add_to_library_action.test.tsx
+++ b/src/plugins/dashboard/public/application/actions/add_to_library_action.test.tsx
@@ -15,6 +15,7 @@ import { CoreStart } from 'kibana/public';
import { coreMock, uiSettingsServiceMock } from '../../../../../core/public/mocks';
import { embeddablePluginMock } from 'src/plugins/embeddable/public/mocks';
import { getStubPluginServices } from '../../../../presentation_util/public';
+import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
import {
EmbeddableInput,
@@ -65,6 +66,7 @@ beforeEach(async () => {
uiSettings: uiSettingsServiceMock.createStartContract(),
http: coreStart.http,
presentationUtil: getStubPluginServices(),
+ screenshotMode: screenshotModePluginMock.createSetupContract(),
};
container = new DashboardContainer(getSampleDashboardInput(), containerOptions);
diff --git a/src/plugins/dashboard/public/application/actions/clone_panel_action.test.tsx b/src/plugins/dashboard/public/application/actions/clone_panel_action.test.tsx
index 99665d312d32e..fc4c6b299284b 100644
--- a/src/plugins/dashboard/public/application/actions/clone_panel_action.test.tsx
+++ b/src/plugins/dashboard/public/application/actions/clone_panel_action.test.tsx
@@ -23,6 +23,7 @@ import {
} from '../../services/embeddable_test_samples';
import { ErrorEmbeddable, IContainer, isErrorEmbeddable } from '../../services/embeddable';
import { getStubPluginServices } from '../../../../presentation_util/public';
+import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
const { setup, doStart } = embeddablePluginMock.createInstance();
setup.registerEmbeddableFactory(
@@ -56,6 +57,7 @@ beforeEach(async () => {
uiSettings: uiSettingsServiceMock.createStartContract(),
http: coreStart.http,
presentationUtil: getStubPluginServices(),
+ screenshotMode: screenshotModePluginMock.createSetupContract(),
};
const input = getSampleDashboardInput({
panels: {
diff --git a/src/plugins/dashboard/public/application/actions/expand_panel_action.test.tsx b/src/plugins/dashboard/public/application/actions/expand_panel_action.test.tsx
index 0635152332993..b20a96c79aed6 100644
--- a/src/plugins/dashboard/public/application/actions/expand_panel_action.test.tsx
+++ b/src/plugins/dashboard/public/application/actions/expand_panel_action.test.tsx
@@ -13,6 +13,7 @@ import { getSampleDashboardInput, getSampleDashboardPanel } from '../test_helper
import { embeddablePluginMock } from 'src/plugins/embeddable/public/mocks';
import { isErrorEmbeddable } from '../../services/embeddable';
import { getStubPluginServices } from '../../../../presentation_util/public';
+import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
import {
CONTACT_CARD_EMBEDDABLE,
@@ -48,6 +49,7 @@ beforeEach(async () => {
uiSettings: uiSettingsServiceMock.createStartContract(),
http: coreMock.createStart().http,
presentationUtil: getStubPluginServices(),
+ screenshotMode: screenshotModePluginMock.createSetupContract(),
};
const input = getSampleDashboardInput({
panels: {
diff --git a/src/plugins/dashboard/public/application/actions/export_csv_action.test.tsx b/src/plugins/dashboard/public/application/actions/export_csv_action.test.tsx
index 51c64f1875376..797765eda232d 100644
--- a/src/plugins/dashboard/public/application/actions/export_csv_action.test.tsx
+++ b/src/plugins/dashboard/public/application/actions/export_csv_action.test.tsx
@@ -25,6 +25,7 @@ import { DataPublicPluginStart } from '../../../../data/public/types';
import { dataPluginMock } from '../../../../data/public/mocks';
import { LINE_FEED_CHARACTER } from 'src/plugins/data/common/exports/export_csv';
import { getStubPluginServices } from '../../../../presentation_util/public';
+import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
describe('Export CSV action', () => {
const { setup, doStart } = embeddablePluginMock.createInstance();
@@ -61,6 +62,7 @@ describe('Export CSV action', () => {
uiSettings: uiSettingsServiceMock.createStartContract(),
http: coreStart.http,
presentationUtil: getStubPluginServices(),
+ screenshotMode: screenshotModePluginMock.createSetupContract(),
};
const input = getSampleDashboardInput({
panels: {
diff --git a/src/plugins/dashboard/public/application/actions/library_notification_action.test.tsx b/src/plugins/dashboard/public/application/actions/library_notification_action.test.tsx
index 587f741461bb4..ab442bf839e37 100644
--- a/src/plugins/dashboard/public/application/actions/library_notification_action.test.tsx
+++ b/src/plugins/dashboard/public/application/actions/library_notification_action.test.tsx
@@ -28,6 +28,7 @@ import {
CONTACT_CARD_EMBEDDABLE,
} from '../../services/embeddable_test_samples';
import { getStubPluginServices } from '../../../../presentation_util/public';
+import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
const { setup, doStart } = embeddablePluginMock.createInstance();
setup.registerEmbeddableFactory(
@@ -62,6 +63,7 @@ beforeEach(async () => {
uiSettings: uiSettingsServiceMock.createStartContract(),
http: coreStart.http,
presentationUtil: getStubPluginServices(),
+ screenshotMode: screenshotModePluginMock.createSetupContract(),
};
container = new DashboardContainer(getSampleDashboardInput(), containerOptions);
diff --git a/src/plugins/dashboard/public/application/actions/library_notification_popover.test.tsx b/src/plugins/dashboard/public/application/actions/library_notification_popover.test.tsx
index b5efa0447e651..de1a475fdbd18 100644
--- a/src/plugins/dashboard/public/application/actions/library_notification_popover.test.tsx
+++ b/src/plugins/dashboard/public/application/actions/library_notification_popover.test.tsx
@@ -29,6 +29,7 @@ import {
ContactCardEmbeddable,
} from '../../services/embeddable_test_samples';
import { getStubPluginServices } from '../../../../presentation_util/public';
+import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
describe('LibraryNotificationPopover', () => {
const { setup, doStart } = embeddablePluginMock.createInstance();
@@ -58,6 +59,7 @@ describe('LibraryNotificationPopover', () => {
uiSettings: uiSettingsServiceMock.createStartContract(),
http: coreStart.http,
presentationUtil: getStubPluginServices(),
+ screenshotMode: screenshotModePluginMock.createSetupContract(),
};
container = new DashboardContainer(getSampleDashboardInput(), containerOptions);
diff --git a/src/plugins/dashboard/public/application/actions/replace_panel_action.test.tsx b/src/plugins/dashboard/public/application/actions/replace_panel_action.test.tsx
index f8880ac5618fc..fe39f6112a7f3 100644
--- a/src/plugins/dashboard/public/application/actions/replace_panel_action.test.tsx
+++ b/src/plugins/dashboard/public/application/actions/replace_panel_action.test.tsx
@@ -22,6 +22,7 @@ import {
ContactCardEmbeddableOutput,
} from '../../services/embeddable_test_samples';
import { getStubPluginServices } from '../../../../presentation_util/public';
+import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
const { setup, doStart } = embeddablePluginMock.createInstance();
setup.registerEmbeddableFactory(
@@ -48,6 +49,7 @@ beforeEach(async () => {
uiSettings: uiSettingsServiceMock.createStartContract(),
http: coreStart.http,
presentationUtil: getStubPluginServices(),
+ screenshotMode: screenshotModePluginMock.createSetupContract(),
};
const input = getSampleDashboardInput({
panels: {
diff --git a/src/plugins/dashboard/public/application/actions/unlink_from_library_action.test.tsx b/src/plugins/dashboard/public/application/actions/unlink_from_library_action.test.tsx
index 7d87c49bda649..4f10f833f643c 100644
--- a/src/plugins/dashboard/public/application/actions/unlink_from_library_action.test.tsx
+++ b/src/plugins/dashboard/public/application/actions/unlink_from_library_action.test.tsx
@@ -30,6 +30,7 @@ import {
CONTACT_CARD_EMBEDDABLE,
} from '../../services/embeddable_test_samples';
import { getStubPluginServices } from '../../../../presentation_util/public';
+import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
const { setup, doStart } = embeddablePluginMock.createInstance();
setup.registerEmbeddableFactory(
@@ -57,6 +58,7 @@ beforeEach(async () => {
uiSettings: uiSettingsServiceMock.createStartContract(),
http: coreStart.http,
presentationUtil: getStubPluginServices(),
+ screenshotMode: screenshotModePluginMock.createSetupContract(),
};
container = new DashboardContainer(getSampleDashboardInput(), containerOptions);
diff --git a/src/plugins/dashboard/public/application/dashboard_app.tsx b/src/plugins/dashboard/public/application/dashboard_app.tsx
index 3e6566f0da0a4..7aedbe9e11001 100644
--- a/src/plugins/dashboard/public/application/dashboard_app.tsx
+++ b/src/plugins/dashboard/public/application/dashboard_app.tsx
@@ -17,11 +17,11 @@ import {
getDashboardTitle,
leaveConfirmStrings,
} from '../dashboard_strings';
-import { EmbeddableRenderer } from '../services/embeddable';
+import { createDashboardEditUrl } from '../dashboard_constants';
+import { EmbeddableRenderer, ViewMode } from '../services/embeddable';
import { DashboardTopNav, isCompleteDashboardAppState } from './top_nav/dashboard_top_nav';
import { DashboardAppServices, DashboardEmbedSettings, DashboardRedirect } from '../types';
import { createKbnUrlStateStorage, withNotifyOnErrors } from '../services/kibana_utils';
-import { createDashboardEditUrl } from '../dashboard_constants';
export interface DashboardAppProps {
history: History;
savedDashboardId?: string;
@@ -51,7 +51,6 @@ export function DashboardApp({
const dashboardState = useDashboardSelector((state) => state.dashboardStateReducer);
const dashboardAppState = useDashboardAppState({
history,
- redirectTo,
savedDashboardId,
kbnUrlStateStorage,
isEmbeddedExternally: Boolean(embedSettings),
@@ -101,15 +100,26 @@ export function DashboardApp({
};
}, [data.search.session]);
+ const printMode = useMemo(
+ () => dashboardAppState.getLatestDashboardState?.().viewMode === ViewMode.PRINT,
+ [dashboardAppState]
+ );
+
+ useEffect(() => {
+ if (!embedSettings) chrome.setIsVisible(!printMode);
+ }, [chrome, printMode, embedSettings]);
+
return (
<>
{isCompleteDashboardAppState(dashboardAppState) && (
<>
-
+ {!printMode && (
+
+ )}
{dashboardAppState.savedDashboard.outcome === 'conflict' &&
dashboardAppState.savedDashboard.id &&
diff --git a/src/plugins/dashboard/public/application/dashboard_router.tsx b/src/plugins/dashboard/public/application/dashboard_router.tsx
index 4a22899c12e8a..c74ac506e4809 100644
--- a/src/plugins/dashboard/public/application/dashboard_router.tsx
+++ b/src/plugins/dashboard/public/application/dashboard_router.tsx
@@ -109,6 +109,7 @@ export async function mountApp({
embeddable: embeddableStart,
uiSettings: coreStart.uiSettings,
scopedHistory: () => scopedHistory,
+ screenshotModeService: screenshotMode,
indexPatterns: dataStart.indexPatterns,
savedQueryService: dataStart.query.savedQueries,
savedObjectsClient: coreStart.savedObjects.client,
@@ -131,7 +132,6 @@ export async function mountApp({
activeSpaceId || 'default'
),
spacesService: spacesApi,
- screenshotModeService: screenshotMode,
};
const getUrlStateStorage = (history: RouteComponentProps['history']) =>
diff --git a/src/plugins/dashboard/public/application/embeddable/dashboard_container.test.tsx b/src/plugins/dashboard/public/application/embeddable/dashboard_container.test.tsx
index 6cd102a4d4770..744d63c1ba04a 100644
--- a/src/plugins/dashboard/public/application/embeddable/dashboard_container.test.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/dashboard_container.test.tsx
@@ -43,11 +43,13 @@ import { getStubPluginServices } from '../../../../presentation_util/public';
const presentationUtil = getStubPluginServices();
const options: DashboardContainerServices = {
+ // TODO: clean up use of any
application: {} as any,
embeddable: {} as any,
notifications: {} as any,
overlays: {} as any,
inspector: {} as any,
+ screenshotMode: {} as any,
SavedObjectFinder: () => null,
ExitFullScreenButton: () => null,
uiActions: {} as any,
diff --git a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx
index 54fa1f05b9c0d..d7081bf020d85 100644
--- a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx
@@ -40,6 +40,7 @@ import {
import { PLACEHOLDER_EMBEDDABLE } from './placeholder';
import { DashboardAppCapabilities, DashboardContainerInput } from '../../types';
import { PresentationUtilPluginStart } from '../../services/presentation_util';
+import type { ScreenshotModePluginStart } from '../../services/screenshot_mode';
import { PanelPlacementMethod, IPanelPlacementArgs } from './panel/dashboard_panel_placement';
import {
combineDashboardFiltersWithControlGroupFilters,
@@ -55,6 +56,7 @@ export interface DashboardContainerServices {
application: CoreStart['application'];
inspector: InspectorStartContract;
overlays: CoreStart['overlays'];
+ screenshotMode: ScreenshotModePluginStart;
uiSettings: IUiSettingsClient;
embeddable: EmbeddableStart;
uiActions: UiActionsStart;
diff --git a/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.test.tsx b/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.test.tsx
index 52f04bcead665..7518a36433d35 100644
--- a/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.test.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.test.tsx
@@ -23,6 +23,7 @@ import {
} from '../../../services/embeddable_test_samples';
import { coreMock, uiSettingsServiceMock } from '../../../../../../core/public/mocks';
import { getStubPluginServices } from '../../../../../presentation_util/public';
+import { screenshotModePluginMock } from '../../../../../screenshot_mode/public/mocks';
let dashboardContainer: DashboardContainer | undefined;
const presentationUtil = getStubPluginServices();
@@ -71,6 +72,7 @@ function prepare(props?: Partial) {
uiSettings: uiSettingsServiceMock.createStartContract(),
http: coreMock.createStart().http,
presentationUtil,
+ screenshotMode: screenshotModePluginMock.createSetupContract(),
};
dashboardContainer = new DashboardContainer(initialInput, options);
const defaultTestProps: DashboardGridProps = {
diff --git a/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx b/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx
index 9d2afdba36dbc..09ac0c1dd94bb 100644
--- a/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx
@@ -154,7 +154,7 @@ class DashboardGridUi extends React.Component {
id: 'dashboard.dashboardGrid.toast.unableToLoadDashboardDangerMessage',
defaultMessage: 'Unable to load dashboard.',
}),
- body: error.message,
+ body: (error as { message: string }).message,
toastLifeTimeMs: 5000,
});
}
@@ -254,6 +254,11 @@ class DashboardGridUi extends React.Component {
/>
));
+ // in print mode, dashboard layout is not controlled by React Grid Layout
+ if (viewMode === ViewMode.PRINT) {
+ return <>{dashboardPanels}>;
+ }
+
return (
;
type DivProps = Pick, 'className' | 'style' | 'children'>;
@@ -20,6 +21,7 @@ type DivProps = Pick, 'className' | 'style'
interface Props extends PanelProps, DivProps {
id: DashboardPanelState['explicitInput']['id'];
type: DashboardPanelState['type'];
+ container: DashboardContainer;
focusedPanelId?: string;
expandedPanelId?: string;
key: string;
@@ -52,6 +54,8 @@ const Item = React.forwardRef(
'dshDashboardGrid__item--expanded': expandPanel,
// eslint-disable-next-line @typescript-eslint/naming-convention
'dshDashboardGrid__item--hidden': hidePanel,
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ printViewport__vis: container.getInput().viewMode === ViewMode.PRINT,
});
return (
@@ -116,7 +120,8 @@ export const ObservedItem: FC = (props: Props) => {
export const DashboardGridItem: FC = (props: Props) => {
const { isProjectEnabled } = useLabs();
- const isEnabled = isProjectEnabled('labs:dashboard:deferBelowFold');
+ const isPrintMode = props.container.getInput().viewMode === ViewMode.PRINT;
+ const isEnabled = !isPrintMode && isProjectEnabled('labs:dashboard:deferBelowFold');
return isEnabled ? : ;
};
diff --git a/src/plugins/dashboard/public/application/embeddable/viewport/_index.scss b/src/plugins/dashboard/public/application/embeddable/viewport/_index.scss
index 56483d9d10195..02411f5902b3b 100644
--- a/src/plugins/dashboard/public/application/embeddable/viewport/_index.scss
+++ b/src/plugins/dashboard/public/application/embeddable/viewport/_index.scss
@@ -1 +1,2 @@
@import './dashboard_viewport';
+@import './print_viewport';
diff --git a/src/plugins/dashboard/public/application/embeddable/viewport/_print_viewport.scss b/src/plugins/dashboard/public/application/embeddable/viewport/_print_viewport.scss
new file mode 100644
index 0000000000000..a451178cc46b0
--- /dev/null
+++ b/src/plugins/dashboard/public/application/embeddable/viewport/_print_viewport.scss
@@ -0,0 +1,9 @@
+.printViewport {
+ &__vis {
+ height: 600px; // These values might need to be passed in as dimensions for the report. I.e., print should use layout dimensions.
+ width: 975px;
+
+ // Some vertical space between vis, but center horizontally
+ margin: 10px auto;
+ }
+}
diff --git a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx
index 7c671ce7736d7..f0333cefd612f 100644
--- a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx
@@ -27,6 +27,7 @@ import {
CONTACT_CARD_EMBEDDABLE,
} from '../../../../../embeddable/public/lib/test_samples';
import { getStubPluginServices } from '../../../../../presentation_util/public';
+import { screenshotModePluginMock } from '../../../../../screenshot_mode/public/mocks';
let dashboardContainer: DashboardContainer | undefined;
const presentationUtil = getStubPluginServices();
@@ -65,6 +66,7 @@ function getProps(props?: Partial): {
getTriggerCompatibleActions: (() => []) as any,
} as any,
presentationUtil,
+ screenshotMode: screenshotModePluginMock.createSetupContract(),
};
const input = getSampleDashboardInput({
diff --git a/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.test.tsx b/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.test.tsx
index 5561d1676e41c..0ef21fca26f29 100644
--- a/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.test.tsx
+++ b/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.test.tsx
@@ -52,7 +52,6 @@ const createDashboardAppStateProps = (): UseDashboardStateProps => ({
savedDashboardId: 'testDashboardId',
history: createBrowserHistory(),
isEmbeddedExternally: false,
- redirectTo: jest.fn(),
});
const createDashboardAppStateServices = () => {
diff --git a/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.ts b/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.ts
index fddcc309e1ef1..cb5c7483f261a 100644
--- a/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.ts
+++ b/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.ts
@@ -22,7 +22,6 @@ import {
DashboardBuildContext,
DashboardAppServices,
DashboardAppState,
- DashboardRedirect,
DashboardState,
} from '../../types';
import { DashboardAppLocatorParams } from '../../locator';
@@ -44,14 +43,12 @@ import {
export interface UseDashboardStateProps {
history: History;
savedDashboardId?: string;
- redirectTo: DashboardRedirect;
isEmbeddedExternally: boolean;
kbnUrlStateStorage: IKbnUrlStateStorage;
}
export const useDashboardAppState = ({
history,
- redirectTo,
savedDashboardId,
kbnUrlStateStorage,
isEmbeddedExternally,
@@ -184,12 +181,20 @@ export const useDashboardAppState = ({
savedDashboard,
});
+ // Backwards compatible way of detecting that we are taking a screenshot
+ const legacyPrintLayoutDetected =
+ screenshotModeService?.isScreenshotMode() &&
+ screenshotModeService.getScreenshotLayout() === 'print';
+
const initialDashboardState = {
...savedDashboardState,
...dashboardSessionStorageState,
...initialDashboardStateFromUrl,
...forwardedAppState,
+ // if we are in legacy print mode, dashboard needs to be in print viewMode
+ ...(legacyPrintLayoutDetected ? { viewMode: ViewMode.PRINT } : {}),
+
// if there is an incoming embeddable, dashboard always needs to be in edit mode to receive it.
...(incomingEmbeddable ? { viewMode: ViewMode.EDIT } : {}),
};
diff --git a/src/plugins/dashboard/public/application/test_helpers/make_default_services.ts b/src/plugins/dashboard/public/application/test_helpers/make_default_services.ts
index cce2b4eb042ef..616fe56102df9 100644
--- a/src/plugins/dashboard/public/application/test_helpers/make_default_services.ts
+++ b/src/plugins/dashboard/public/application/test_helpers/make_default_services.ts
@@ -15,6 +15,7 @@ import { DashboardAppServices, DashboardAppCapabilities } from '../../types';
import { embeddablePluginMock } from '../../../../embeddable/public/mocks';
import { IndexPatternsContract, SavedQueryService } from '../../services/data';
import { savedObjectsPluginMock } from '../../../../saved_objects/public/mocks';
+import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
import { visualizationsPluginMock } from '../../../../visualizations/public/mocks';
import { PluginInitializerContext, ScopedHistory } from '../../../../../core/public';
import { SavedObjectLoader, SavedObjectLoaderFindOptions } from '../../services/saved_objects';
@@ -72,6 +73,7 @@ export function makeDefaultServices(): DashboardAppServices {
} as PluginInitializerContext;
return {
+ screenshotModeService: screenshotModePluginMock.createSetupContract(),
visualizations: visualizationsPluginMock.createStartContract(),
savedObjects: savedObjectsPluginMock.createStartContract(),
embeddable: embeddablePluginMock.createInstance().doStart(),
diff --git a/src/plugins/dashboard/public/dashboard_constants.ts b/src/plugins/dashboard/public/dashboard_constants.ts
index 409d80e2ef066..6f9a30e3a7041 100644
--- a/src/plugins/dashboard/public/dashboard_constants.ts
+++ b/src/plugins/dashboard/public/dashboard_constants.ts
@@ -14,6 +14,7 @@ export const DashboardConstants = {
LANDING_PAGE_PATH: '/list',
CREATE_NEW_DASHBOARD_URL: '/create',
VIEW_DASHBOARD_URL: '/view',
+ PRINT_DASHBOARD_URL: '/print',
ADD_EMBEDDABLE_ID: 'addEmbeddableId',
ADD_EMBEDDABLE_TYPE: 'addEmbeddableType',
DASHBOARDS_ID: 'dashboards',
diff --git a/src/plugins/dashboard/public/locator.ts b/src/plugins/dashboard/public/locator.ts
index a256a65a5d7f4..b6655e246de36 100644
--- a/src/plugins/dashboard/public/locator.ts
+++ b/src/plugins/dashboard/public/locator.ts
@@ -128,6 +128,7 @@ export class DashboardAppLocatorDefinition implements LocatorDefinition => {
diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx
index ff0ac0642ec91..9912aef943144 100644
--- a/src/plugins/dashboard/public/plugin.tsx
+++ b/src/plugins/dashboard/public/plugin.tsx
@@ -12,7 +12,6 @@ import { filter, map } from 'rxjs/operators';
import { Start as InspectorStartContract } from 'src/plugins/inspector/public';
import { UrlForwardingSetup, UrlForwardingStart } from 'src/plugins/url_forwarding/public';
-import { ScreenshotModePluginStart } from 'src/plugins/screenshot_mode/public';
import { APP_WRAPPER_CLASS } from '../../../core/public';
import {
App,
@@ -37,6 +36,10 @@ import { NavigationPublicPluginStart as NavigationStart } from './services/navig
import { DataPublicPluginSetup, DataPublicPluginStart, esFilters } from './services/data';
import { SharePluginSetup, SharePluginStart, UrlGeneratorContract } from './services/share';
import type { SavedObjectTaggingOssPluginStart } from './services/saved_objects_tagging_oss';
+import type {
+ ScreenshotModePluginSetup,
+ ScreenshotModePluginStart,
+} from './services/screenshot_mode';
import {
getSavedObjectFinder,
SavedObjectLoader,
@@ -102,6 +105,7 @@ export interface DashboardSetupDependencies {
share?: SharePluginSetup;
uiActions: UiActionsSetup;
usageCollection?: UsageCollectionSetup;
+ screenshotMode: ScreenshotModePluginSetup;
}
export interface DashboardStartDependencies {
@@ -116,9 +120,9 @@ export interface DashboardStartDependencies {
savedObjects: SavedObjectsStart;
presentationUtil: PresentationUtilPluginStart;
savedObjectsTaggingOss?: SavedObjectTaggingOssPluginStart;
- screenshotMode?: ScreenshotModePluginStart;
spaces?: SpacesPluginStart;
visualizations: VisualizationsStart;
+ screenshotMode: ScreenshotModePluginStart;
}
export interface DashboardSetup {
@@ -162,7 +166,15 @@ export class DashboardPlugin
public setup(
core: CoreSetup,
- { share, embeddable, home, urlForwarding, data, usageCollection }: DashboardSetupDependencies
+ {
+ share,
+ embeddable,
+ home,
+ urlForwarding,
+ data,
+ usageCollection,
+ screenshotMode,
+ }: DashboardSetupDependencies
): DashboardSetup {
this.dashboardFeatureFlagConfig =
this.initializerContext.config.get();
@@ -197,6 +209,7 @@ export class DashboardPlugin
embeddable: deps.embeddable,
uiActions: deps.uiActions,
inspector: deps.inspector,
+ screenshotMode: deps.screenshotMode,
http: coreStart.http,
ExitFullScreenButton,
presentationUtil: deps.presentationUtil,
diff --git a/src/plugins/dashboard/public/services/screenshot_mode.ts b/src/plugins/dashboard/public/services/screenshot_mode.ts
new file mode 100644
index 0000000000000..12ec1bca2207f
--- /dev/null
+++ b/src/plugins/dashboard/public/services/screenshot_mode.ts
@@ -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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+export type {
+ ScreenshotModePluginStart,
+ ScreenshotModePluginSetup,
+} from '../../../screenshot_mode/public';
+
+export type { Layout } from '../../../screenshot_mode/common';
diff --git a/src/plugins/dashboard/public/types.ts b/src/plugins/dashboard/public/types.ts
index d4a6cb20bc551..b7b146aeba348 100644
--- a/src/plugins/dashboard/public/types.ts
+++ b/src/plugins/dashboard/public/types.ts
@@ -19,7 +19,6 @@ import type {
import { History } from 'history';
import { AnyAction, Dispatch } from 'redux';
import { BehaviorSubject, Subject } from 'rxjs';
-import { ScreenshotModePluginStart } from 'src/plugins/screenshot_mode/public';
import { Query, Filter, IndexPattern, RefreshInterval, TimeRange } from './services/data';
import { ContainerInput, EmbeddableInput, ViewMode } from './services/embeddable';
import { SharePluginStart } from './services/share';
@@ -33,6 +32,7 @@ import { SavedObjectsTaggingApi } from './services/saved_objects_tagging_oss';
import { DataPublicPluginStart, IndexPatternsContract } from './services/data';
import { SavedObjectLoader, SavedObjectsStart } from './services/saved_objects';
import { IKbnUrlStateStorage } from './services/kibana_utils';
+import type { ScreenshotModePluginStart } from './services/screenshot_mode';
import type { DashboardContainer, DashboardSavedObject } from '.';
import { VisualizationsStart } from '../../visualizations/public';
import { DashboardAppLocatorParams } from './locator';
@@ -206,9 +206,9 @@ export interface DashboardAppServices {
onAppLeave: AppMountParameters['onAppLeave'];
savedObjectsTagging?: SavedObjectsTaggingApi;
savedObjectsClient: SavedObjectsClientContract;
+ screenshotModeService: ScreenshotModePluginStart;
dashboardSessionStorage: DashboardSessionStorage;
setHeaderActionMenu: AppMountParameters['setHeaderActionMenu'];
savedQueryService: DataPublicPluginStart['query']['savedQueries'];
spacesService?: SpacesPluginStart;
- screenshotModeService?: ScreenshotModePluginStart;
}
diff --git a/src/plugins/embeddable/common/types.ts b/src/plugins/embeddable/common/types.ts
index c3cac2d5d67db..b9d9d4cc34146 100644
--- a/src/plugins/embeddable/common/types.ts
+++ b/src/plugins/embeddable/common/types.ts
@@ -13,6 +13,7 @@ import { PersistableStateService, PersistableState } from '../../kibana_utils/co
export enum ViewMode {
EDIT = 'edit',
PREVIEW = 'preview',
+ PRINT = 'print',
VIEW = 'view',
}
diff --git a/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx b/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx
index 9807a47698a50..6748e9f3b1d08 100644
--- a/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx
+++ b/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx
@@ -251,7 +251,7 @@ export class EmbeddablePanel extends React.Component {
};
public render() {
- const viewOnlyMode = this.state.viewMode === ViewMode.VIEW;
+ const viewOnlyMode = [ViewMode.VIEW, ViewMode.PRINT].includes(this.state.viewMode);
const classes = classNames('embPanel', {
'embPanel--editing': !viewOnlyMode,
'embPanel--loading': this.state.loading,
diff --git a/src/plugins/newsfeed/public/plugin.test.ts b/src/plugins/newsfeed/public/plugin.test.ts
index 4be69feb79f55..3497a1e52697d 100644
--- a/src/plugins/newsfeed/public/plugin.test.ts
+++ b/src/plugins/newsfeed/public/plugin.test.ts
@@ -10,6 +10,7 @@ import { take } from 'rxjs/operators';
import { coreMock } from '../../../core/public/mocks';
import { NewsfeedPublicPlugin } from './plugin';
import { NewsfeedApiEndpoint } from './lib/api';
+import { screenshotModePluginMock } from '../../screenshot_mode/public/mocks';
describe('Newsfeed plugin', () => {
let plugin: NewsfeedPublicPlugin;
@@ -46,7 +47,7 @@ describe('Newsfeed plugin', () => {
describe('base case', () => {
it('makes fetch requests', () => {
const startContract = plugin.start(coreMock.createStart(), {
- screenshotMode: { isScreenshotMode: () => false },
+ screenshotMode: screenshotModePluginMock.createSetupContract(),
});
const sub = startContract
.createNewsFeed$(NewsfeedApiEndpoint.KIBANA) // Any endpoint will do
@@ -60,8 +61,10 @@ describe('Newsfeed plugin', () => {
describe('when in screenshot mode', () => {
it('makes no fetch requests in screenshot mode', () => {
+ const screenshotMode = screenshotModePluginMock.createSetupContract();
+ screenshotMode.isScreenshotMode.mockReturnValue(true);
const startContract = plugin.start(coreMock.createStart(), {
- screenshotMode: { isScreenshotMode: () => true },
+ screenshotMode,
});
const sub = startContract
.createNewsFeed$(NewsfeedApiEndpoint.KIBANA) // Any endpoint will do
diff --git a/src/plugins/screenshot_mode/common/get_set_browser_screenshot_mode.ts b/src/plugins/screenshot_mode/common/get_set_browser_screenshot_mode.ts
index ff79ccf0126f4..850f70d2d002a 100644
--- a/src/plugins/screenshot_mode/common/get_set_browser_screenshot_mode.ts
+++ b/src/plugins/screenshot_mode/common/get_set_browser_screenshot_mode.ts
@@ -7,7 +7,7 @@
*/
// **PLEASE NOTE**
-// The functionality in this file targets a browser environment and is intended to be used both in public and server.
+// The functionality in this file targets a browser environment AND is intended to be used both in public and server.
// For instance, reporting uses these functions when starting puppeteer to set the current browser into "screenshot" mode.
export const KBN_SCREENSHOT_MODE_ENABLED_KEY = '__KBN_SCREENSHOT_MODE_ENABLED_KEY__';
@@ -61,3 +61,31 @@ export const setScreenshotModeDisabled = () => {
}
);
};
+
+/** @deprecated */
+export const KBN_SCREENSHOT_MODE_LAYOUT_KEY = '__KBN_SCREENSHOT_MODE_LAYOUT_KEY__';
+
+/** @deprecated */
+export type Layout = 'canvas' | 'preserve_layout' | 'print';
+
+/** @deprecated */
+export const setScreenshotLayout = (value: Layout) => {
+ Object.defineProperty(
+ window,
+ '__KBN_SCREENSHOT_MODE_LAYOUT_KEY__', // Literal value to prevent adding an external reference
+ {
+ enumerable: true,
+ writable: true,
+ configurable: false,
+ value,
+ }
+ );
+};
+
+/** @deprecated */
+export const getScreenshotLayout = (): undefined | Layout => {
+ return (
+ (window as unknown as Record)[KBN_SCREENSHOT_MODE_LAYOUT_KEY] ||
+ (window.localStorage.getItem(KBN_SCREENSHOT_MODE_LAYOUT_KEY) as Layout)
+ );
+};
diff --git a/src/plugins/screenshot_mode/common/index.ts b/src/plugins/screenshot_mode/common/index.ts
index 9c8c3d24ef289..949691911fc27 100644
--- a/src/plugins/screenshot_mode/common/index.ts
+++ b/src/plugins/screenshot_mode/common/index.ts
@@ -11,6 +11,11 @@ export {
setScreenshotModeEnabled,
setScreenshotModeDisabled,
KBN_SCREENSHOT_MODE_ENABLED_KEY,
+ KBN_SCREENSHOT_MODE_LAYOUT_KEY,
+ setScreenshotLayout,
+ getScreenshotLayout,
} from './get_set_browser_screenshot_mode';
+export type { Layout } from './get_set_browser_screenshot_mode';
+
export { KBN_SCREENSHOT_MODE_HEADER } from './constants';
diff --git a/src/plugins/screenshot_mode/public/mocks.ts b/src/plugins/screenshot_mode/public/mocks.ts
index 7fa93ff0bcea8..d7e69e9d89211 100644
--- a/src/plugins/screenshot_mode/public/mocks.ts
+++ b/src/plugins/screenshot_mode/public/mocks.ts
@@ -11,9 +11,11 @@ import type { ScreenshotModePluginSetup, ScreenshotModePluginStart } from './typ
export const screenshotModePluginMock = {
createSetupContract: (): DeeplyMockedKeys => ({
+ getScreenshotLayout: jest.fn(),
isScreenshotMode: jest.fn(() => false),
}),
createStartContract: (): DeeplyMockedKeys => ({
+ getScreenshotLayout: jest.fn(),
isScreenshotMode: jest.fn(() => false),
}),
};
diff --git a/src/plugins/screenshot_mode/public/plugin.ts b/src/plugins/screenshot_mode/public/plugin.ts
index a005bb7c3d055..bb34fe84e2c39 100644
--- a/src/plugins/screenshot_mode/public/plugin.ts
+++ b/src/plugins/screenshot_mode/public/plugin.ts
@@ -10,11 +10,12 @@ import { CoreSetup, CoreStart, Plugin } from '../../../core/public';
import { ScreenshotModePluginSetup, ScreenshotModePluginStart } from './types';
-import { getScreenshotMode } from '../common';
+import { getScreenshotMode, getScreenshotLayout } from '../common';
export class ScreenshotModePlugin implements Plugin {
private publicContract = Object.freeze({
isScreenshotMode: () => getScreenshotMode() === true,
+ getScreenshotLayout,
});
public setup(core: CoreSetup): ScreenshotModePluginSetup {
diff --git a/src/plugins/screenshot_mode/public/types.ts b/src/plugins/screenshot_mode/public/types.ts
index f6963de0cbd63..d1603cbceb26f 100644
--- a/src/plugins/screenshot_mode/public/types.ts
+++ b/src/plugins/screenshot_mode/public/types.ts
@@ -6,12 +6,17 @@
* Side Public License, v 1.
*/
+import type { Layout } from '../common';
+
export interface IScreenshotModeService {
/**
* Returns a boolean indicating whether the current user agent (browser) would like to view UI optimized for
* screenshots or printing.
*/
isScreenshotMode: () => boolean;
+
+ /** @deprecated */
+ getScreenshotLayout: () => undefined | Layout;
}
export type ScreenshotModePluginSetup = IScreenshotModeService;
diff --git a/src/plugins/screenshot_mode/server/plugin.ts b/src/plugins/screenshot_mode/server/plugin.ts
index 9295451f640c2..b885ff97bf262 100644
--- a/src/plugins/screenshot_mode/server/plugin.ts
+++ b/src/plugins/screenshot_mode/server/plugin.ts
@@ -30,10 +30,11 @@ export class ScreenshotModePlugin
// We use "require" here to ensure the import does not have external references due to code bundling that
// commonly happens during transpiling. External references would be missing in the environment puppeteer creates.
// eslint-disable-next-line @typescript-eslint/no-var-requires
- const { setScreenshotModeEnabled } = require('../common');
+ const { setScreenshotModeEnabled, setScreenshotLayout } = require('../common');
return {
setScreenshotModeEnabled,
+ setScreenshotLayout,
isScreenshotMode,
};
}
diff --git a/src/plugins/screenshot_mode/server/types.ts b/src/plugins/screenshot_mode/server/types.ts
index 566ae19719454..1b9f3868f0966 100644
--- a/src/plugins/screenshot_mode/server/types.ts
+++ b/src/plugins/screenshot_mode/server/types.ts
@@ -6,7 +6,8 @@
* Side Public License, v 1.
*/
-import { RequestHandlerContext, KibanaRequest } from 'src/core/server';
+import type { RequestHandlerContext, KibanaRequest } from 'src/core/server';
+import type { Layout } from '../common';
/**
* Any context that requires access to the screenshot mode flag but does not have access
@@ -23,6 +24,9 @@ export interface ScreenshotModePluginSetup {
* on the page have run to ensure that screenshot mode is detected as early as possible.
*/
setScreenshotModeEnabled: () => void;
+
+ /** @deprecated */
+ setScreenshotLayout: (value: Layout) => void;
}
export interface ScreenshotModePluginStart {
diff --git a/x-pack/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts b/x-pack/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts
index 0947d24f827c2..0f2572ff2b2e4 100644
--- a/x-pack/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts
+++ b/x-pack/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts
@@ -17,7 +17,7 @@ import { ReportingCore } from '../../..';
import { KBN_SCREENSHOT_MODE_HEADER } from '../../../../../../../src/plugins/screenshot_mode/server';
import { ConditionalHeaders, ConditionalHeadersConditions } from '../../../export_types/common';
import { LevelLogger } from '../../../lib';
-import { ViewZoomWidthHeight } from '../../../lib/layouts/layout';
+import { Layout, ViewZoomWidthHeight } from '../../../lib/layouts/layout';
import { ElementPosition } from '../../../lib/screenshots';
import { allowRequest, NetworkPolicy } from '../../network_policy';
@@ -97,11 +97,13 @@ export class HeadlessChromiumDriver {
waitForSelector: pageLoadSelector,
timeout,
locator,
+ layout,
}: {
conditionalHeaders: ConditionalHeaders;
waitForSelector: string;
timeout: number;
locator?: LocatorParams;
+ layout?: Layout;
},
logger: LevelLogger
): Promise {
@@ -116,6 +118,10 @@ export class HeadlessChromiumDriver {
*/
await this.page.evaluateOnNewDocument(this.core.getEnableScreenshotMode());
+ if (layout) {
+ await this.page.evaluateOnNewDocument(this.core.getSetScreenshotLayout(), layout.id);
+ }
+
if (locator) {
await this.page.evaluateOnNewDocument(
(key: string, value: unknown) => {
diff --git a/x-pack/plugins/reporting/server/core.ts b/x-pack/plugins/reporting/server/core.ts
index bc74f5463ba33..43aefb73aebb9 100644
--- a/x-pack/plugins/reporting/server/core.ts
+++ b/x-pack/plugins/reporting/server/core.ts
@@ -253,9 +253,16 @@ export class ReportingCore {
.toPromise();
}
+ private getScreenshotModeDep() {
+ return this.getPluginSetupDeps().screenshotMode;
+ }
+
public getEnableScreenshotMode() {
- const { screenshotMode } = this.getPluginSetupDeps();
- return screenshotMode.setScreenshotModeEnabled;
+ return this.getScreenshotModeDep().setScreenshotModeEnabled;
+ }
+
+ public getSetScreenshotLayout() {
+ return this.getScreenshotModeDep().setScreenshotLayout;
}
/*
diff --git a/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.css b/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.css
index 508d217cdd030..60513c417165f 100644
--- a/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.css
+++ b/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.css
@@ -5,7 +5,7 @@
******
*/
- /**
+/**
* global
*/
@@ -27,7 +27,6 @@ filter-bar,
* Discover Tweaks
*/
-
/* hide unusable controls */
discover-app .dscTimechart,
discover-app .dscSidebar__container,
@@ -36,7 +35,6 @@ discover-app .discover-table-footer {
display: none;
}
-
/**
* The global banner (e.g. "Help us improve Elastic...") should not print.
*/
@@ -73,7 +71,8 @@ discover-app .discover-table-footer {
position: fixed;
width: 100%;
height: 100%;
- top: 0; left: 0;
+ top: 0;
+ left: 0;
}
/**
diff --git a/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts b/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts
index 424e85327c22b..7f6bc9e5d9505 100644
--- a/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts
+++ b/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts
@@ -4,7 +4,6 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-
import path from 'path';
import { CustomPageSize } from 'pdfmake/interfaces';
import { LAYOUT_TYPES } from '../../../common/constants';
@@ -37,6 +36,7 @@ export class PreserveLayout extends Layout implements LayoutInstance {
}
public getCssOverridesPath() {
+ // TODO: Remove this path once we have migrated all plugins away from depending on this hiding page elements.
return path.join(__dirname, 'preserve_layout.css');
}
diff --git a/x-pack/plugins/reporting/server/lib/layouts/print.css b/x-pack/plugins/reporting/server/lib/layouts/print.css
deleted file mode 100644
index 7d38ebe81e4e8..0000000000000
--- a/x-pack/plugins/reporting/server/lib/layouts/print.css
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- ******
- ****** This is a collection of CSS overrides that make Kibana look better for
- ****** generating PDF reports with headless browser
- ******
- */
-
-/**
- * global
- */
-
-/* elements can hide themselves when shared */
-.hide-for-sharing {
- display: none !important;
-}
-
-/* hide unusable controls */
-kbn-top-nav,
-filter-bar,
-.kbnTopNavMenu__wrapper,
-::-webkit-scrollbar,
-.euiNavDrawer {
- display: none !important;
-}
-
-/**
- * Discover Tweaks
- */
-
-/* hide unusable controls */
-discover-app .dscTimechart,
-discover-app .dscSidebar__container,
-discover-app .dscCollapsibleSidebar__collapseButton,
-discover-app .discover-table-footer {
- display: none;
-}
-
-/**
- * The global banner (e.g. "Help us improve Elastic...") should not print.
- */
-
-#globalBannerList {
- display: none;
-}
-
-/**
- * Visualize Editor Tweaks
- */
-
-/* hide unusable controls
-* !important is required to override resizable panel inline display */
-.visEditor__content .visEditor--default > :not(.visEditor__visualization__wrapper) {
- display: none !important;
-}
-/** THIS IS FOR TSVB UNTIL REFACTOR **/
-.tvbEditorVisualization {
- position: static !important;
-}
-.visualize .tvbVisTimeSeries__legendToggle,
-.tvbEditor--hideForReporting {
- /* all non-content rows in interface */
- display: none;
-}
-/** END TSVB BAD BAD HACKS **/
-
-/* remove left padding from visualizations so that map lines up with .leaflet-container and
-* setting the position to be fixed and to take up the entire screen, because some zoom levels/viewports
-* are triggering the media breakpoints that cause the .visEditor__canvas to take up more room than the viewport */
-.visEditor .visEditor__canvas {
- padding-left: 0px;
- position: fixed;
- width: 100%;
- height: 100%;
- top: 0;
- left: 0;
-}
-
-/**
- * Visualization tweaks
- */
-
-/* hide unusable controls */
-.visualize .visLegend__toggle,
-.visualize .kbnAggTable__controls/* export raw, export formatted, etc. */,
-.visualize .leaflet-container .leaflet-top.leaflet-left/* tilemap controls */,
-.visualize paginate-controls {
- display: none;
-}
-
-/* Ensure the min-height of the small breakpoint isn't used */
-.vis-editor visualization {
- min-height: 0 !important;
-}
-
-/**
-* Dashboard tweaks
-*/
-
-.dashboardViewport .embPanel__header {
- /* hide the panel heading with the controls and title */
- display: none !important;
-}
-
-.dashboardViewport .euiPanel {
- /* Remove the border from the eui panel */
- border: none !important;
-}
-
-/**
- * 1. Reporting manually makes each visualization it wants to screenshot larger, so we need to hide
- * the visualizations in the other panels. We can only use properties that will be manually set in
- * reporting/export_types/printable_pdf/lib/screenshot.js or this will also hide the visualization
- * we want to capture.
- * 2. React grid item's transform affects the visualizations, even when they are using fixed positioning. Chrome seems
- * to handle this fine, but firefox moves the visualizations around.
- */
-.dashboardViewport .react-grid-item {
- height: 0 !important; /* 1. */
- width: 0 !important; /* 1. */
- transform: none !important; /* 2. */
- -webkit-transform: none !important; /* 2. */
-}
diff --git a/x-pack/plugins/reporting/server/lib/layouts/print_layout.ts b/x-pack/plugins/reporting/server/lib/layouts/print_layout.ts
index 0849f8850f91d..68226affb41e4 100644
--- a/x-pack/plugins/reporting/server/lib/layouts/print_layout.ts
+++ b/x-pack/plugins/reporting/server/lib/layouts/print_layout.ts
@@ -5,13 +5,8 @@
* 2.0.
*/
-import path from 'path';
import { PageOrientation, PredefinedPageSize } from 'pdfmake/interfaces';
-import { EvaluateFn, SerializableOrJSHandle } from 'puppeteer';
-import { LevelLogger } from '../';
import { DEFAULT_VIEWPORT, LAYOUT_TYPES } from '../../../common/constants';
-import { Size } from '../../../common/types';
-import { HeadlessChromiumDriver } from '../../browsers';
import { CaptureConfig } from '../../types';
import { getDefaultLayoutSelectors, LayoutInstance, LayoutSelectorDictionary } from './';
import { Layout } from './layout';
@@ -31,7 +26,7 @@ export class PrintLayout extends Layout implements LayoutInstance {
}
public getCssOverridesPath() {
- return path.join(__dirname, 'print.css');
+ return undefined;
}
public getBrowserViewport() {
@@ -49,40 +44,6 @@ export class PrintLayout extends Layout implements LayoutInstance {
height: this.viewport.height * itemsCount,
};
}
-
- public async positionElements(
- browser: HeadlessChromiumDriver,
- logger: LevelLogger
- ): Promise {
- logger.debug('positioning elements');
-
- const elementSize: Size = {
- width: this.viewport.width / this.captureConfig.zoom,
- height: this.viewport.height / this.captureConfig.zoom,
- };
- const evalOptions: { fn: EvaluateFn; args: SerializableOrJSHandle[] } = {
- fn: (selector: string, height: number, width: number) => {
- const visualizations = document.querySelectorAll(selector) as NodeListOf;
- const visualizationsLength = visualizations.length;
-
- for (let i = 0; i < visualizationsLength; i++) {
- const visualization = visualizations[i];
- const style = visualization.style;
- style.position = 'fixed';
- style.top = `${height * i}px`;
- style.left = '0';
- style.width = `${width}px`;
- style.height = `${height}px`;
- style.zIndex = '1';
- style.backgroundColor = 'inherit';
- }
- },
- args: [this.selectors.screenshot, elementSize.height, elementSize.width],
- };
-
- await browser.evaluate(evalOptions, { context: 'PositionElements' }, logger);
- }
-
public getPdfImageSize() {
return {
width: 500,
diff --git a/x-pack/plugins/reporting/server/lib/screenshots/observable_handler.ts b/x-pack/plugins/reporting/server/lib/screenshots/observable_handler.ts
index 1db313b091025..cdbddb8d89c89 100644
--- a/x-pack/plugins/reporting/server/lib/screenshots/observable_handler.ts
+++ b/x-pack/plugins/reporting/server/lib/screenshots/observable_handler.ts
@@ -76,6 +76,7 @@ export class ScreenshotObservableHandler {
index,
urlOrUrlLocatorTuple,
this.conditionalHeaders,
+ this.layout,
this.logger
)
).pipe(this.waitUntil(this.timeouts.openUrl));
diff --git a/x-pack/plugins/reporting/server/lib/screenshots/open_url.ts b/x-pack/plugins/reporting/server/lib/screenshots/open_url.ts
index 63a5e80289e3e..b26037aa917b8 100644
--- a/x-pack/plugins/reporting/server/lib/screenshots/open_url.ts
+++ b/x-pack/plugins/reporting/server/lib/screenshots/open_url.ts
@@ -10,6 +10,7 @@ import { LevelLogger, startTrace } from '../';
import { LocatorParams, UrlOrUrlLocatorTuple } from '../../../common/types';
import { HeadlessChromiumDriver } from '../../browsers';
import { ConditionalHeaders } from '../../export_types/common';
+import { Layout } from '../layouts';
import { DEFAULT_PAGELOAD_SELECTOR } from './constants';
export const openUrl = async (
@@ -18,6 +19,7 @@ export const openUrl = async (
index: number,
urlOrUrlLocatorTuple: UrlOrUrlLocatorTuple,
conditionalHeaders: ConditionalHeaders,
+ layout: undefined | Layout,
logger: LevelLogger
): Promise => {
// If we're moving to another page in the app, we'll want to wait for the app to tell us
@@ -36,7 +38,11 @@ export const openUrl = async (
}
try {
- await browser.open(url, { conditionalHeaders, waitForSelector, timeout, locator }, logger);
+ await browser.open(
+ url,
+ { conditionalHeaders, waitForSelector, timeout, locator, layout },
+ logger
+ );
} catch (err) {
logger.error(err);
throw new Error(
From 71166d24e52306359cf9ff8294956fb4b6b83ebf Mon Sep 17 00:00:00 2001
From: David Roberts
Date: Mon, 29 Nov 2021 14:48:46 +0000
Subject: [PATCH 12/47] [Upgrade assistant] Fix the "Fix" button for ML
snapshots in need of upgrade (#119745)
The deprecations for ML snapshots that are too old and need
upgrading are supposed to have a "Fix" button next to them.
Unfortunately this disappeared when a message was reworded
in elastic/elasticsearch#79387.
This change adjusts the regex that the upgrade assistant
uses to detect which deprecations to add the "Fix" button
to so that it will match both "Model snapshot" and "model
snapshot". The test data is also updated to match the new
backend text.
This change is designed to work with elastic/elasticsearch#81060.
---
.../upgrade_assistant/server/lib/es_deprecations_status.ts | 2 +-
.../plugins/upgrade_assistant/server/routes/ml_snapshots.ts | 2 +-
.../plugins/upgrade_assistant/server/routes/status.test.ts | 5 ++---
3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts
index 2e2c80b790cd5..e334d214f2463 100644
--- a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts
+++ b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts
@@ -139,7 +139,7 @@ const getCorrectiveAction = (
);
const requiresReindexAction = /Index created before/.test(message);
const requiresIndexSettingsAction = Boolean(indexSettingDeprecation);
- const requiresMlAction = /model snapshot/.test(message);
+ const requiresMlAction = /[Mm]odel snapshot/.test(message);
if (requiresReindexAction) {
return {
diff --git a/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts b/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts
index fa6af0f5e4228..69c7c24b63123 100644
--- a/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts
+++ b/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts
@@ -63,7 +63,7 @@ const verifySnapshotUpgrade = async (
const { body: deprecations } = await esClient.asCurrentUser.migration.deprecations();
const mlSnapshotDeprecations = deprecations.ml_settings.filter((deprecation) => {
- return /model snapshot/.test(deprecation.message);
+ return /[Mm]odel snapshot/.test(deprecation.message);
});
// If there are no ML deprecations, we assume the deprecation was resolved successfully
diff --git a/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts
index e442d3b4fd11c..b11993e2baa5a 100644
--- a/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts
+++ b/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts
@@ -49,9 +49,8 @@ describe('Status API', () => {
{
level: 'critical',
message:
- 'model snapshot [1] for job [deprecation_check_job] needs to be deleted or upgraded',
- details:
- 'model snapshot [%s] for job [%s] supports minimum version [%s] and needs to be at least [%s]',
+ 'Model snapshot [1] for job [deprecation_check_job] has an obsolete minimum version [6.3.0].',
+ details: 'Delete model snapshot [1] or update it to 7.0.0 or greater.',
url: 'doc_url',
correctiveAction: {
type: 'mlSnapshot',
From 81374de4f611e1df4e99f87c54f6d878e640057e Mon Sep 17 00:00:00 2001
From: Tiago Costa
Date: Mon, 29 Nov 2021 14:59:43 +0000
Subject: [PATCH 13/47] skip flaky suite (#116865)
---
x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts
index bb89fa8f683fa..1d8a172e57b78 100644
--- a/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts
+++ b/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts
@@ -142,7 +142,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
});
});
- describe('tls alert', function () {
+ // FLAKY: https://github.com/elastic/kibana/issues/116865
+ describe.skip('tls alert', function () {
const DEFAULT_DATE_START = 'Sep 10, 2019 @ 12:40:08.078';
const DEFAULT_DATE_END = 'Sep 11, 2019 @ 19:40:08.078';
let alerts: any;
From ae9d51b7fe3ee6f30d0d196c782e0dcabb7ac5ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?=
Date: Mon, 29 Nov 2021 16:12:27 +0100
Subject: [PATCH 14/47] [APM] Remove log-log descriptions from correlation
charts (#119700)
---
.../app/correlations/chart_title_tool_tip.tsx | 25 +++
.../failed_transactions_correlations.tsx | 175 ++++++------------
...get_transaction_distribution_chart_data.ts | 61 ++++++
.../app/correlations/latency_correlations.tsx | 80 +++-----
.../correlations/use_transaction_colors.ts | 17 --
.../distribution/index.tsx | 139 ++++++--------
...use_transaction_distribution_chart_data.ts | 36 +---
.../transaction_distribution_chart/index.tsx | 14 +-
.../translations/translations/ja-JP.json | 4 -
.../translations/translations/zh-CN.json | 4 -
10 files changed, 233 insertions(+), 322 deletions(-)
create mode 100644 x-pack/plugins/apm/public/components/app/correlations/chart_title_tool_tip.tsx
create mode 100644 x-pack/plugins/apm/public/components/app/correlations/get_transaction_distribution_chart_data.ts
delete mode 100644 x-pack/plugins/apm/public/components/app/correlations/use_transaction_colors.ts
diff --git a/x-pack/plugins/apm/public/components/app/correlations/chart_title_tool_tip.tsx b/x-pack/plugins/apm/public/components/app/correlations/chart_title_tool_tip.tsx
new file mode 100644
index 0000000000000..ed2bd49858310
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/app/correlations/chart_title_tool_tip.tsx
@@ -0,0 +1,25 @@
+/*
+ * 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 React from 'react';
+import { EuiIconTip } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+export function ChartTitleToolTip() {
+ return (
+
+ );
+}
diff --git a/x-pack/plugins/apm/public/components/app/correlations/failed_transactions_correlations.tsx b/x-pack/plugins/apm/public/components/app/correlations/failed_transactions_correlations.tsx
index b2efae74c9c74..c642ca7bd577f 100644
--- a/x-pack/plugins/apm/public/components/app/correlations/failed_transactions_correlations.tsx
+++ b/x-pack/plugins/apm/public/components/app/correlations/failed_transactions_correlations.tsx
@@ -18,7 +18,6 @@ import {
EuiTitle,
EuiBetaBadge,
EuiBadge,
- EuiText,
EuiToolTip,
EuiSwitch,
EuiIconTip,
@@ -27,13 +26,11 @@ import type { EuiTableSortingType } from '@elastic/eui/src/components/basic_tabl
import type { Direction } from '@elastic/eui/src/services/sort/sort_direction';
import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n-react';
import { useUiTracker } from '../../../../../observability/public';
import { asPercent } from '../../../../common/utils/formatters';
import { FailedTransactionsCorrelation } from '../../../../common/correlations/failed_transactions_correlations/types';
-import { DEFAULT_PERCENTILE_THRESHOLD } from '../../../../common/correlations/constants';
import { FieldStats } from '../../../../common/correlations/field_stats_types';
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
@@ -48,18 +45,17 @@ import { CorrelationsTable } from './correlations_table';
import { FailedTransactionsCorrelationsHelpPopover } from './failed_transactions_correlations_help_popover';
import { getFailedTransactionsCorrelationImpactLabel } from './utils/get_failed_transactions_correlation_impact_label';
import { getOverallHistogram } from './utils/get_overall_histogram';
-import {
- TransactionDistributionChart,
- TransactionDistributionChartData,
-} from '../../shared/charts/transaction_distribution_chart';
+import { TransactionDistributionChart } from '../../shared/charts/transaction_distribution_chart';
import { CorrelationsEmptyStatePrompt } from './empty_state_prompt';
import { CrossClusterSearchCompatibilityWarning } from './cross_cluster_search_warning';
import { CorrelationsProgressControls } from './progress_controls';
-import { useTransactionColors } from './use_transaction_colors';
import { CorrelationsContextPopover } from './context_popover';
import { OnAddFilter } from './context_popover/top_values';
import { useFailedTransactionsCorrelations } from './use_failed_transactions_correlations';
+import { getTransactionDistributionChartData } from './get_transaction_distribution_chart_data';
+import { ChartTitleToolTip } from './chart_title_tool_tip';
+import { MIN_TAB_TITLE_HEIGHT } from '../transaction_details/distribution';
export function FailedTransactionsCorrelations({
onFilter,
@@ -67,7 +63,6 @@ export function FailedTransactionsCorrelations({
onFilter: () => void;
}) {
const euiTheme = useTheme();
- const transactionColors = useTransactionColors();
const {
core: { notifications },
@@ -427,133 +422,75 @@ export function FailedTransactionsCorrelations({
correlationTerms.length < 1 &&
(progress.loaded === 1 || !progress.isRunning);
- const transactionDistributionChartData: TransactionDistributionChartData[] =
- [];
-
- if (Array.isArray(overallHistogram)) {
- transactionDistributionChartData.push({
- id: i18n.translate(
- 'xpack.apm.transactionDistribution.chart.allTransactionsLabel',
- { defaultMessage: 'All transactions' }
- ),
- histogram: overallHistogram,
- });
- }
-
- if (Array.isArray(response.errorHistogram)) {
- transactionDistributionChartData.push({
- id: i18n.translate(
- 'xpack.apm.transactionDistribution.chart.failedTransactionsLabel',
- { defaultMessage: 'Failed transactions' }
- ),
- histogram: response.errorHistogram,
- });
- }
-
- if (selectedTerm && Array.isArray(selectedTerm.histogram)) {
- transactionDistributionChartData.push({
- id: `${selectedTerm.fieldName}:${selectedTerm.fieldValue}`,
- histogram: selectedTerm.histogram,
- });
- }
+ const transactionDistributionChartData = getTransactionDistributionChartData({
+ euiTheme,
+ allTransactionsHistogram: overallHistogram,
+ failedTransactionsHistogram: response.errorHistogram,
+ selectedTerm,
+ });
return (
-
-
-
-
-
- {i18n.translate(
- 'xpack.apm.correlations.failedTransactions.panelTitle',
- {
- defaultMessage: 'Failed transactions latency distribution',
- }
- )}
-
-
-
-
-
-
+
+
+
+ {i18n.translate(
+ 'xpack.apm.correlations.failedTransactions.panelTitle',
{
- defaultMessage:
- 'Failed transaction correlations is not GA. Please help us by reporting any bugs.',
+ defaultMessage: 'Failed transactions latency distribution',
}
)}
- />
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
- {selectedTerm && (
-
- ,
- allTransactions: (
-
-
-
- ),
- failedTransactions: (
-
-
-
- ),
- focusTransaction: (
-
- {selectedTerm?.fieldName}:{selectedTerm?.fieldValue}
-
- ),
- }}
- />
-
- )}
+
diff --git a/x-pack/plugins/apm/public/components/app/correlations/get_transaction_distribution_chart_data.ts b/x-pack/plugins/apm/public/components/app/correlations/get_transaction_distribution_chart_data.ts
new file mode 100644
index 0000000000000..49ddd8aec0fe4
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/app/correlations/get_transaction_distribution_chart_data.ts
@@ -0,0 +1,61 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { i18n } from '@kbn/i18n';
+import { EuiTheme } from '../../../../../../../src/plugins/kibana_react/common';
+import type {
+ FieldValuePair,
+ HistogramItem,
+} from '../../../../common/correlations/types';
+import { TransactionDistributionChartData } from '../../shared/charts/transaction_distribution_chart';
+
+export function getTransactionDistributionChartData({
+ euiTheme,
+ allTransactionsHistogram,
+ failedTransactionsHistogram,
+ selectedTerm,
+}: {
+ euiTheme: EuiTheme;
+ allTransactionsHistogram?: HistogramItem[];
+ failedTransactionsHistogram?: HistogramItem[];
+ selectedTerm?: FieldValuePair & { histogram: HistogramItem[] };
+}) {
+ const transactionDistributionChartData: TransactionDistributionChartData[] =
+ [];
+
+ if (Array.isArray(allTransactionsHistogram)) {
+ transactionDistributionChartData.push({
+ id: i18n.translate(
+ 'xpack.apm.transactionDistribution.chart.allTransactionsLabel',
+ { defaultMessage: 'All transactions' }
+ ),
+ histogram: allTransactionsHistogram,
+ areaSeriesColor: euiTheme.eui.euiColorVis1,
+ });
+ }
+
+ if (Array.isArray(failedTransactionsHistogram)) {
+ transactionDistributionChartData.push({
+ id: i18n.translate(
+ 'xpack.apm.transactionDistribution.chart.failedTransactionsLabel',
+ { defaultMessage: 'Failed transactions' }
+ ),
+ histogram: failedTransactionsHistogram,
+ areaSeriesColor: euiTheme.eui.euiColorVis7,
+ });
+ }
+
+ if (selectedTerm && Array.isArray(selectedTerm.histogram)) {
+ transactionDistributionChartData.push({
+ id: `${selectedTerm.fieldName}:${selectedTerm.fieldValue}`,
+ histogram: selectedTerm.histogram,
+ areaSeriesColor: euiTheme.eui.euiColorVis2,
+ });
+ }
+
+ return transactionDistributionChartData;
+}
diff --git a/x-pack/plugins/apm/public/components/app/correlations/latency_correlations.tsx b/x-pack/plugins/apm/public/components/app/correlations/latency_correlations.tsx
index 629868fb88bf6..f79e955595717 100644
--- a/x-pack/plugins/apm/public/components/app/correlations/latency_correlations.tsx
+++ b/x-pack/plugins/apm/public/components/app/correlations/latency_correlations.tsx
@@ -15,7 +15,6 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiSpacer,
- EuiText,
EuiTitle,
EuiToolTip,
} from '@elastic/eui';
@@ -23,22 +22,17 @@ import { Direction } from '@elastic/eui/src/services/sort/sort_direction';
import { EuiTableSortingType } from '@elastic/eui/src/components/basic_table/table_types';
import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n-react';
import { useUiTracker } from '../../../../../observability/public';
import { asPreciseDecimal } from '../../../../common/utils/formatters';
-import { DEFAULT_PERCENTILE_THRESHOLD } from '../../../../common/correlations/constants';
import { LatencyCorrelation } from '../../../../common/correlations/latency_correlations/types';
import { FieldStats } from '../../../../common/correlations/field_stats_types';
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
import { FETCH_STATUS } from '../../../hooks/use_fetcher';
-import {
- TransactionDistributionChart,
- TransactionDistributionChartData,
-} from '../../shared/charts/transaction_distribution_chart';
+import { TransactionDistributionChart } from '../../shared/charts/transaction_distribution_chart';
import { push } from '../../shared/Links/url_helpers';
import { CorrelationsTable } from './correlations_table';
@@ -47,18 +41,21 @@ import { getOverallHistogram } from './utils/get_overall_histogram';
import { CorrelationsEmptyStatePrompt } from './empty_state_prompt';
import { CrossClusterSearchCompatibilityWarning } from './cross_cluster_search_warning';
import { CorrelationsProgressControls } from './progress_controls';
-import { useTransactionColors } from './use_transaction_colors';
import { CorrelationsContextPopover } from './context_popover';
import { OnAddFilter } from './context_popover/top_values';
import { useLatencyCorrelations } from './use_latency_correlations';
+import { getTransactionDistributionChartData } from './get_transaction_distribution_chart_data';
+import { useTheme } from '../../../hooks/use_theme';
+import { ChartTitleToolTip } from './chart_title_tool_tip';
+import { MIN_TAB_TITLE_HEIGHT } from '../transaction_details/distribution';
export function LatencyCorrelations({ onFilter }: { onFilter: () => void }) {
- const transactionColors = useTransactionColors();
-
const {
core: { notifications },
} = useApmPluginContext();
+ const euiTheme = useTheme();
+
const { progress, response, startFetch, cancelFetch } =
useLatencyCorrelations();
const { overallHistogram, hasData, status } = getOverallHistogram(
@@ -274,30 +271,20 @@ export function LatencyCorrelations({ onFilter }: { onFilter: () => void }) {
const showCorrelationsEmptyStatePrompt =
histogramTerms.length < 1 && (progress.loaded === 1 || !progress.isRunning);
- const transactionDistributionChartData: TransactionDistributionChartData[] =
- [];
-
- if (Array.isArray(overallHistogram)) {
- transactionDistributionChartData.push({
- id: i18n.translate(
- 'xpack.apm.transactionDistribution.chart.allTransactionsLabel',
- { defaultMessage: 'All transactions' }
- ),
- histogram: overallHistogram,
- });
- }
-
- if (selectedHistogram && Array.isArray(selectedHistogram.histogram)) {
- transactionDistributionChartData.push({
- id: `${selectedHistogram.fieldName}:${selectedHistogram.fieldValue}`,
- histogram: selectedHistogram.histogram,
- });
- }
+ const transactionDistributionChartData = getTransactionDistributionChartData({
+ euiTheme,
+ allTransactionsHistogram: overallHistogram,
+ selectedTerm: selectedHistogram,
+ });
return (
-
-
+
+
{i18n.translate(
@@ -309,40 +296,19 @@ export function LatencyCorrelations({ onFilter }: { onFilter: () => void }) {
+
+
+
+
+
- {selectedHistogram && (
-
- ,
- allTransactions: (
-
-
-
- ),
- focusTransaction: (
-
- {selectedHistogram?.fieldName}:{selectedHistogram?.fieldValue}
-
- ),
- }}
- />
-
- )}
-
{
- const euiTheme = useTheme();
- return {
- ALL_TRANSACTIONS: euiTheme.eui.euiColorVis1,
- ALL_FAILED_TRANSACTIONS: euiTheme.eui.euiColorVis7,
- FOCUS_TRANSACTION: euiTheme.eui.euiColorVis2,
- };
-};
diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.tsx
index e6c189ed0c74e..a2f6fd493313f 100644
--- a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.tsx
@@ -18,18 +18,15 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n-react';
import { useUiTracker } from '../../../../../../observability/public';
import { getDurationFormatter } from '../../../../../common/utils/formatters';
-import { DEFAULT_PERCENTILE_THRESHOLD } from '../../../../../common/correlations/constants';
import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params';
import { FETCH_STATUS } from '../../../../hooks/use_fetcher';
import { TransactionDistributionChart } from '../../../shared/charts/transaction_distribution_chart';
-import { useTransactionColors } from '../../correlations/use_transaction_colors';
import type { TabContentProps } from '../types';
import { useWaterfallFetcher } from '../use_waterfall_fetcher';
@@ -37,10 +34,11 @@ import { WaterfallWithSummary } from '../waterfall_with_summary';
import { useTransactionDistributionChartData } from './use_transaction_distribution_chart_data';
import { HeightRetainer } from '../../../shared/HeightRetainer';
+import { ChartTitleToolTip } from '../../correlations/chart_title_tool_tip';
// Enforce min height so it's consistent across all tabs on the same level
// to prevent "flickering" behavior
-const MIN_TAB_TITLE_HEIGHT = 56;
+export const MIN_TAB_TITLE_HEIGHT = 56;
type Selection = [number, number];
@@ -69,7 +67,6 @@ export function TransactionDistribution({
selection,
traceSamples,
}: TransactionDistributionProps) {
- const transactionColors = useTransactionColors();
const { urlParams } = useLegacyUrlParams();
const { waterfall, status: waterfallStatus } = useWaterfallFetcher();
@@ -108,8 +105,12 @@ export function TransactionDistribution({
return (
-
-
+
+
{i18n.translate(
@@ -121,93 +122,65 @@ export function TransactionDistribution({
- {hasData && !selection && (
-
-
-
-
-
-
- {emptySelectionText}
+
+
+
+
+
+
+
+ {selection ? (
+
+
+ {i18n.translate(
+ 'xpack.apm.transactionDetails.distribution.selectionText',
+ {
+ defaultMessage: `Selection: {formattedSelection}`,
+ values: {
+ formattedSelection: getFormattedSelection(selection),
+ },
+ }
+ )}
+
-
-
- )}
- {hasData && selection && (
-
-
- {i18n.translate(
- 'xpack.apm.transactionDetails.distribution.selectionText',
- {
- defaultMessage: `Selection: {formattedSelection}`,
- values: {
- formattedSelection: getFormattedSelection(selection),
- },
- }
- )}
-
-
- )}
+ ) : (
+ <>
+
+
+
+
+ {emptySelectionText}
+
+ >
+ )}
+
+
-
-
-
-
- ),
- failedTransactions: (
-
-
-
- ),
- }}
- />
-
-
diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/use_transaction_distribution_chart_data.ts b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/use_transaction_distribution_chart_data.ts
index a02fc7fe6665f..6d690415d8c6c 100644
--- a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/use_transaction_distribution_chart_data.ts
+++ b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/use_transaction_distribution_chart_data.ts
@@ -6,23 +6,20 @@
*/
import { useEffect } from 'react';
-
import { i18n } from '@kbn/i18n';
-
import { DEFAULT_PERCENTILE_THRESHOLD } from '../../../../../common/correlations/constants';
import { EVENT_OUTCOME } from '../../../../../common/elasticsearch_fieldnames';
import { EventOutcome } from '../../../../../common/event_outcome';
-
import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context';
import { useFetcher, FETCH_STATUS } from '../../../../hooks/use_fetcher';
-
-import type { TransactionDistributionChartData } from '../../../shared/charts/transaction_distribution_chart';
-
import { isErrorMessage } from '../../correlations/utils/is_error_message';
import { useFetchParams } from '../../correlations/use_fetch_params';
+import { getTransactionDistributionChartData } from '../../correlations/get_transaction_distribution_chart_data';
+import { useTheme } from '../../../../hooks/use_theme';
export const useTransactionDistributionChartData = () => {
const params = useFetchParams();
+ const euiTheme = useTheme();
const {
core: { notifications },
@@ -122,28 +119,11 @@ export const useTransactionDistributionChartData = () => {
}
}, [errorHistogramError, notifications.toasts]);
- const transactionDistributionChartData: TransactionDistributionChartData[] =
- [];
-
- if (Array.isArray(overallLatencyHistogram)) {
- transactionDistributionChartData.push({
- id: i18n.translate(
- 'xpack.apm.transactionDistribution.chart.allTransactionsLabel',
- { defaultMessage: 'All transactions' }
- ),
- histogram: overallLatencyHistogram,
- });
- }
-
- if (Array.isArray(errorHistogramData.overallHistogram)) {
- transactionDistributionChartData.push({
- id: i18n.translate(
- 'xpack.apm.transactionDistribution.chart.failedTransactionsLabel',
- { defaultMessage: 'Failed transactions' }
- ),
- histogram: errorHistogramData.overallHistogram,
- });
- }
+ const transactionDistributionChartData = getTransactionDistributionChartData({
+ euiTheme,
+ allTransactionsHistogram: overallLatencyHistogram,
+ failedTransactionsHistogram: errorHistogramData.overallHistogram,
+ });
return {
chartData: transactionDistributionChartData,
diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_distribution_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/transaction_distribution_chart/index.tsx
index d5cd423b2b123..b33f152a63016 100644
--- a/x-pack/plugins/apm/public/components/shared/charts/transaction_distribution_chart/index.tsx
+++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_distribution_chart/index.tsx
@@ -33,6 +33,7 @@ import { useChartTheme } from '../../../../../../observability/public';
import { getDurationFormatter } from '../../../../../common/utils/formatters';
import type { HistogramItem } from '../../../../../common/correlations/types';
+import { DEFAULT_PERCENTILE_THRESHOLD } from '../../../../../common/correlations/constants';
import { FETCH_STATUS } from '../../../../hooks/use_fetcher';
import { useTheme } from '../../../../hooks/use_theme';
@@ -42,6 +43,7 @@ import { ChartContainer } from '../chart_container';
export interface TransactionDistributionChartData {
id: string;
histogram: HistogramItem[];
+ areaSeriesColor: string;
}
interface TransactionDistributionChartProps {
@@ -49,9 +51,7 @@ interface TransactionDistributionChartProps {
hasData: boolean;
markerCurrentTransaction?: number;
markerValue: number;
- markerPercentile: number;
onChartSelection?: BrushEndListener;
- palette?: string[];
selection?: [number, number];
status: FETCH_STATUS;
}
@@ -98,19 +98,13 @@ export function TransactionDistributionChart({
hasData,
markerCurrentTransaction,
markerValue,
- markerPercentile,
onChartSelection,
- palette,
selection,
status,
}: TransactionDistributionChartProps) {
const chartTheme = useChartTheme();
const euiTheme = useTheme();
-
- const areaSeriesColors = palette ?? [
- euiTheme.eui.euiColorVis1,
- euiTheme.eui.euiColorVis2,
- ];
+ const markerPercentile = DEFAULT_PERCENTILE_THRESHOLD;
const annotationsDataValues: LineAnnotationDatum[] = [
{
@@ -265,7 +259,7 @@ export function TransactionDistributionChart({
curve={CurveType.CURVE_STEP_AFTER}
xAccessor="key"
yAccessors={['doc_count']}
- color={areaSeriesColors[i]}
+ color={d.areaSeriesColor}
fit="lookahead"
// To make the area appear without the orphaned points technique,
// we changed the original data to replace values of 0 with 0.0001.
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 9fc49535e18ef..6d54be0664e0d 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -6233,13 +6233,9 @@
"xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsBetaDescription": "失敗したトランザクションの相関関係はGAではありません。不具合が発生したら報告してください。",
"xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsBetaLabel": "ベータ",
"xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsBetaTitle": "失敗したトランザクションの相関関係",
- "xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsChartAllTransactions": "すべてのトランザクション",
"xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsLabel": "失敗したトランザクションの相関関係",
- "xpack.apm.transactionDetails.tabs.latencyCorrelationsChartAllTransactions": "すべてのトランザクション",
- "xpack.apm.transactionDetails.tabs.latencyCorrelationsChartDescription": "{allTransactions}と{focusTransaction}の{br}重複する帯を使用した遅延(x)とトランザクション(y)の両対数プロット。",
"xpack.apm.transactionDetails.tabs.latencyLabel": "遅延の相関関係",
"xpack.apm.transactionDetails.tabs.traceSamplesLabel": "トレースのサンプル",
- "xpack.apm.transactionDetails.tabs.transactionDistributionChartAllTransactions": "すべてのトランザクション",
"xpack.apm.transactionDetails.traceNotFound": "選択されたトレースが見つかりません",
"xpack.apm.transactionDetails.traceSampleTitle": "トレースのサンプル",
"xpack.apm.transactionDetails.transactionLabel": "トランザクション",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 102051ac2a9df..f04696d7dbe3f 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -6276,13 +6276,9 @@
"xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsBetaDescription": "失败事务相关性不是 GA 版。请通过报告错误来帮助我们。",
"xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsBetaLabel": "公测版",
"xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsBetaTitle": "失败事务相关性",
- "xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsChartAllTransactions": "所有事务",
"xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsLabel": "失败事务相关性",
- "xpack.apm.transactionDetails.tabs.latencyCorrelationsChartAllTransactions": "所有事务",
- "xpack.apm.transactionDetails.tabs.latencyCorrelationsChartDescription": "{allTransactions}和{focusTransaction}{br}带重叠的延迟 (x) 与事务 (y) 双对数坐标图。",
"xpack.apm.transactionDetails.tabs.latencyLabel": "延迟相关性",
"xpack.apm.transactionDetails.tabs.traceSamplesLabel": "跟踪样例",
- "xpack.apm.transactionDetails.tabs.transactionDistributionChartAllTransactions": "所有事务",
"xpack.apm.transactionDetails.traceNotFound": "找不到所选跟踪",
"xpack.apm.transactionDetails.traceSampleTitle": "跟踪样例",
"xpack.apm.transactionDetails.transactionLabel": "事务",
From d9ee4d7ee37a7b0eececdef68045028d07084efe Mon Sep 17 00:00:00 2001
From: Alexey Antonov
Date: Mon, 29 Nov 2021 18:15:49 +0300
Subject: [PATCH 15/47] Update vega related modules (main) (#119663)
* Update vega related modules (main)
* update types
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
package.json | 8 +-
.../public/vega_inspector/vega_adapter.ts | 38 ++-
yarn.lock | 243 +++++++++---------
3 files changed, 159 insertions(+), 130 deletions(-)
diff --git a/package.json b/package.json
index 983dddda5d4fb..5e8a77f2c55f4 100644
--- a/package.json
+++ b/package.json
@@ -397,12 +397,12 @@
"usng.js": "^0.4.5",
"utility-types": "^3.10.0",
"uuid": "3.3.2",
- "vega": "^5.19.1",
+ "vega": "^5.21.0",
"vega-interpreter": "^1.0.4",
- "vega-lite": "^5.0.0",
- "vega-schema-url-parser": "^2.1.0",
+ "vega-lite": "^5.2.0",
+ "vega-schema-url-parser": "^2.2.0",
"vega-spec-injector": "^0.0.2",
- "vega-tooltip": "^0.25.1",
+ "vega-tooltip": "^0.27.0",
"venn.js": "0.2.20",
"vinyl": "^2.2.0",
"vt-pbf": "^3.1.1",
diff --git a/src/plugins/vis_types/vega/public/vega_inspector/vega_adapter.ts b/src/plugins/vis_types/vega/public/vega_inspector/vega_adapter.ts
index bc90fe35199b8..def7fefd55173 100644
--- a/src/plugins/vis_types/vega/public/vega_inspector/vega_adapter.ts
+++ b/src/plugins/vis_types/vega/public/vega_inspector/vega_adapter.ts
@@ -6,14 +6,35 @@
* Side Public License, v 1.
*/
+import { i18n } from '@kbn/i18n';
+
import { Observable, ReplaySubject, fromEventPattern, merge, timer } from 'rxjs';
import { map, switchMap, filter, debounce } from 'rxjs/operators';
-import { View, Runtime, Spec } from 'vega';
-import { i18n } from '@kbn/i18n';
-import { Assign } from '@kbn/utility-types';
+import type { View, Spec } from 'vega';
+import type { Assign } from '@kbn/utility-types';
interface DebugValues {
- view: View;
+ view: Assign<
+ {
+ _runtime: {
+ data: Record<
+ string,
+ {
+ values: {
+ value: Array>;
+ };
+ }
+ >;
+ signals: Record<
+ string,
+ {
+ value: unknown;
+ }
+ >;
+ };
+ },
+ View
+ >;
spec: Spec;
}
@@ -38,8 +59,11 @@ const vegaAdapterValueLabel = i18n.translate('visTypeVega.inspector.vegaAdapter.
/** Get Runtime Scope for Vega View
* @link https://vega.github.io/vega/docs/api/debugging/#scope
**/
-const getVegaRuntimeScope = (debugValues: DebugValues) =>
- (debugValues.view as any)._runtime as Runtime;
+const getVegaRuntimeScope = (debugValues: DebugValues) => {
+ const { data, signals } = debugValues.view._runtime ?? {};
+
+ return { data, signals };
+};
const serializeColumns = (item: Record, columns: string[]) => {
const nonSerializableFieldLabel = '(..)';
@@ -69,7 +93,7 @@ export class VegaAdapter {
const runtimeScope = getVegaRuntimeScope(debugValues);
return Object.keys(runtimeScope.data || []).reduce((acc: InspectDataSets[], key) => {
- const value = runtimeScope.data[key].values.value;
+ const { value } = runtimeScope.data[key].values;
if (value && value[0]) {
const columns = Object.keys(value[0]);
diff --git a/yarn.lock b/yarn.lock
index 44185306ca38f..821b788bc7c8f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5259,10 +5259,10 @@
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.9.tgz#d868b6febb02666330410fe7f58f3c4b8258be7b"
integrity sha512-MNl+rT5UmZeilaPxAVs6YaPC2m6aA8rofviZbhbxpPpl61uKodfdQVsBtgJGTqGizEf02oW3tsVe7FYB8kK14A==
-"@types/clone@~2.1.0":
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/@types/clone/-/clone-2.1.0.tgz#cb888a3fe5319275b566ae3a9bc606e310c533d4"
- integrity sha512-d/aS/lPOnUSruPhgNtT8jW39fHRVTLQy9sodysP1kkG8EdAtdZu1vt8NJaYA8w/6Z9j8izkAsx1A/yJhcYR1CA==
+"@types/clone@~2.1.1":
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/@types/clone/-/clone-2.1.1.tgz#9b880d0ce9b1f209b5e0bd6d9caa38209db34024"
+ integrity sha512-BZIU34bSYye0j/BFcPraiDZ5ka6MJADjcDVELGf7glr9K+iE8NYVjFslJFVWzskSxkLLyCrSPScE82/UUoBSvg==
"@types/cmd-shim@^2.0.0":
version "2.0.0"
@@ -5424,7 +5424,7 @@
"@types/estree" "*"
"@types/json-schema" "*"
-"@types/estree@*":
+"@types/estree@*", "@types/estree@^0.0.50":
version "0.0.50"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83"
integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==
@@ -5468,11 +5468,6 @@
resolved "https://registry.yarnpkg.com/@types/fancy-log/-/fancy-log-1.3.1.tgz#dd94fbc8c2e2ab8ab402ca8d04bb8c34965f0696"
integrity sha512-31Dt9JaGfHretvwVxCBrCFL5iC9MQ3zOXpu+8C4qzW0cxc5rJJVGxB5c/vZ+wmeTk/JjPz/D0gv8BZ+Ip6iCqQ==
-"@types/fast-json-stable-stringify@^2.0.0":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#40363bb847cb86b2c2e1599f1398d11e8329c921"
- integrity sha512-mky/O83TXmGY39P1H9YbUpjV6l6voRYlufqfFCvel8l1phuy8HRjdWc1rrPuN53ITBJlbyMSV6z3niOySO5pgQ==
-
"@types/fetch-mock@^7.3.1":
version "7.3.1"
resolved "https://registry.yarnpkg.com/@types/fetch-mock/-/fetch-mock-7.3.1.tgz#df7421e8bcb351b430bfbfa5c52bb353826ac94f"
@@ -27558,16 +27553,11 @@ tslib@^2.0.0, tslib@^2.0.1, tslib@^2.2.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c"
integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==
-tslib@^2.3.0:
+tslib@^2.3.0, tslib@~2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
-tslib@~2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a"
- integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==
-
tsutils@2.27.2:
version "2.27.2"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.27.2.tgz#60ba88a23d6f785ec4b89c6e8179cac9b431f1c7"
@@ -28574,14 +28564,14 @@ vega-crossfilter@~4.0.5:
vega-dataflow "^5.7.3"
vega-util "^1.15.2"
-vega-dataflow@^5.7.3, vega-dataflow@~5.7.3:
- version "5.7.3"
- resolved "https://registry.yarnpkg.com/vega-dataflow/-/vega-dataflow-5.7.3.tgz#66ca06a61f72a210b0732e3b6cc1eec5117197f7"
- integrity sha512-2ipzKgQUmbSXcQBH+9XF0BYbXyZrHvjlbJ8ifyRWYQk78w8kMvE6wy/rcdXYK6iVZ6aAbEDDT7jTI+rFt3tGLA==
+vega-dataflow@^5.7.3, vega-dataflow@^5.7.4, vega-dataflow@~5.7.4:
+ version "5.7.4"
+ resolved "https://registry.yarnpkg.com/vega-dataflow/-/vega-dataflow-5.7.4.tgz#7cafc0a41b9d0b11dd2e34a513f8b7ca345dfd74"
+ integrity sha512-JGHTpUo8XGETH3b1V892we6hdjzCWB977ybycIu8DPqRoyrZuj6t1fCVImazfMgQD1LAfJlQybWP+alwKDpKig==
dependencies:
vega-format "^1.0.4"
vega-loader "^4.3.2"
- vega-util "^1.15.2"
+ vega-util "^1.16.1"
vega-encode@~4.8.3:
version "4.8.3"
@@ -28594,16 +28584,17 @@ vega-encode@~4.8.3:
vega-scale "^7.0.3"
vega-util "^1.15.2"
-vega-event-selector@^2.0.6, vega-event-selector@~2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/vega-event-selector/-/vega-event-selector-2.0.6.tgz#6beb00e066b78371dde1a0f40cb5e0bbaecfd8bc"
- integrity sha512-UwCu50Sqd8kNZ1X/XgiAY+QAyQUmGFAwyDu7y0T5fs6/TPQnDo/Bo346NgSgINBEhEKOAMY1Nd/rPOk4UEm/ew==
+vega-event-selector@^3.0.0, vega-event-selector@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/vega-event-selector/-/vega-event-selector-3.0.0.tgz#7b855ac0c3ddb59bc5b5caa0d96dbbc9fbd33a4c"
+ integrity sha512-Gls93/+7tEJGE3kUuUnxrBIxtvaNeF01VIFB2Q2Of2hBIBvtHX74jcAdDtkh5UhhoYGD8Q1J30P5cqEBEwtPoQ==
-vega-expression@^4.0.1, vega-expression@~4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/vega-expression/-/vega-expression-4.0.1.tgz#c03e4fc68a00acac49557faa4e4ed6ac8a59c5fd"
- integrity sha512-ZrDj0hP8NmrCpdLFf7Rd/xMUHGoSYsAOTaYp7uXZ2dkEH5x0uPy5laECMc8TiQvL8W+8IrN2HAWCMRthTSRe2Q==
+vega-expression@^5.0.0, vega-expression@~5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/vega-expression/-/vega-expression-5.0.0.tgz#938f26689693a1e0d26716030cdaed43ca7abdfb"
+ integrity sha512-y5+c2frq0tGwJ7vYXzZcfVcIRF/QGfhf2e+bV1Z0iQs+M2lI1II1GPDdmOcMKimpoCVp/D61KUJDIGE1DSmk2w==
dependencies:
+ "@types/estree" "^0.0.50"
vega-util "^1.16.0"
vega-force@~4.0.7:
@@ -28626,19 +28617,19 @@ vega-format@^1.0.4, vega-format@~1.0.4:
vega-time "^2.0.3"
vega-util "^1.15.2"
-vega-functions@^5.10.0, vega-functions@^5.12.0, vega-functions@~5.12.0:
- version "5.12.0"
- resolved "https://registry.yarnpkg.com/vega-functions/-/vega-functions-5.12.0.tgz#44bf08a7b20673dc8cf51d6781c8ea1399501668"
- integrity sha512-3hljmGs+gR7TbO/yYuvAP9P5laKISf1GKk4yRHLNdM61fWgKm8pI3f6LY2Hvq9cHQFTiJ3/5/Bx2p1SX5R4quQ==
+vega-functions@^5.10.0, vega-functions@^5.12.1, vega-functions@~5.12.1:
+ version "5.12.1"
+ resolved "https://registry.yarnpkg.com/vega-functions/-/vega-functions-5.12.1.tgz#b69f9ad4cd9f777dbc942587c02261b2f4cdba2c"
+ integrity sha512-7cHfcjXOj27qEbh2FTzWDl7FJK4xGcMFF7+oiyqa0fp7BU/wNT5YdNV0t5kCX9WjV7mfJWACKV74usLJbyM6GA==
dependencies:
d3-array "^2.7.1"
d3-color "^2.0.0"
d3-geo "^2.0.1"
vega-dataflow "^5.7.3"
- vega-expression "^4.0.1"
+ vega-expression "^5.0.0"
vega-scale "^7.1.1"
vega-scenegraph "^4.9.3"
- vega-selections "^5.3.0"
+ vega-selections "^5.3.1"
vega-statistics "^1.7.9"
vega-time "^2.0.4"
vega-util "^1.16.0"
@@ -28671,38 +28662,37 @@ vega-interpreter@^1.0.4:
resolved "https://registry.yarnpkg.com/vega-interpreter/-/vega-interpreter-1.0.4.tgz#291ebf85bc2d1c3550a3da22ff75b3ba0d326a39"
integrity sha512-6tpYIa/pJz0cZo5fSxDSkZkAA51pID2LjOtQkOQvbzn+sJiCaWKPFhur8MBqbcmYZ9bnap1OYNwlrvpd2qBLvg==
-vega-label@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/vega-label/-/vega-label-1.0.0.tgz#c3bea3a608a62217ca554ecc0f7fe0395d81bd1b"
- integrity sha512-hCdm2pcHgkKgxnzW9GvX5JmYNiUMlOXOibtMmBzvFBQHX3NiV9giQ5nsPiQiFbV08VxEPtM+VYXr2HyrIcq5zQ==
+vega-label@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/vega-label/-/vega-label-1.1.0.tgz#0a11ae3ba18d7aed909c51ec67c2a9dde4426c6f"
+ integrity sha512-LAThIiDEsZxYvbSkvPLJ93eJF+Ts8RXv1IpBh8gmew8XGmaLJvVkzdsMe7WJJwuaVEsK7ZZFyB/Inkp842GW6w==
dependencies:
vega-canvas "^1.2.5"
vega-dataflow "^5.7.3"
vega-scenegraph "^4.9.2"
vega-util "^1.15.2"
-vega-lite@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/vega-lite/-/vega-lite-5.0.0.tgz#93898a910702736da41048f590882b907d78ac65"
- integrity sha512-CrMAy3D2E662qtShrOeGttwwthRxUOZUfdu39THyxkOfLNJBCLkNjfQpFekEidxwbtFTO1zMZzyFIP3AE2I8kQ==
+vega-lite@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/vega-lite/-/vega-lite-5.2.0.tgz#bc3c5c70a38d9de8f3fb9644c7dd52f3b9f47a1b"
+ integrity sha512-Yxcg8MvYfxHcG6BbkaKT0oVCIMIcE19UvqIsEwBmyd/7h2nzW7oRnID81T8UrY7hpDrIr6wa2JADOT2dhGNErw==
dependencies:
- "@types/clone" "~2.1.0"
- "@types/fast-json-stable-stringify" "^2.0.0"
+ "@types/clone" "~2.1.1"
array-flat-polyfill "^1.0.1"
clone "~2.1.2"
fast-deep-equal "~3.1.3"
fast-json-stable-stringify "~2.1.0"
json-stringify-pretty-compact "~3.0.0"
- tslib "~2.1.0"
- vega-event-selector "~2.0.6"
- vega-expression "~4.0.1"
- vega-util "~1.16.0"
- yargs "~16.2.0"
+ tslib "~2.3.1"
+ vega-event-selector "~3.0.0"
+ vega-expression "~5.0.0"
+ vega-util "~1.17.0"
+ yargs "~17.2.1"
-vega-loader@^4.3.2, vega-loader@^4.3.3, vega-loader@~4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/vega-loader/-/vega-loader-4.4.0.tgz#fc515b7368c46b2be8df1fcf3c35c696c13c453d"
- integrity sha512-e5enQECdau7rJob0NFB5pGumh3RaaSWWm90+boxMy3ay2b4Ki/3XIvo+C4F1Lx04qSxvQF7tO2LJcklRm6nqRA==
+vega-loader@^4.3.2, vega-loader@^4.3.3, vega-loader@~4.4.1:
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/vega-loader/-/vega-loader-4.4.1.tgz#8f9de46202f33659d1a2737f6e322a9fc3364275"
+ integrity sha512-dj65i4qlNhK0mOmjuchHgUrF5YUaWrYpx0A8kXA68lBk5Hkx8FNRztkcl07CZJ1+8V81ymEyJii9jzGbhEX0ag==
dependencies:
d3-dsv "^2.0.0"
node-fetch "^2.6.1"
@@ -28710,14 +28700,14 @@ vega-loader@^4.3.2, vega-loader@^4.3.3, vega-loader@~4.4.0:
vega-format "^1.0.4"
vega-util "^1.16.0"
-vega-parser@~6.1.3:
- version "6.1.3"
- resolved "https://registry.yarnpkg.com/vega-parser/-/vega-parser-6.1.3.tgz#df72785e4b086eceb90ee6219a399210933b507b"
- integrity sha512-8oiVhhW26GQ4GZBvolId8FVFvhn3s1KGgPlD7Z+4P2wkV+xe5Nqu0TEJ20F/cn3b88fd0Vj48X3BH3dlSeKNFg==
+vega-parser@~6.1.4:
+ version "6.1.4"
+ resolved "https://registry.yarnpkg.com/vega-parser/-/vega-parser-6.1.4.tgz#4868e41af2c9645b6d7daeeb205cfad06b9d465c"
+ integrity sha512-tORdpWXiH/kkXcpNdbSVEvtaxBuuDtgYp9rBunVW9oLsjFvFXbSWlM1wvJ9ZFSaTfx6CqyTyGMiJemmr1QnTjQ==
dependencies:
vega-dataflow "^5.7.3"
- vega-event-selector "^2.0.6"
- vega-functions "^5.12.0"
+ vega-event-selector "^3.0.0"
+ vega-functions "^5.12.1"
vega-scale "^7.1.1"
vega-util "^1.16.0"
@@ -28758,10 +28748,10 @@ vega-scale@^7.0.3, vega-scale@^7.1.1, vega-scale@~7.1.1:
vega-time "^2.0.4"
vega-util "^1.15.2"
-vega-scenegraph@^4.9.2, vega-scenegraph@^4.9.3, vega-scenegraph@~4.9.3:
- version "4.9.3"
- resolved "https://registry.yarnpkg.com/vega-scenegraph/-/vega-scenegraph-4.9.3.tgz#c4720550ea7ff5c8d9d0690f47fe2640547cfc6b"
- integrity sha512-lBvqLbXqrqRCTGJmSgzZC/tLR/o+TXfakbdhDzNdpgTavTaQ65S/67Gpj5hPpi77DvsfZUIY9lCEeO37aJhy0Q==
+vega-scenegraph@^4.9.2, vega-scenegraph@^4.9.3, vega-scenegraph@^4.9.4, vega-scenegraph@~4.9.4:
+ version "4.9.4"
+ resolved "https://registry.yarnpkg.com/vega-scenegraph/-/vega-scenegraph-4.9.4.tgz#468408c1e89703fa9d3450445daabff623de2757"
+ integrity sha512-QaegQzbFE2yhYLNWAmHwAuguW3yTtQrmwvfxYT8tk0g+KKodrQ5WSmNrphWXhqwtsgVSvtdZkfp2IPeumcOQJg==
dependencies:
d3-path "^2.0.0"
d3-shape "^2.0.0"
@@ -28770,17 +28760,17 @@ vega-scenegraph@^4.9.2, vega-scenegraph@^4.9.3, vega-scenegraph@~4.9.3:
vega-scale "^7.1.1"
vega-util "^1.15.2"
-vega-schema-url-parser@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/vega-schema-url-parser/-/vega-schema-url-parser-2.1.0.tgz#847f9cf9f1624f36f8a51abc1adb41ebc6673cb4"
- integrity sha512-JHT1PfOyVzOohj89uNunLPirs05Nf59isPT5gnwIkJph96rRgTIBJE7l7yLqndd7fLjr3P8JXHGAryRp74sCaQ==
+vega-schema-url-parser@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/vega-schema-url-parser/-/vega-schema-url-parser-2.2.0.tgz#a0d1e02915adfbfcb1fd517c8c2ebe2419985c1e"
+ integrity sha512-yAtdBnfYOhECv9YC70H2gEiqfIbVkq09aaE4y/9V/ovEFmH9gPKaEgzIZqgT7PSPQjKhsNkb6jk6XvSoboxOBw==
-vega-selections@^5.3.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/vega-selections/-/vega-selections-5.3.0.tgz#810f2e7b7642fa836cf98b2e5dcc151093b1f6a7"
- integrity sha512-vC4NPsuN+IffruFXfH0L3i2A51RgG4PqpLv85TvrEAIYnSkyKDE4bf+wVraR3aPdnLLkc3+tYuMi6le5FmThIA==
+vega-selections@^5.3.1:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/vega-selections/-/vega-selections-5.3.1.tgz#af5c3cc6532a55a5b692eb0fcc2a1d8d521605a4"
+ integrity sha512-cm4Srw1WHjcLGXX7GpxiUlfESv8XPu5b6Vh3mqMDPU94P2FO91SR9gei+EtRdt+KCFgIjr//MnRUjg/hAWwjkQ==
dependencies:
- vega-expression "^4.0.1"
+ vega-expression "^5.0.0"
vega-util "^1.16.0"
vega-spec-injector@^0.0.2:
@@ -28788,10 +28778,10 @@ vega-spec-injector@^0.0.2:
resolved "https://registry.yarnpkg.com/vega-spec-injector/-/vega-spec-injector-0.0.2.tgz#f1d990109dd9d845c524738f818baa4b72a60ca6"
integrity sha512-wOMMqmpssn0/ZFPW7wl1v26vbseRX7zHPWzEyS9TwNXTRCu1TcjIBIR+X23lCWocxhoBqFxmqyn8UowMhlGtAg==
-vega-statistics@^1.7.9, vega-statistics@~1.7.9:
- version "1.7.9"
- resolved "https://registry.yarnpkg.com/vega-statistics/-/vega-statistics-1.7.9.tgz#feec01d463e1b50593d890d20631f72138fcb65d"
- integrity sha512-T0sd2Z08k/mHxr1Vb4ajLWytPluLFYnsYqyk4SIS5czzUs4errpP2gUu63QJ0B7CKNu33vnS9WdOMOo/Eprr/Q==
+vega-statistics@^1.7.9, vega-statistics@~1.7.10:
+ version "1.7.10"
+ resolved "https://registry.yarnpkg.com/vega-statistics/-/vega-statistics-1.7.10.tgz#4353637402e5e96bff2ebd16bd58e2c15cac3018"
+ integrity sha512-QLb12gcfpDZ9K5h3TLGrlz4UXDH9wSPyg9LLfOJZacxvvJEPohacUQNrGEAVtFO9ccUCerRfH9cs25ZtHsOZrw==
dependencies:
d3-array "^2.7.1"
@@ -28804,35 +28794,37 @@ vega-time@^2.0.3, vega-time@^2.0.4, vega-time@~2.0.4:
d3-time "^2.0.0"
vega-util "^1.15.2"
-vega-tooltip@^0.25.1:
- version "0.25.1"
- resolved "https://registry.yarnpkg.com/vega-tooltip/-/vega-tooltip-0.25.1.tgz#cb7e438438649eb46896e7bee6f54e25d25b3c09"
- integrity sha512-ugGwGi2/p3OpB8N15xieuzP8DyV5DreqMWcmJ9zpWT8GlkyKtef4dGRXnvHeHQ+iJFmWrq4oZJ+kLTrdiECjAg==
+vega-tooltip@^0.27.0:
+ version "0.27.0"
+ resolved "https://registry.yarnpkg.com/vega-tooltip/-/vega-tooltip-0.27.0.tgz#e03c150cdec78f68938a0dab5ef67a24e6d685da"
+ integrity sha512-FRcHNfMNo9D/7an5nZuP6JC2JGEsc85qcGjyMU7VlPpjQj9eBj1P+sZSNbb54Z20g7inVSBRyd8qgNn5EYTxJA==
dependencies:
vega-util "^1.16.0"
-vega-transforms@~4.9.3:
- version "4.9.3"
- resolved "https://registry.yarnpkg.com/vega-transforms/-/vega-transforms-4.9.3.tgz#40e5234b956a68eaa03eedf489ed03293075bbfb"
- integrity sha512-PdqQd5oPlRyD405M2w+Sz9Bo+i7Rwi8o03SVK7RaeQsJC2FffKGJ6acIaSEgOq+yD1Q2k/1SePmCXcmLUlIiEA==
+vega-transforms@~4.9.4:
+ version "4.9.4"
+ resolved "https://registry.yarnpkg.com/vega-transforms/-/vega-transforms-4.9.4.tgz#5cf6b91bda9f184bbbaba63838be8e5e6a571235"
+ integrity sha512-JGBhm5Bf6fiGTUSB5Qr5ckw/KU9FJcSV5xIe/y4IobM/i/KNwI1i1fP45LzP4F4yZc0DMTwJod2UvFHGk9plKA==
dependencies:
d3-array "^2.7.1"
- vega-dataflow "^5.7.3"
+ vega-dataflow "^5.7.4"
vega-statistics "^1.7.9"
vega-time "^2.0.4"
- vega-util "^1.15.2"
+ vega-util "^1.16.1"
-vega-typings@~0.19.2:
- version "0.19.2"
- resolved "https://registry.yarnpkg.com/vega-typings/-/vega-typings-0.19.2.tgz#374fc1020c1abb263a0be87de28d1a4bd0526c3f"
- integrity sha512-YU/S9rDk4d+t4+4eTa9fzuw87PMNteeVtpcL51kUO8H7HvGaoW7ll8RHKLkR0NYBEGPRoFDKUxnoyMvhgjsdYw==
+vega-typings@~0.22.0:
+ version "0.22.1"
+ resolved "https://registry.yarnpkg.com/vega-typings/-/vega-typings-0.22.1.tgz#287c646cfa93b1822d0fb6ea11d5543632f8b56e"
+ integrity sha512-88cIrjmoTxo/0nWTf+GuitkFhirHWVWCfymADiCUXt6s9arpQ6XPP5xjrN5KDc0LZd9xr7p4FIiEgADghgLTgw==
dependencies:
+ vega-event-selector "^3.0.0"
+ vega-expression "^5.0.0"
vega-util "^1.15.2"
-vega-util@^1.15.2, vega-util@^1.16.0, vega-util@~1.16.0:
- version "1.16.0"
- resolved "https://registry.yarnpkg.com/vega-util/-/vega-util-1.16.0.tgz#77405d8df0a94944d106bdc36015f0d43aa2caa3"
- integrity sha512-6mmz6mI+oU4zDMeKjgvE2Fjz0Oh6zo6WGATcvCfxH2gXBzhBHmy5d25uW5Zjnkc6QBXSWPLV9Xa6SiqMsrsKog==
+vega-util@^1.15.2, vega-util@^1.16.0, vega-util@^1.16.1, vega-util@~1.17.0:
+ version "1.17.0"
+ resolved "https://registry.yarnpkg.com/vega-util/-/vega-util-1.17.0.tgz#b72ae0baa97f943bf591f8f5bb27ceadf06834ac"
+ integrity sha512-HTaydZd9De3yf+8jH66zL4dXJ1d1p5OIFyoBzFiOli4IJbwkL1jrefCKz6AHDm1kYBzDJ0X4bN+CzZSCTvNk1w==
vega-view-transforms@~4.5.8:
version "4.5.8"
@@ -28843,10 +28835,10 @@ vega-view-transforms@~4.5.8:
vega-scenegraph "^4.9.2"
vega-util "^1.15.2"
-vega-view@~5.9.2:
- version "5.9.2"
- resolved "https://registry.yarnpkg.com/vega-view/-/vega-view-5.9.2.tgz#cb957e481a952abbe7b3a11aa2d58cc728f295e7"
- integrity sha512-XAwKWyVjLClR3aCbTLCWdZj7aZozOULNg7078GxJIgVcBJOENCAidceI/H7JieyUZ96p3AiEHLQdWr167InBpg==
+vega-view@~5.10.1:
+ version "5.10.1"
+ resolved "https://registry.yarnpkg.com/vega-view/-/vega-view-5.10.1.tgz#b69348bb32a9845a1bd341fdd946df98684fadc3"
+ integrity sha512-4xvQ5KZcgKdZx1Z7jjenCUumvlyr/j4XcHLRf9gyeFrFvvS596dVpL92V8twhV6O++DmS2+fj+rHagO8Di4nMg==
dependencies:
d3-array "^2.7.1"
d3-timer "^2.0.0"
@@ -28854,8 +28846,8 @@ vega-view@~5.9.2:
vega-format "^1.0.4"
vega-functions "^5.10.0"
vega-runtime "^6.1.3"
- vega-scenegraph "^4.9.2"
- vega-util "^1.15.2"
+ vega-scenegraph "^4.9.4"
+ vega-util "^1.16.1"
vega-voronoi@~4.1.5:
version "4.1.5"
@@ -28877,35 +28869,35 @@ vega-wordcloud@~4.1.3:
vega-statistics "^1.7.9"
vega-util "^1.15.2"
-vega@^5.19.1:
- version "5.19.1"
- resolved "https://registry.yarnpkg.com/vega/-/vega-5.19.1.tgz#64c8350740fe1a11d56cc6617ab3a76811fd704c"
- integrity sha512-UE6/c9q9kzuz4HULFuU9HscBASoZa+zcXqGKdbQP545Nwmhd078QpcH+wZsq9lYfiTxmFtzLK/a0OH0zhkghvA==
+vega@^5.21.0:
+ version "5.21.0"
+ resolved "https://registry.yarnpkg.com/vega/-/vega-5.21.0.tgz#f3d858d7544bfe4ffa3d8cd43d9ea978bf7391e8"
+ integrity sha512-yqqRa9nAqYoAxe7sVhRpsh0b001fly7Yx05klPkXmrvzjxXd07gClW1mOuGgSnVQqo7jTp/LYgbO1bD37FbEig==
dependencies:
vega-crossfilter "~4.0.5"
- vega-dataflow "~5.7.3"
+ vega-dataflow "~5.7.4"
vega-encode "~4.8.3"
- vega-event-selector "~2.0.6"
- vega-expression "~4.0.1"
+ vega-event-selector "~3.0.0"
+ vega-expression "~5.0.0"
vega-force "~4.0.7"
vega-format "~1.0.4"
- vega-functions "~5.12.0"
+ vega-functions "~5.12.1"
vega-geo "~4.3.8"
vega-hierarchy "~4.0.9"
- vega-label "~1.0.0"
- vega-loader "~4.4.0"
- vega-parser "~6.1.3"
+ vega-label "~1.1.0"
+ vega-loader "~4.4.1"
+ vega-parser "~6.1.4"
vega-projection "~1.4.5"
vega-regression "~1.0.9"
vega-runtime "~6.1.3"
vega-scale "~7.1.1"
- vega-scenegraph "~4.9.3"
- vega-statistics "~1.7.9"
+ vega-scenegraph "~4.9.4"
+ vega-statistics "~1.7.10"
vega-time "~2.0.4"
- vega-transforms "~4.9.3"
- vega-typings "~0.19.2"
- vega-util "~1.16.0"
- vega-view "~5.9.2"
+ vega-transforms "~4.9.4"
+ vega-typings "~0.22.0"
+ vega-util "~1.17.0"
+ vega-view "~5.10.1"
vega-view-transforms "~4.5.8"
vega-voronoi "~4.1.5"
vega-wordcloud "~4.1.3"
@@ -29881,7 +29873,7 @@ yargs@^15.0.2, yargs@^15.3.1, yargs@^15.4.1:
y18n "^4.0.0"
yargs-parser "^18.1.2"
-yargs@^16.2.0, yargs@~16.2.0:
+yargs@^16.2.0:
version "16.2.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
@@ -29939,6 +29931,19 @@ yargs@^7.1.0:
y18n "^3.2.1"
yargs-parser "5.0.0-security.0"
+yargs@~17.2.1:
+ version "17.2.1"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.2.1.tgz#e2c95b9796a0e1f7f3bf4427863b42e0418191ea"
+ integrity sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==
+ dependencies:
+ cliui "^7.0.2"
+ escalade "^3.1.1"
+ get-caller-file "^2.0.5"
+ require-directory "^2.1.1"
+ string-width "^4.2.0"
+ y18n "^5.0.5"
+ yargs-parser "^20.2.2"
+
yargs@~3.10.0:
version "3.10.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
From 2c4196270abc540f841ab5492061d29fb5184ad5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ester=20Mart=C3=AD=20Vilaseca?=
Date: Mon, 29 Nov 2021 17:06:25 +0100
Subject: [PATCH 16/47] [Unified Observability] Add feature flag for the new
overview page (#119193)
* Add feature flag to display a blank overview page when enabled
* Add tests for overview page feature flag
* Fix types
* Fix more types
* Remove duplicated BucketSize type
* fix linter
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../public/application/application.test.tsx | 8 +-
.../components/app/section/apm/index.test.tsx | 8 +-
.../components/app/section/ux/index.test.tsx | 8 +-
.../public/hooks/use_time_range.test.ts | 16 ++-
x-pack/plugins/observability/public/index.ts | 6 +-
.../public/pages/overview/index.test.tsx | 51 +++++++
.../public/pages/overview/index.tsx | 131 ++---------------
.../pages/overview/old_overview_page.tsx | 136 ++++++++++++++++++
.../pages/overview/overview.stories.tsx | 6 +-
.../public/pages/overview/overview_page.tsx | 82 +++++++++++
.../public/utils/test_helper.tsx | 8 +-
x-pack/plugins/observability/server/index.ts | 1 +
12 files changed, 333 insertions(+), 128 deletions(-)
create mode 100644 x-pack/plugins/observability/public/pages/overview/index.test.tsx
create mode 100644 x-pack/plugins/observability/public/pages/overview/old_overview_page.tsx
create mode 100644 x-pack/plugins/observability/public/pages/overview/overview_page.tsx
diff --git a/x-pack/plugins/observability/public/application/application.test.tsx b/x-pack/plugins/observability/public/application/application.test.tsx
index 6b5863c8b122a..dddc44c3c26ea 100644
--- a/x-pack/plugins/observability/public/application/application.test.tsx
+++ b/x-pack/plugins/observability/public/application/application.test.tsx
@@ -46,7 +46,13 @@ describe('renderApp', () => {
uiSettings: { get: () => false },
http: { basePath: { prepend: (path: string) => path } },
} as unknown as CoreStart;
- const config = { unsafe: { alertingExperience: { enabled: true }, cases: { enabled: true } } };
+ const config = {
+ unsafe: {
+ alertingExperience: { enabled: true },
+ cases: { enabled: true },
+ overviewNext: { enabled: false },
+ },
+ };
const params = {
element: window.document.createElement('div'),
history: createMemoryHistory(),
diff --git a/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx b/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx
index c9c2ed549a1c3..35835cd0bc8e6 100644
--- a/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx
+++ b/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx
@@ -42,7 +42,13 @@ describe('APMSection', () => {
http: { basePath: { prepend: jest.fn() } },
} as unknown as CoreStart,
appMountParameters: {} as AppMountParameters,
- config: { unsafe: { alertingExperience: { enabled: true }, cases: { enabled: true } } },
+ config: {
+ unsafe: {
+ alertingExperience: { enabled: true },
+ cases: { enabled: true },
+ overviewNext: { enabled: false },
+ },
+ },
observabilityRuleTypeRegistry: createObservabilityRuleTypeRegistryMock(),
plugins: {
data: {
diff --git a/x-pack/plugins/observability/public/components/app/section/ux/index.test.tsx b/x-pack/plugins/observability/public/components/app/section/ux/index.test.tsx
index 8a99b6a53cf06..b4dda3ed3559e 100644
--- a/x-pack/plugins/observability/public/components/app/section/ux/index.test.tsx
+++ b/x-pack/plugins/observability/public/components/app/section/ux/index.test.tsx
@@ -42,7 +42,13 @@ describe('UXSection', () => {
http: { basePath: { prepend: jest.fn() } },
} as unknown as CoreStart,
appMountParameters: {} as AppMountParameters,
- config: { unsafe: { alertingExperience: { enabled: true }, cases: { enabled: true } } },
+ config: {
+ unsafe: {
+ alertingExperience: { enabled: true },
+ cases: { enabled: true },
+ overviewNext: { enabled: false },
+ },
+ },
plugins: {
data: {
query: {
diff --git a/x-pack/plugins/observability/public/hooks/use_time_range.test.ts b/x-pack/plugins/observability/public/hooks/use_time_range.test.ts
index bf513d8a1a99a..bbf3096e55107 100644
--- a/x-pack/plugins/observability/public/hooks/use_time_range.test.ts
+++ b/x-pack/plugins/observability/public/hooks/use_time_range.test.ts
@@ -24,7 +24,13 @@ describe('useTimeRange', () => {
jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({
core: {} as CoreStart,
appMountParameters: {} as AppMountParameters,
- config: { unsafe: { alertingExperience: { enabled: true }, cases: { enabled: true } } },
+ config: {
+ unsafe: {
+ alertingExperience: { enabled: true },
+ cases: { enabled: true },
+ overviewNext: { enabled: false },
+ },
+ },
plugins: {
data: {
query: {
@@ -67,7 +73,13 @@ describe('useTimeRange', () => {
jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({
core: {} as CoreStart,
appMountParameters: {} as AppMountParameters,
- config: { unsafe: { alertingExperience: { enabled: true }, cases: { enabled: true } } },
+ config: {
+ unsafe: {
+ alertingExperience: { enabled: true },
+ cases: { enabled: true },
+ overviewNext: { enabled: false },
+ },
+ },
plugins: {
data: {
query: {
diff --git a/x-pack/plugins/observability/public/index.ts b/x-pack/plugins/observability/public/index.ts
index 0dab3e5135717..7646ac9bec9bb 100644
--- a/x-pack/plugins/observability/public/index.ts
+++ b/x-pack/plugins/observability/public/index.ts
@@ -26,7 +26,11 @@ export type {
export { enableInspectEsQueries } from '../common/ui_settings_keys';
export interface ConfigSchema {
- unsafe: { alertingExperience: { enabled: boolean }; cases: { enabled: boolean } };
+ unsafe: {
+ alertingExperience: { enabled: boolean };
+ cases: { enabled: boolean };
+ overviewNext: { enabled: boolean };
+ };
}
export const plugin: PluginInitializer<
diff --git a/x-pack/plugins/observability/public/pages/overview/index.test.tsx b/x-pack/plugins/observability/public/pages/overview/index.test.tsx
new file mode 100644
index 0000000000000..b37ed1d873ba7
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/overview/index.test.tsx
@@ -0,0 +1,51 @@
+/*
+ * 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 React from 'react';
+import { shallow } from 'enzyme';
+import * as PluginContext from '../../hooks/use_plugin_context';
+import { PluginContextValue } from '../../context/plugin_context';
+import { OverviewPage } from './';
+import { OverviewPage as OldOverviewPage } from './old_overview_page';
+import { OverviewPage as NewOverviewPage } from './overview_page';
+
+describe('Overview page', () => {
+ it('should render the old overview page when feature flag is disabled', () => {
+ const pluginContext = {
+ config: {
+ unsafe: {
+ overviewNext: { enabled: false },
+ },
+ },
+ };
+
+ jest
+ .spyOn(PluginContext, 'usePluginContext')
+ .mockReturnValue(pluginContext as PluginContextValue);
+
+ const component = shallow();
+ expect(component.find(OldOverviewPage)).toHaveLength(1);
+ expect(component.find(NewOverviewPage)).toHaveLength(0);
+ });
+
+ it('should render the new overview page when feature flag is enabled', () => {
+ const pluginContext = {
+ config: {
+ unsafe: {
+ overviewNext: { enabled: true },
+ },
+ },
+ };
+
+ jest
+ .spyOn(PluginContext, 'usePluginContext')
+ .mockReturnValue(pluginContext as PluginContextValue);
+
+ const component = shallow();
+ expect(component.find(OldOverviewPage)).toHaveLength(0);
+ expect(component.find(NewOverviewPage)).toHaveLength(1);
+ });
+});
diff --git a/x-pack/plugins/observability/public/pages/overview/index.tsx b/x-pack/plugins/observability/public/pages/overview/index.tsx
index 7100a0552876d..cc38445e3a0f2 100644
--- a/x-pack/plugins/observability/public/pages/overview/index.tsx
+++ b/x-pack/plugins/observability/public/pages/overview/index.tsx
@@ -4,133 +4,24 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-
-import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiPanel } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
import React from 'react';
-import { useTrackPageview } from '../..';
-import { EmptySections } from '../../components/app/empty_sections';
-import { ObservabilityHeaderMenu } from '../../components/app/header';
-import { NewsFeed } from '../../components/app/news_feed';
-import { Resources } from '../../components/app/resources';
-import { AlertsSection } from '../../components/app/section/alerts';
-import { DatePicker } from '../../components/shared/date_picker';
-import { useBreadcrumbs } from '../../hooks/use_breadcrumbs';
-import { useFetcher } from '../../hooks/use_fetcher';
-import { useHasData } from '../../hooks/use_has_data';
-import { usePluginContext } from '../../hooks/use_plugin_context';
-import { useTimeRange } from '../../hooks/use_time_range';
import { RouteParams } from '../../routes';
-import { getNewsFeed } from '../../services/get_news_feed';
-import { getBucketSize } from '../../utils/get_bucket_size';
-import { getNoDataConfig } from '../../utils/no_data_config';
-import { DataSections } from './data_sections';
-import { LoadingObservability } from './loading_observability';
+import { usePluginContext } from '../../hooks/use_plugin_context';
+import { OverviewPage as OldOverviewPage } from './old_overview_page';
+import { OverviewPage as NewOverviewPage } from './overview_page';
+
+export type { BucketSize } from './old_overview_page';
interface Props {
routeParams: RouteParams<'/overview'>;
}
-export type BucketSize = ReturnType;
-function calculateBucketSize({ start, end }: { start?: number; end?: number }) {
- if (start && end) {
- return getBucketSize({ start, end, minInterval: '60s' });
- }
-}
-
-export function OverviewPage({ routeParams }: Props) {
- useTrackPageview({ app: 'observability-overview', path: 'overview' });
- useTrackPageview({ app: 'observability-overview', path: 'overview', delay: 15000 });
- useBreadcrumbs([
- {
- text: i18n.translate('xpack.observability.breadcrumbs.overviewLinkText', {
- defaultMessage: 'Overview',
- }),
- },
- ]);
-
- const { core, ObservabilityPageTemplate } = usePluginContext();
-
- const { relativeStart, relativeEnd, absoluteStart, absoluteEnd } = useTimeRange();
- const relativeTime = { start: relativeStart, end: relativeEnd };
- const absoluteTime = { start: absoluteStart, end: absoluteEnd };
+export function OverviewPage(props: Props) {
+ const { config } = usePluginContext();
- const { data: newsFeed } = useFetcher(() => getNewsFeed({ core }), [core]);
-
- const { hasDataMap, hasAnyData, isAllRequestsComplete } = useHasData();
-
- if (hasAnyData === undefined) {
- return ;
+ if (config.unsafe.overviewNext.enabled) {
+ return ;
+ } else {
+ return ;
}
-
- const hasData = hasAnyData === true || (isAllRequestsComplete === false ? undefined : false);
-
- const noDataConfig = getNoDataConfig({
- hasData,
- basePath: core.http.basePath,
- docsLink: core.docLinks.links.observability.guide,
- });
-
- const { refreshInterval = 10000, refreshPaused = true } = routeParams.query;
-
- const bucketSize = calculateBucketSize({
- start: absoluteTime.start,
- end: absoluteTime.end,
- });
-
- return (
- ,
- ],
- }
- : undefined
- }
- >
- {hasData && (
- <>
-
-
-
- {/* Data sections */}
- {hasAnyData && }
-
-
-
-
- {/* Resources / What's New sections */}
-
-
-
- {!!newsFeed?.items?.length && }
-
-
- {hasDataMap?.alert?.hasData && (
-
-
-
-
-
- )}
-
-
-
- >
- )}
-
- );
}
-
-const overviewPageTitle = i18n.translate('xpack.observability.overview.pageTitle', {
- defaultMessage: 'Overview',
-});
diff --git a/x-pack/plugins/observability/public/pages/overview/old_overview_page.tsx b/x-pack/plugins/observability/public/pages/overview/old_overview_page.tsx
new file mode 100644
index 0000000000000..7100a0552876d
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/overview/old_overview_page.tsx
@@ -0,0 +1,136 @@
+/*
+ * 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 { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiPanel } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import React from 'react';
+import { useTrackPageview } from '../..';
+import { EmptySections } from '../../components/app/empty_sections';
+import { ObservabilityHeaderMenu } from '../../components/app/header';
+import { NewsFeed } from '../../components/app/news_feed';
+import { Resources } from '../../components/app/resources';
+import { AlertsSection } from '../../components/app/section/alerts';
+import { DatePicker } from '../../components/shared/date_picker';
+import { useBreadcrumbs } from '../../hooks/use_breadcrumbs';
+import { useFetcher } from '../../hooks/use_fetcher';
+import { useHasData } from '../../hooks/use_has_data';
+import { usePluginContext } from '../../hooks/use_plugin_context';
+import { useTimeRange } from '../../hooks/use_time_range';
+import { RouteParams } from '../../routes';
+import { getNewsFeed } from '../../services/get_news_feed';
+import { getBucketSize } from '../../utils/get_bucket_size';
+import { getNoDataConfig } from '../../utils/no_data_config';
+import { DataSections } from './data_sections';
+import { LoadingObservability } from './loading_observability';
+
+interface Props {
+ routeParams: RouteParams<'/overview'>;
+}
+export type BucketSize = ReturnType;
+function calculateBucketSize({ start, end }: { start?: number; end?: number }) {
+ if (start && end) {
+ return getBucketSize({ start, end, minInterval: '60s' });
+ }
+}
+
+export function OverviewPage({ routeParams }: Props) {
+ useTrackPageview({ app: 'observability-overview', path: 'overview' });
+ useTrackPageview({ app: 'observability-overview', path: 'overview', delay: 15000 });
+ useBreadcrumbs([
+ {
+ text: i18n.translate('xpack.observability.breadcrumbs.overviewLinkText', {
+ defaultMessage: 'Overview',
+ }),
+ },
+ ]);
+
+ const { core, ObservabilityPageTemplate } = usePluginContext();
+
+ const { relativeStart, relativeEnd, absoluteStart, absoluteEnd } = useTimeRange();
+
+ const relativeTime = { start: relativeStart, end: relativeEnd };
+ const absoluteTime = { start: absoluteStart, end: absoluteEnd };
+
+ const { data: newsFeed } = useFetcher(() => getNewsFeed({ core }), [core]);
+
+ const { hasDataMap, hasAnyData, isAllRequestsComplete } = useHasData();
+
+ if (hasAnyData === undefined) {
+ return ;
+ }
+
+ const hasData = hasAnyData === true || (isAllRequestsComplete === false ? undefined : false);
+
+ const noDataConfig = getNoDataConfig({
+ hasData,
+ basePath: core.http.basePath,
+ docsLink: core.docLinks.links.observability.guide,
+ });
+
+ const { refreshInterval = 10000, refreshPaused = true } = routeParams.query;
+
+ const bucketSize = calculateBucketSize({
+ start: absoluteTime.start,
+ end: absoluteTime.end,
+ });
+
+ return (
+ ,
+ ],
+ }
+ : undefined
+ }
+ >
+ {hasData && (
+ <>
+
+
+
+ {/* Data sections */}
+ {hasAnyData && }
+
+
+
+
+ {/* Resources / What's New sections */}
+
+
+
+ {!!newsFeed?.items?.length && }
+
+
+ {hasDataMap?.alert?.hasData && (
+
+
+
+
+
+ )}
+
+
+
+ >
+ )}
+
+ );
+}
+
+const overviewPageTitle = i18n.translate('xpack.observability.overview.pageTitle', {
+ defaultMessage: 'Overview',
+});
diff --git a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx
index 6549e892cab12..6213ea3e66d40 100644
--- a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx
+++ b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx
@@ -66,7 +66,11 @@ const withCore = makeDecorator({
setHeaderActionMenu: () => {},
} as unknown as AppMountParameters,
config: {
- unsafe: { alertingExperience: { enabled: true }, cases: { enabled: true } },
+ unsafe: {
+ alertingExperience: { enabled: true },
+ cases: { enabled: true },
+ overviewNext: { enabled: false },
+ },
},
core: options as CoreStart,
plugins: {
diff --git a/x-pack/plugins/observability/public/pages/overview/overview_page.tsx b/x-pack/plugins/observability/public/pages/overview/overview_page.tsx
new file mode 100644
index 0000000000000..f4cdec680af94
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/overview/overview_page.tsx
@@ -0,0 +1,82 @@
+/*
+ * 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 { i18n } from '@kbn/i18n';
+import React from 'react';
+import { useTrackPageview } from '../..';
+import { DatePicker } from '../../components/shared/date_picker';
+import { useBreadcrumbs } from '../../hooks/use_breadcrumbs';
+import { useHasData } from '../../hooks/use_has_data';
+import { usePluginContext } from '../../hooks/use_plugin_context';
+import { useTimeRange } from '../../hooks/use_time_range';
+import { RouteParams } from '../../routes';
+import { getNoDataConfig } from '../../utils/no_data_config';
+import { LoadingObservability } from './loading_observability';
+
+interface Props {
+ routeParams: RouteParams<'/overview'>;
+}
+
+export function OverviewPage({ routeParams }: Props) {
+ useTrackPageview({ app: 'observability-overview', path: 'overview' });
+ useTrackPageview({ app: 'observability-overview', path: 'overview', delay: 15000 });
+ useBreadcrumbs([
+ {
+ text: i18n.translate('xpack.observability.breadcrumbs.overviewLinkText', {
+ defaultMessage: 'Overview',
+ }),
+ },
+ ]);
+
+ const { core, ObservabilityPageTemplate } = usePluginContext();
+
+ const { relativeStart, relativeEnd } = useTimeRange();
+
+ const relativeTime = { start: relativeStart, end: relativeEnd };
+
+ const { hasAnyData, isAllRequestsComplete } = useHasData();
+
+ if (hasAnyData === undefined) {
+ return ;
+ }
+
+ const hasData = hasAnyData === true || (isAllRequestsComplete === false ? undefined : false);
+
+ const noDataConfig = getNoDataConfig({
+ hasData,
+ basePath: core.http.basePath,
+ docsLink: core.docLinks.links.observability.guide,
+ });
+
+ const { refreshInterval = 10000, refreshPaused = true } = routeParams.query;
+
+ return (
+ ,
+ ],
+ }
+ : undefined
+ }
+ >
+ {hasData && New observability content goes here
}
+
+ );
+}
+
+const overviewPageTitle = i18n.translate('xpack.observability.overview.pageTitle', {
+ defaultMessage: 'Overview',
+});
diff --git a/x-pack/plugins/observability/public/utils/test_helper.tsx b/x-pack/plugins/observability/public/utils/test_helper.tsx
index 544f3feecb2bb..a3ec446e5c307 100644
--- a/x-pack/plugins/observability/public/utils/test_helper.tsx
+++ b/x-pack/plugins/observability/public/utils/test_helper.tsx
@@ -34,7 +34,13 @@ export const core = {
},
} as unknown as CoreStart;
-const config = { unsafe: { alertingExperience: { enabled: true }, cases: { enabled: true } } };
+const config = {
+ unsafe: {
+ alertingExperience: { enabled: true },
+ cases: { enabled: true },
+ overviewNext: { enabled: false },
+ },
+};
const plugins = {
data: { query: { timefilter: { timefilter: { setTime: jest.fn() } } } },
diff --git a/x-pack/plugins/observability/server/index.ts b/x-pack/plugins/observability/server/index.ts
index d99cf0865c0dd..51204c7512a3d 100644
--- a/x-pack/plugins/observability/server/index.ts
+++ b/x-pack/plugins/observability/server/index.ts
@@ -34,6 +34,7 @@ export const config: PluginConfigDescriptor = {
unsafe: schema.object({
alertingExperience: schema.object({ enabled: schema.boolean({ defaultValue: true }) }),
cases: schema.object({ enabled: schema.boolean({ defaultValue: true }) }),
+ overviewNext: schema.object({ enabled: schema.boolean({ defaultValue: false }) }),
}),
}),
};
From 75fcfe1c80ff78f2c3ef1f8065b531d171a3a273 Mon Sep 17 00:00:00 2001
From: "Christiane (Tina) Heiligers"
Date: Mon, 29 Nov 2021 09:17:15 -0700
Subject: [PATCH 17/47] Docs/kibana logging links (#119680)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
docs/migration/migrate_8_0.asciidoc | 8 ++++----
docs/settings/logging-settings.asciidoc | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/docs/migration/migrate_8_0.asciidoc b/docs/migration/migrate_8_0.asciidoc
index 59dd36a4fa5ef..8936e41762c69 100644
--- a/docs/migration/migrate_8_0.asciidoc
+++ b/docs/migration/migrate_8_0.asciidoc
@@ -65,7 +65,7 @@ If you are currently using one of these settings in your Kibana config, please r
==== Default logging timezone is now the system's timezone
*Details:* In prior releases the timezone used in logs defaulted to UTC. We now use the host machine's timezone by default.
-*Impact:* To restore the previous behavior, in kibana.yml use the pattern layout, with a date modifier:
+*Impact:* To restore the previous behavior, in kibana.yml use the pattern layout, with a {kibana-ref}/logging-configuration.html#date-format[date modifier]:
[source,yaml]
-------------------
logging:
@@ -100,7 +100,7 @@ See https://github.com/elastic/kibana/pull/87939 for more details.
[float]
==== Logging destination is specified by the appender
-*Details:* Previously log destination would be `stdout` and could be changed to `file` using `logging.dest`. With the new logging configuration, you can specify the destination using appenders.
+*Details:* Previously log destination would be `stdout` and could be changed to `file` using `logging.dest`. With the new logging configuration, you can specify the destination using {kibana-ref}/logging-configuration.html#logging-appenders[appenders].
*Impact:* To restore the previous behavior and log records to *stdout*, in `kibana.yml` use an appender with `type: console`.
[source,yaml]
@@ -131,7 +131,7 @@ logging:
[float]
==== Set log verbosity with root
-*Details:* Previously logging output would be specified by `logging.silent` (none), `logging.quiet` (error messages only) and `logging.verbose` (all). With the new logging configuration, set the minimum required log level.
+*Details:* Previously logging output would be specified by `logging.silent` (none), `logging.quiet` (error messages only) and `logging.verbose` (all). With the new logging configuration, set the minimum required {kibana-ref}/logging-configuration.html#log-level[log level].
*Impact:* To restore the previous behavior, in `kibana.yml` specify `logging.root.level`:
[source,yaml]
@@ -188,7 +188,7 @@ logging:
==== Configure log rotation with the rolling-file appender
*Details:* Previously log rotation would be enabled when `logging.rotate.enabled` was true.
-*Impact:* To restore the previous behavior, in `kibana.yml` use the `rolling-file` appender.
+*Impact:* To restore the previous behavior, in `kibana.yml` use the {kibana-ref}/logging-configuration.html#rolling-file-appender[`rolling-file`] appender.
[source,yaml]
-------------------
diff --git a/docs/settings/logging-settings.asciidoc b/docs/settings/logging-settings.asciidoc
index cb8237c5aa384..a9053b90ce722 100644
--- a/docs/settings/logging-settings.asciidoc
+++ b/docs/settings/logging-settings.asciidoc
@@ -30,7 +30,7 @@ The following table serves as a quick reference for different logging configurat
| Allows you to specify a fileName to write log records to disk. To write <>, add the file appender to `root.appenders`. If configured, you also need to specify <>.
| `logging.appenders[].rolling-file:`
-| Similar to Log4j's `RollingFileAppender`, this appender will log to a file and rotate if following a rolling strategy when the configured policy triggers. There are currently two policies supported: `size-limit` and `time-interval`.
+| Similar to https://logging.apache.org/log4j/2.x/[Log4j's] `RollingFileAppender`, this appender will log to a file and rotate if following a rolling strategy when the configured policy triggers. There are currently two policies supported: <> and <>.
| `logging.appenders[]..type`
| The appender type determines where the log messages are sent. Options are `console`, `file`, `rewrite`, `rolling-file`. Required.
From 095247f8574fa9c93521fcddd490bc1bdc1b5d9c Mon Sep 17 00:00:00 2001
From: Shahzad
Date: Mon, 29 Nov 2021 18:29:30 +0100
Subject: [PATCH 18/47] [Uptime] Monitor management stub crud routes (#119800)
* fix uptime config key
* crud routes
* prefix
* test wip
* add tests
* revert
* fixed path
---
x-pack/plugins/uptime/common/config.ts | 2 +-
.../uptime/common/constants/rest_api.ts | 3 +-
.../framework/kibana_framework_adapter.ts | 7 +++
.../plugins/uptime/server/rest_api/index.ts | 12 +++++
.../synthetics_service/add_monitor.ts | 26 ++++++++++
.../synthetics_service/delete_monitor.ts | 34 +++++++++++++
.../synthetics_service/edit_monitor.ts | 31 +++++++++++
.../synthetics_service/get_monitors.ts | 40 +++++++++++++++
.../apis/uptime/rest/add_monitor.ts | 29 +++++++++++
.../apis/uptime/rest/delete_monitor.ts | 36 +++++++++++++
.../apis/uptime/rest/edit_monitor.ts | 37 ++++++++++++++
.../apis/uptime/rest/get_monitor.ts | 51 +++++++++++++++++++
.../api_integration/apis/uptime/rest/index.ts | 7 +++
x-pack/test/api_integration/config.ts | 4 ++
14 files changed, 317 insertions(+), 2 deletions(-)
create mode 100644 x-pack/plugins/uptime/server/rest_api/synthetics_service/add_monitor.ts
create mode 100644 x-pack/plugins/uptime/server/rest_api/synthetics_service/delete_monitor.ts
create mode 100644 x-pack/plugins/uptime/server/rest_api/synthetics_service/edit_monitor.ts
create mode 100644 x-pack/plugins/uptime/server/rest_api/synthetics_service/get_monitors.ts
create mode 100644 x-pack/test/api_integration/apis/uptime/rest/add_monitor.ts
create mode 100644 x-pack/test/api_integration/apis/uptime/rest/delete_monitor.ts
create mode 100644 x-pack/test/api_integration/apis/uptime/rest/edit_monitor.ts
create mode 100644 x-pack/test/api_integration/apis/uptime/rest/get_monitor.ts
diff --git a/x-pack/plugins/uptime/common/config.ts b/x-pack/plugins/uptime/common/config.ts
index ccd5e7b5a2cc6..8b70869645649 100644
--- a/x-pack/plugins/uptime/common/config.ts
+++ b/x-pack/plugins/uptime/common/config.ts
@@ -36,7 +36,7 @@ export const config: PluginConfigDescriptor = {
username: schema.string(),
password: schema.string(),
manifestUrl: schema.string(),
- hosts: schema.arrayOf(schema.string()),
+ hosts: schema.maybe(schema.arrayOf(schema.string())),
})
),
})
diff --git a/x-pack/plugins/uptime/common/constants/rest_api.ts b/x-pack/plugins/uptime/common/constants/rest_api.ts
index bef84c41796d9..9c8098390d129 100644
--- a/x-pack/plugins/uptime/common/constants/rest_api.ts
+++ b/x-pack/plugins/uptime/common/constants/rest_api.ts
@@ -37,5 +37,6 @@ export enum API_URLS {
CONNECTOR_TYPES = '/api/actions/connector_types',
// Service end points
- INDEX_TEMPLATES = '/api/uptime/service/index_templates',
+ INDEX_TEMPLATES = '/internal/uptime/service/index_templates',
+ SYNTHETICS_MONITORS = '/internal/uptime/service/monitors',
}
diff --git a/x-pack/plugins/uptime/server/lib/adapters/framework/kibana_framework_adapter.ts b/x-pack/plugins/uptime/server/lib/adapters/framework/kibana_framework_adapter.ts
index eae9dd5e73cae..d51496d6efaf1 100644
--- a/x-pack/plugins/uptime/server/lib/adapters/framework/kibana_framework_adapter.ts
+++ b/x-pack/plugins/uptime/server/lib/adapters/framework/kibana_framework_adapter.ts
@@ -20,6 +20,7 @@ export class UMKibanaBackendFrameworkAdapter implements UMBackendFrameworkAdapte
validate,
options,
};
+
switch (method) {
case 'GET':
this.server.router.get(routeDefinition, handler);
@@ -27,6 +28,12 @@ export class UMKibanaBackendFrameworkAdapter implements UMBackendFrameworkAdapte
case 'POST':
this.server.router.post(routeDefinition, handler);
break;
+ case 'PUT':
+ this.server.router.put(routeDefinition, handler);
+ break;
+ case 'DELETE':
+ this.server.router.delete(routeDefinition, handler);
+ break;
default:
throw new Error(`Handler for method ${method} is not defined`);
}
diff --git a/x-pack/plugins/uptime/server/rest_api/index.ts b/x-pack/plugins/uptime/server/rest_api/index.ts
index 344dd4d203d8d..4eb6ae3071256 100644
--- a/x-pack/plugins/uptime/server/rest_api/index.ts
+++ b/x-pack/plugins/uptime/server/rest_api/index.ts
@@ -28,6 +28,13 @@ 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';
+import {
+ getAllSyntheticsMonitorRoute,
+ getSyntheticsMonitorRoute,
+} from './synthetics_service/get_monitors';
+import { addSyntheticsMonitorRoute } from './synthetics_service/add_monitor';
+import { editSyntheticsMonitorRoute } from './synthetics_service/edit_monitor';
+import { deleteSyntheticsMonitorRoute } from './synthetics_service/delete_monitor';
export * from './types';
export { createRouteWithAuth } from './create_route_with_auth';
@@ -53,4 +60,9 @@ export const restApiRoutes: UMRestApiRouteFactory[] = [
createLastSuccessfulStepRoute,
createJourneyScreenshotBlocksRoute,
installIndexTemplatesRoute,
+ getSyntheticsMonitorRoute,
+ getAllSyntheticsMonitorRoute,
+ addSyntheticsMonitorRoute,
+ editSyntheticsMonitorRoute,
+ deleteSyntheticsMonitorRoute,
];
diff --git a/x-pack/plugins/uptime/server/rest_api/synthetics_service/add_monitor.ts b/x-pack/plugins/uptime/server/rest_api/synthetics_service/add_monitor.ts
new file mode 100644
index 0000000000000..11d7dcedcaa34
--- /dev/null
+++ b/x-pack/plugins/uptime/server/rest_api/synthetics_service/add_monitor.ts
@@ -0,0 +1,26 @@
+/*
+ * 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 } from '@kbn/config-schema';
+import { UMRestApiRouteFactory } from '../types';
+import { API_URLS } from '../../../common/constants';
+import { SyntheticsMonitorSavedObject } from '../../../common/types';
+import { syntheticsMonitorType } from '../../lib/saved_objects/synthetics_monitor';
+
+export const addSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({
+ method: 'POST',
+ path: API_URLS.SYNTHETICS_MONITORS,
+ validate: {
+ body: schema.any(),
+ },
+ handler: async ({ request, savedObjectsClient }): Promise => {
+ const monitor = request.body as SyntheticsMonitorSavedObject;
+
+ const newMonitor = await savedObjectsClient.create(syntheticsMonitorType, monitor);
+ // TODO: call to service sync
+ return newMonitor;
+ },
+});
diff --git a/x-pack/plugins/uptime/server/rest_api/synthetics_service/delete_monitor.ts b/x-pack/plugins/uptime/server/rest_api/synthetics_service/delete_monitor.ts
new file mode 100644
index 0000000000000..68eb8aa130d2e
--- /dev/null
+++ b/x-pack/plugins/uptime/server/rest_api/synthetics_service/delete_monitor.ts
@@ -0,0 +1,34 @@
+/*
+ * 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 } from '@kbn/config-schema';
+import { SavedObjectsErrorHelpers } from '../../../../../../src/core/server';
+import { UMRestApiRouteFactory } from '../types';
+import { API_URLS } from '../../../common/constants';
+import { syntheticsMonitorType } from '../../lib/saved_objects/synthetics_monitor';
+
+export const deleteSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({
+ method: 'DELETE',
+ path: API_URLS.SYNTHETICS_MONITORS + '/{monitorId}',
+ validate: {
+ params: schema.object({
+ monitorId: schema.string(),
+ }),
+ },
+ handler: async ({ request, savedObjectsClient }): Promise => {
+ const { monitorId } = request.params;
+
+ try {
+ await savedObjectsClient.delete(syntheticsMonitorType, monitorId);
+ // TODO: call to service sync
+ return monitorId;
+ } catch (getErr) {
+ if (SavedObjectsErrorHelpers.isNotFoundError(getErr)) {
+ return 'Not found';
+ }
+ }
+ },
+});
diff --git a/x-pack/plugins/uptime/server/rest_api/synthetics_service/edit_monitor.ts b/x-pack/plugins/uptime/server/rest_api/synthetics_service/edit_monitor.ts
new file mode 100644
index 0000000000000..46a91738c380d
--- /dev/null
+++ b/x-pack/plugins/uptime/server/rest_api/synthetics_service/edit_monitor.ts
@@ -0,0 +1,31 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+import { schema } from '@kbn/config-schema';
+import { UMRestApiRouteFactory } from '../types';
+import { API_URLS } from '../../../common/constants';
+import { SyntheticsMonitorSavedObject } from '../../../common/types';
+import { syntheticsMonitorType } from '../../lib/saved_objects/synthetics_monitor';
+
+export const editSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({
+ method: 'PUT',
+ path: API_URLS.SYNTHETICS_MONITORS + '/{monitorId}',
+ validate: {
+ params: schema.object({
+ monitorId: schema.string(),
+ }),
+ body: schema.any(),
+ },
+ handler: async ({ request, savedObjectsClient }): Promise => {
+ const monitor = request.body as SyntheticsMonitorSavedObject['attributes'];
+
+ const { monitorId } = request.params;
+
+ const editMonitor = await savedObjectsClient.update(syntheticsMonitorType, monitorId, monitor);
+ // TODO: call to service sync
+ return editMonitor;
+ },
+});
diff --git a/x-pack/plugins/uptime/server/rest_api/synthetics_service/get_monitors.ts b/x-pack/plugins/uptime/server/rest_api/synthetics_service/get_monitors.ts
new file mode 100644
index 0000000000000..537d6c77195ca
--- /dev/null
+++ b/x-pack/plugins/uptime/server/rest_api/synthetics_service/get_monitors.ts
@@ -0,0 +1,40 @@
+/*
+ * 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 } from '@kbn/config-schema';
+import { UMRestApiRouteFactory } from '../types';
+import { API_URLS } from '../../../common/constants';
+import { syntheticsMonitorType } from '../../lib/saved_objects/synthetics_monitor';
+
+export const getSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({
+ method: 'GET',
+ path: API_URLS.SYNTHETICS_MONITORS + '/{monitorId}',
+ validate: {
+ params: schema.object({
+ monitorId: schema.string(),
+ }),
+ },
+ handler: async ({ request, savedObjectsClient }): Promise => {
+ const { monitorId } = request.params;
+ return await savedObjectsClient.get(syntheticsMonitorType, monitorId);
+ },
+});
+
+export const getAllSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({
+ method: 'GET',
+ path: API_URLS.SYNTHETICS_MONITORS,
+ validate: {
+ query: schema.object({
+ page: schema.maybe(schema.number()),
+ perPage: schema.maybe(schema.number()),
+ }),
+ },
+ handler: async ({ request, savedObjectsClient }): Promise => {
+ const { perPage = 50, page } = request.query;
+ // TODO: add query/filtering params
+ return await savedObjectsClient.find({ type: syntheticsMonitorType, perPage, page });
+ },
+});
diff --git a/x-pack/test/api_integration/apis/uptime/rest/add_monitor.ts b/x-pack/test/api_integration/apis/uptime/rest/add_monitor.ts
new file mode 100644
index 0000000000000..a57a03fd3a1f5
--- /dev/null
+++ b/x-pack/test/api_integration/apis/uptime/rest/add_monitor.ts
@@ -0,0 +1,29 @@
+/*
+ * 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 expect from '@kbn/expect';
+import { FtrProviderContext } from '../../../ftr_provider_context';
+import { API_URLS } from '../../../../../plugins/uptime/common/constants';
+
+export default function ({ getService }: FtrProviderContext) {
+ describe('add synthetics monitor', () => {
+ const supertest = getService('supertest');
+ const newMonitor = {
+ type: 'http',
+ name: 'Test monitor',
+ urls: 'https://www.elastic.co',
+ };
+
+ it('returns the newly added monitor', async () => {
+ const apiResponse = await supertest
+ .post(API_URLS.SYNTHETICS_MONITORS)
+ .set('kbn-xsrf', 'true')
+ .send(newMonitor);
+
+ expect(apiResponse.body.attributes).eql(newMonitor);
+ });
+ });
+}
diff --git a/x-pack/test/api_integration/apis/uptime/rest/delete_monitor.ts b/x-pack/test/api_integration/apis/uptime/rest/delete_monitor.ts
new file mode 100644
index 0000000000000..bc49587fab872
--- /dev/null
+++ b/x-pack/test/api_integration/apis/uptime/rest/delete_monitor.ts
@@ -0,0 +1,36 @@
+/*
+ * 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 expect from '@kbn/expect';
+import { FtrProviderContext } from '../../../ftr_provider_context';
+import { API_URLS } from '../../../../../plugins/uptime/common/constants';
+
+export default function ({ getService }: FtrProviderContext) {
+ describe('delete synthetics monitor', () => {
+ const supertest = getService('supertest');
+ const newMonitor = {
+ type: 'http',
+ name: 'Test monitor',
+ urls: 'https://www.elastic.co',
+ };
+
+ it('deleted monitor by id', async () => {
+ const apiResponse = await supertest
+ .post(API_URLS.SYNTHETICS_MONITORS)
+ .set('kbn-xsrf', 'true')
+ .send(newMonitor);
+
+ const monitorId = apiResponse.body.id;
+
+ const deleteResponse = await supertest
+ .delete(API_URLS.SYNTHETICS_MONITORS + '/' + monitorId)
+ .set('kbn-xsrf', 'true');
+ //
+ expect(deleteResponse.body).eql(monitorId);
+ });
+ });
+}
diff --git a/x-pack/test/api_integration/apis/uptime/rest/edit_monitor.ts b/x-pack/test/api_integration/apis/uptime/rest/edit_monitor.ts
new file mode 100644
index 0000000000000..f5d54c40a8646
--- /dev/null
+++ b/x-pack/test/api_integration/apis/uptime/rest/edit_monitor.ts
@@ -0,0 +1,37 @@
+/*
+ * 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 expect from '@kbn/expect';
+import { FtrProviderContext } from '../../../ftr_provider_context';
+import { API_URLS } from '../../../../../plugins/uptime/common/constants';
+export default function ({ getService }: FtrProviderContext) {
+ describe('edit synthetics monitor', () => {
+ const supertest = getService('supertest');
+ const newMonitor = {
+ type: 'http',
+ name: 'Test monitor',
+ urls: 'https://www.elastic.co',
+ };
+
+ it('edits the monitor', async () => {
+ const apiResponse = await supertest
+ .post(API_URLS.SYNTHETICS_MONITORS)
+ .set('kbn-xsrf', 'true')
+ .send(newMonitor);
+
+ const monitorId = apiResponse.body.id;
+
+ expect(apiResponse.body.attributes).eql(newMonitor);
+
+ const editResponse = await supertest
+ .put(API_URLS.SYNTHETICS_MONITORS + '/' + monitorId)
+ .set('kbn-xsrf', 'true')
+ .send({ ...newMonitor, name: 'New name' });
+
+ expect(editResponse.body.attributes.name).eql('New name');
+ });
+ });
+}
diff --git a/x-pack/test/api_integration/apis/uptime/rest/get_monitor.ts b/x-pack/test/api_integration/apis/uptime/rest/get_monitor.ts
new file mode 100644
index 0000000000000..76d27ff8a9d1d
--- /dev/null
+++ b/x-pack/test/api_integration/apis/uptime/rest/get_monitor.ts
@@ -0,0 +1,51 @@
+/*
+ * 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 expect from '@kbn/expect';
+import { FtrProviderContext } from '../../../ftr_provider_context';
+import { API_URLS } from '../../../../../plugins/uptime/common/constants';
+
+export default function ({ getService }: FtrProviderContext) {
+ describe('get synthetics monitor', () => {
+ const newMonitor = {
+ type: 'http',
+ name: 'Test monitor',
+ urls: 'https://www.elastic.co',
+ };
+
+ const addMonitor = async () => {
+ const res = await supertest
+ .post(API_URLS.SYNTHETICS_MONITORS)
+ .set('kbn-xsrf', 'true')
+ .send(newMonitor);
+ return res.body.id;
+ };
+
+ const supertest = getService('supertest');
+
+ it('get all monitors', async () => {
+ const id1 = await addMonitor();
+ const id2 = await addMonitor();
+
+ const apiResponse = await supertest.get(API_URLS.SYNTHETICS_MONITORS);
+
+ const monitor1 = apiResponse.body.saved_objects.find((obj: any) => obj.id === id1);
+ const monitor2 = apiResponse.body.saved_objects.find((obj: any) => obj.id === id2);
+
+ expect(monitor1.id).eql(id1);
+ expect(monitor2.id).eql(id2);
+ });
+
+ it('get monitor by id', async () => {
+ const monitorId = await addMonitor();
+
+ const apiResponse = await supertest.get(API_URLS.SYNTHETICS_MONITORS + '/' + monitorId);
+
+ expect(apiResponse.body.id).eql(monitorId);
+ });
+ });
+}
diff --git a/x-pack/test/api_integration/apis/uptime/rest/index.ts b/x-pack/test/api_integration/apis/uptime/rest/index.ts
index dc3c00b03f712..f674879552d6a 100644
--- a/x-pack/test/api_integration/apis/uptime/rest/index.ts
+++ b/x-pack/test/api_integration/apis/uptime/rest/index.ts
@@ -71,5 +71,12 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./index_status'));
loadTestFile(require.resolve('./monitor_states_real_data'));
});
+
+ describe('uptime CRUD routes', () => {
+ loadTestFile(require.resolve('./get_monitor'));
+ loadTestFile(require.resolve('./add_monitor'));
+ loadTestFile(require.resolve('./edit_monitor'));
+ loadTestFile(require.resolve('./delete_monitor'));
+ });
});
}
diff --git a/x-pack/test/api_integration/config.ts b/x-pack/test/api_integration/config.ts
index e2c2e0b52dfdc..bf42a5b0865a2 100644
--- a/x-pack/test/api_integration/config.ts
+++ b/x-pack/test/api_integration/config.ts
@@ -35,6 +35,10 @@ export async function getApiIntegrationConfig({ readConfigFile }: FtrConfigProvi
'--xpack.ruleRegistry.write.enabled=true',
'--xpack.ruleRegistry.write.enabled=true',
'--xpack.ruleRegistry.write.cache.enabled=false',
+ '--xpack.uptime.unsafe.service.enabled=true',
+ '--xpack.uptime.unsafe.service.password=test',
+ '--xpack.uptime.unsafe.service.manifestUrl=http://test.com',
+ '--xpack.uptime.unsafe.service.username=user',
`--xpack.securitySolution.enableExperimental=${JSON.stringify(['ruleRegistryEnabled'])}`,
],
},
From 8915c90a3127e14bf2b778bd1daa7310a96ce31f Mon Sep 17 00:00:00 2001
From: Jean-Louis Leysens
Date: Mon, 29 Nov 2021 19:03:29 +0100
Subject: [PATCH 19/47] [es-query] Fix logic for detecting scripted phrase
fields (#119511)
* WIP, started updating functions for detecting scripted phrase filters
* replace script.script with query.script.script
* added test to verify detection of scripted and phrase filters
* with elastic@ email
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../build_filters/phrase_filter.test.ts | 25 ++++++++++++++++++-
.../filters/build_filters/phrase_filter.ts | 10 +++++---
.../filter_manager/lib/generate_filters.ts | 4 ++-
.../filter_manager/lib/mappers/map_phrase.ts | 2 +-
.../filter_manager/phrase_filter_manager.ts | 4 +--
5 files changed, 36 insertions(+), 9 deletions(-)
diff --git a/packages/kbn-es-query/src/filters/build_filters/phrase_filter.test.ts b/packages/kbn-es-query/src/filters/build_filters/phrase_filter.test.ts
index 87a7812165a66..7c7f7dd28f6ca 100644
--- a/packages/kbn-es-query/src/filters/build_filters/phrase_filter.test.ts
+++ b/packages/kbn-es-query/src/filters/build_filters/phrase_filter.test.ts
@@ -5,16 +5,19 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
-
+import { set } from 'lodash';
import {
buildInlineScriptForPhraseFilter,
buildPhraseFilter,
getPhraseFilterField,
PhraseFilter,
+ isPhraseFilter,
+ isScriptedPhraseFilter,
} from './phrase_filter';
import { fields, getField } from '../stubs';
import { DataViewBase } from '../../es_query';
import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
+import { Filter } from './types';
describe('Phrase filter builder', () => {
let indexPattern: DataViewBase;
@@ -164,3 +167,23 @@ describe('getPhraseFilterField', function () {
expect(result).toBe('extension');
});
});
+
+describe('isPhraseFilter', () => {
+ it('should return true if the filter is a phrases filter false otherwise', () => {
+ const filter: Filter = set({ meta: {} }, 'query.match_phrase', {}) as Filter;
+ const unknownFilter = {} as Filter;
+
+ expect(isPhraseFilter(filter)).toBe(true);
+ expect(isPhraseFilter(unknownFilter)).toBe(false);
+ });
+});
+
+describe('isScriptedPhraseFilter', () => {
+ it('should return true if the filter is a phrases filter false otherwise', () => {
+ const filter: Filter = set({ meta: {} }, 'query.script.script.params.value', {}) as Filter;
+ const unknownFilter = {} as Filter;
+
+ expect(isScriptedPhraseFilter(filter)).toBe(true);
+ expect(isPhraseFilter(unknownFilter)).toBe(false);
+ });
+});
diff --git a/packages/kbn-es-query/src/filters/build_filters/phrase_filter.ts b/packages/kbn-es-query/src/filters/build_filters/phrase_filter.ts
index 4c1827dc58c04..525463c9de246 100644
--- a/packages/kbn-es-query/src/filters/build_filters/phrase_filter.ts
+++ b/packages/kbn-es-query/src/filters/build_filters/phrase_filter.ts
@@ -31,8 +31,10 @@ export type PhraseFilter = Filter & {
export type ScriptedPhraseFilter = Filter & {
meta: PhraseFilterMeta;
- script: {
- script: estypes.InlineScript;
+ query: {
+ script: {
+ script: estypes.InlineScript;
+ };
};
};
@@ -58,7 +60,7 @@ export const isPhraseFilter = (filter: Filter): filter is PhraseFilter => {
* @public
*/
export const isScriptedPhraseFilter = (filter: Filter): filter is ScriptedPhraseFilter =>
- has(filter, 'script.script.params.value');
+ has(filter, 'query.script.script.params.value');
/** @internal */
export const getPhraseFilterField = (filter: PhraseFilter) => {
@@ -77,7 +79,7 @@ export const getPhraseFilterValue = (
const queryValue = Object.values(queryConfig)[0];
return isPlainObject(queryValue) ? queryValue.query : queryValue;
} else {
- return filter.script.script.params?.value;
+ return filter.query?.script?.script?.params?.value;
}
};
diff --git a/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts b/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts
index cfc3ddabe0751..58f5cf8e52c91 100644
--- a/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts
@@ -40,7 +40,9 @@ function getExistingFilter(
}
if (isScriptedPhraseFilter(filter)) {
- return filter.meta.field === fieldName && filter.script.script.params?.value === value;
+ return (
+ filter.meta.field === fieldName && filter.query?.script?.script?.params?.value === value
+ );
}
}) as any;
}
diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts
index 64576d4978c99..23cae0ee852ca 100644
--- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts
@@ -20,7 +20,7 @@ import {
import { FilterValueFormatter } from '../../../../../common';
const getScriptedPhraseValue = (filter: PhraseFilter) =>
- get(filter, ['script', 'script', 'params', 'value']);
+ get(filter, ['query', 'script', 'script', 'params', 'value']);
const getFormattedValueFn = (value: any) => {
return (formatter?: FilterValueFormatter) => {
diff --git a/src/plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.ts b/src/plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.ts
index 8ffeefefd0cc3..98ba8b4fbcda8 100644
--- a/src/plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.ts
+++ b/src/plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.ts
@@ -97,8 +97,8 @@ export class PhraseFilterManager extends FilterManager {
}
// scripted field filter
- if (_.has(kbnFilter, 'script')) {
- return _.get(kbnFilter, 'script.script.params.value');
+ if (_.has(kbnFilter, 'query.script')) {
+ return _.get(kbnFilter, 'query.script.script.params.value');
}
// single phrase filter
From c6db25a3ef5663cc71dce348036601707fac930d Mon Sep 17 00:00:00 2001
From: Tiago Costa
Date: Mon, 29 Nov 2021 18:15:06 +0000
Subject: [PATCH 20/47] chore(NA): splits types from code on @kbn/alerts
(#119855)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
package.json | 1 +
packages/BUILD.bazel | 1 +
packages/kbn-alerts/BUILD.bazel | 27 ++++++++++++++++++++++-----
packages/kbn-alerts/package.json | 1 -
yarn.lock | 4 ++++
5 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/package.json b/package.json
index 5e8a77f2c55f4..b0c7e4659a559 100644
--- a/package.json
+++ b/package.json
@@ -556,6 +556,7 @@
"@types/json-stable-stringify": "^1.0.32",
"@types/json5": "^0.0.30",
"@types/kbn__ace": "link:bazel-bin/packages/kbn-ace/npm_module_types",
+ "@types/kbn__alerts": "link:bazel-bin/packages/kbn-alerts/npm_module_types",
"@types/kbn__i18n": "link:bazel-bin/packages/kbn-i18n/npm_module_types",
"@types/kbn__i18n-react": "link:bazel-bin/packages/kbn-i18n-react/npm_module_types",
"@types/license-checker": "15.0.0",
diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel
index 07513ac94c85d..c9a0f6a759b2a 100644
--- a/packages/BUILD.bazel
+++ b/packages/BUILD.bazel
@@ -78,6 +78,7 @@ filegroup(
"//packages/elastic-apm-synthtrace:build_types",
"//packages/elastic-datemath:build_types",
"//packages/kbn-ace:build_types",
+ "//packages/kbn-alerts:build_types",
"//packages/kbn-i18n:build_types",
"//packages/kbn-i18n-react:build_types",
],
diff --git a/packages/kbn-alerts/BUILD.bazel b/packages/kbn-alerts/BUILD.bazel
index e567c18807dfc..15dbc163cd288 100644
--- a/packages/kbn-alerts/BUILD.bazel
+++ b/packages/kbn-alerts/BUILD.bazel
@@ -1,10 +1,10 @@
-load("@npm//@bazel/typescript:index.bzl", "ts_config", "ts_project")
-load("@build_bazel_rules_nodejs//:index.bzl", "js_library", "pkg_npm")
-load("//src/dev/bazel:index.bzl", "jsts_transpiler")
+load("@npm//@bazel/typescript:index.bzl", "ts_config")
+load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
+load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project")
PKG_BASE_NAME = "kbn-alerts"
-
PKG_REQUIRE_NAME = "@kbn/alerts"
+TYPES_PKG_REQUIRE_NAME = "@types/kbn__alerts"
SOURCE_FILES = glob(
[
@@ -87,7 +87,7 @@ ts_project(
js_library(
name = PKG_BASE_NAME,
srcs = NPM_MODULE_EXTRA_FILES,
- deps = RUNTIME_DEPS + [":target_node", ":target_web", ":tsc_types"],
+ deps = RUNTIME_DEPS + [":target_node", ":target_web"],
package_name = PKG_REQUIRE_NAME,
visibility = ["//visibility:public"],
)
@@ -106,3 +106,20 @@ filegroup(
],
visibility = ["//visibility:public"],
)
+
+pkg_npm_types(
+ name = "npm_module_types",
+ srcs = SRCS,
+ deps = [":tsc_types"],
+ package_name = TYPES_PKG_REQUIRE_NAME,
+ tsconfig = ":tsconfig",
+ visibility = ["//visibility:public"],
+)
+
+filegroup(
+ name = "build_types",
+ srcs = [
+ ":npm_module_types",
+ ],
+ visibility = ["//visibility:public"],
+)
diff --git a/packages/kbn-alerts/package.json b/packages/kbn-alerts/package.json
index b52a6efc35139..13b60ad9fa072 100644
--- a/packages/kbn-alerts/package.json
+++ b/packages/kbn-alerts/package.json
@@ -5,6 +5,5 @@
"license": "SSPL-1.0 OR Elastic License 2.0",
"browser": "./target_web/index.js",
"main": "./target_node/index.js",
- "types": "./target_types/index.d.ts",
"private": true
}
diff --git a/yarn.lock b/yarn.lock
index 821b788bc7c8f..71b82ffdf5af6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5809,6 +5809,10 @@
version "0.0.0"
uid ""
+"@types/kbn__alerts@link:bazel-bin/packages/kbn-alerts/npm_module_types":
+ version "0.0.0"
+ uid ""
+
"@types/kbn__i18n-react@link:bazel-bin/packages/kbn-i18n-react/npm_module_types":
version "0.0.0"
uid ""
From b2f54829d853db84a9aa4829ae664716aaacc9cd Mon Sep 17 00:00:00 2001
From: Spencer
Date: Mon, 29 Nov 2021 10:29:45 -0800
Subject: [PATCH 21/47] [babel] ensure TS preset runs before anything else
(#119107)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
packages/kbn-babel-preset/common_preset.js | 85 ++++++------
..._babel_runtime_helpers_in_entry_bundles.ts | 4 +-
.../src/worker/emit_stats_plugin.ts | 2 +-
packages/kbn-storybook/src/webpack.config.ts | 125 +++++++++++++++---
.../console/public/services/history.ts | 6 +-
.../viewport/dashboard_viewport.tsx | 2 +-
.../roles/roles_management_app.test.tsx | 6 +-
7 files changed, 168 insertions(+), 62 deletions(-)
diff --git a/packages/kbn-babel-preset/common_preset.js b/packages/kbn-babel-preset/common_preset.js
index 3a3763693db9a..824a73f9b2611 100644
--- a/packages/kbn-babel-preset/common_preset.js
+++ b/packages/kbn-babel-preset/common_preset.js
@@ -6,46 +6,57 @@
* Side Public License, v 1.
*/
-const plugins = [
- require.resolve('babel-plugin-add-module-exports'),
-
- // The class properties proposal was merged with the private fields proposal
- // into the "class fields" proposal. Babel doesn't support this combined
- // proposal yet, which includes private field, so this transform is
- // TECHNICALLY stage 2, but for all intents and purposes it's stage 3
- //
- // See https://github.com/babel/proposals/issues/12 for progress
- require.resolve('@babel/plugin-proposal-class-properties'),
-
- // Optional Chaining proposal is stage 4 (https://github.com/tc39/proposal-optional-chaining)
- // Need this since we are using TypeScript 3.7+
- require.resolve('@babel/plugin-proposal-optional-chaining'),
-
- // Nullish coalescing proposal is stage 4 (https://github.com/tc39/proposal-nullish-coalescing)
- // Need this since we are using TypeScript 3.7+
- require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
-
- // Proposal is on stage 4, and included in ECMA-262 (https://github.com/tc39/proposal-export-ns-from)
- // Need this since we are using TypeScript 3.8+
- require.resolve('@babel/plugin-proposal-export-namespace-from'),
-
- // Proposal is on stage 4, and included in ECMA-262 (https://github.com/tc39/proposal-export-ns-from)
- // Need this since we are using TypeScript 3.9+
- require.resolve('@babel/plugin-proposal-private-methods'),
-
- // It enables the @babel/runtime so we can decrease the bundle sizes of the produced outputs
- [
- require.resolve('@babel/plugin-transform-runtime'),
+module.exports = {
+ presets: [
+ // plugins always run before presets, but in this case we need the
+ // @babel/preset-typescript preset to run first so we have to move
+ // our explicit plugin configs to a sub-preset
{
- version: '^7.12.5',
+ plugins: [
+ require.resolve('babel-plugin-add-module-exports'),
+
+ // The class properties proposal was merged with the private fields proposal
+ // into the "class fields" proposal. Babel doesn't support this combined
+ // proposal yet, which includes private field, so this transform is
+ // TECHNICALLY stage 2, but for all intents and purposes it's stage 3
+ //
+ // See https://github.com/babel/proposals/issues/12 for progress
+ require.resolve('@babel/plugin-proposal-class-properties'),
+
+ // Optional Chaining proposal is stage 4 (https://github.com/tc39/proposal-optional-chaining)
+ // Need this since we are using TypeScript 3.7+
+ require.resolve('@babel/plugin-proposal-optional-chaining'),
+
+ // Nullish coalescing proposal is stage 4 (https://github.com/tc39/proposal-nullish-coalescing)
+ // Need this since we are using TypeScript 3.7+
+ require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
+
+ // Proposal is on stage 4, and included in ECMA-262 (https://github.com/tc39/proposal-export-ns-from)
+ // Need this since we are using TypeScript 3.8+
+ require.resolve('@babel/plugin-proposal-export-namespace-from'),
+
+ // Proposal is on stage 4, and included in ECMA-262 (https://github.com/tc39/proposal-export-ns-from)
+ // Need this since we are using TypeScript 3.9+
+ require.resolve('@babel/plugin-proposal-private-methods'),
+
+ // It enables the @babel/runtime so we can decrease the bundle sizes of the produced outputs
+ [
+ require.resolve('@babel/plugin-transform-runtime'),
+ {
+ version: '^7.12.5',
+ },
+ ],
+ ],
},
- ],
-];
-module.exports = {
- presets: [
- [require.resolve('@babel/preset-typescript'), { allowNamespaces: true }],
require.resolve('@babel/preset-react'),
+
+ [
+ require.resolve('@babel/preset-typescript'),
+ {
+ allowNamespaces: true,
+ allowDeclareFields: true,
+ },
+ ],
],
- plugins,
};
diff --git a/packages/kbn-optimizer/src/babel_runtime_helpers/find_babel_runtime_helpers_in_entry_bundles.ts b/packages/kbn-optimizer/src/babel_runtime_helpers/find_babel_runtime_helpers_in_entry_bundles.ts
index beff36023343d..f00905f3f4920 100644
--- a/packages/kbn-optimizer/src/babel_runtime_helpers/find_babel_runtime_helpers_in_entry_bundles.ts
+++ b/packages/kbn-optimizer/src/babel_runtime_helpers/find_babel_runtime_helpers_in_entry_bundles.ts
@@ -35,14 +35,14 @@ export async function runFindBabelHelpersInEntryBundlesCli() {
}
for (const { userRequest } of module.reasons) {
- if (userRequest.startsWith('@babel/runtime/')) {
+ if (userRequest.startsWith('@babel/runtime')) {
imports.add(userRequest);
}
}
}
}
- log.success('found', imports.size, '@babel/register imports in entry bundles');
+ log.success('found', imports.size, '@babel/runtime* imports in entry bundles');
log.write(
Array.from(imports, (i) => `'${i}',`)
.sort()
diff --git a/packages/kbn-optimizer/src/worker/emit_stats_plugin.ts b/packages/kbn-optimizer/src/worker/emit_stats_plugin.ts
index c964219e1fed6..5cb60344037fc 100644
--- a/packages/kbn-optimizer/src/worker/emit_stats_plugin.ts
+++ b/packages/kbn-optimizer/src/worker/emit_stats_plugin.ts
@@ -26,7 +26,7 @@ export class EmitStatsPlugin {
(stats) => {
Fs.writeFileSync(
Path.resolve(this.bundle.outputDir, 'stats.json'),
- JSON.stringify(stats.toJson())
+ JSON.stringify(stats.toJson(), null, 2)
);
}
);
diff --git a/packages/kbn-storybook/src/webpack.config.ts b/packages/kbn-storybook/src/webpack.config.ts
index 27e887eda65ce..53f9c82b86815 100644
--- a/packages/kbn-storybook/src/webpack.config.ts
+++ b/packages/kbn-storybook/src/webpack.config.ts
@@ -9,11 +9,13 @@
import { externals } from '@kbn/ui-shared-deps-src';
import { stringifyRequest } from 'loader-utils';
import { resolve } from 'path';
-import { Configuration, Stats } from 'webpack';
+import webpack, { Configuration, Stats } from 'webpack';
import webpackMerge from 'webpack-merge';
import { REPO_ROOT } from './lib/constants';
import { IgnoreNotFoundExportPlugin } from './ignore_not_found_export_plugin';
+type Preset = string | [string, Record] | Record;
+
const stats = {
...Stats.presetToOptions('minimal'),
colors: true,
@@ -22,6 +24,46 @@ const stats = {
moduleTrace: true,
};
+function isProgressPlugin(plugin: any) {
+ return 'handler' in plugin && plugin.showActiveModules && plugin.showModules;
+}
+
+function isHtmlPlugin(plugin: any): plugin is { options: { template: string } } {
+ return !!(typeof plugin.options?.template === 'string');
+}
+
+function isBabelLoaderRule(rule: webpack.RuleSetRule): rule is webpack.RuleSetRule & {
+ use: webpack.RuleSetLoader[];
+} {
+ return !!(
+ rule.use &&
+ Array.isArray(rule.use) &&
+ rule.use.some(
+ (l) =>
+ typeof l === 'object' && typeof l.loader === 'string' && l.loader.includes('babel-loader')
+ )
+ );
+}
+
+function getPresetPath(preset: Preset) {
+ if (typeof preset === 'string') return preset;
+ if (Array.isArray(preset)) return preset[0];
+ return undefined;
+}
+
+function getTsPreset(preset: Preset) {
+ if (getPresetPath(preset)?.includes('preset-typescript')) {
+ if (typeof preset === 'string') return [preset, {}];
+ if (Array.isArray(preset)) return preset;
+
+ throw new Error('unsupported preset-typescript format');
+ }
+}
+
+function isDesiredPreset(preset: Preset) {
+ return !getPresetPath(preset)?.includes('preset-flow');
+}
+
// Extend the Storybook Webpack config with some customizations
/* eslint-disable import/no-default-export */
export default function ({ config: storybookConfig }: { config: Configuration }) {
@@ -83,21 +125,72 @@ export default function ({ config: storybookConfig }: { config: Configuration })
stats,
};
- // Disable the progress plugin
- const progressPlugin: any = (storybookConfig.plugins || []).find((plugin: any) => {
- return 'handler' in plugin && plugin.showActiveModules && plugin.showModules;
- });
- progressPlugin.handler = () => {};
-
- // This is the hacky part. We find something that looks like the
- // HtmlWebpackPlugin and mutate its `options.template` to point at our
- // revised template.
- const htmlWebpackPlugin: any = (storybookConfig.plugins || []).find((plugin: any) => {
- return plugin.options && typeof plugin.options.template === 'string';
- });
- if (htmlWebpackPlugin) {
- htmlWebpackPlugin.options.template = require.resolve('../templates/index.ejs');
+ const updatedModuleRules = [];
+ // clone and modify the module.rules config provided by storybook so that the default babel plugins run after the typescript preset
+ for (const originalRule of storybookConfig.module?.rules ?? []) {
+ const rule = { ...originalRule };
+ updatedModuleRules.push(rule);
+
+ if (isBabelLoaderRule(rule)) {
+ rule.use = [...rule.use];
+ const loader = (rule.use[0] = { ...rule.use[0] });
+ const options = (loader.options = { ...(loader.options as Record) });
+
+ // capture the plugins defined at the root level
+ const plugins: string[] = options.plugins;
+ options.plugins = [];
+
+ // move the plugins to the top of the preset array so they will run after the typescript preset
+ options.presets = [
+ {
+ plugins,
+ },
+ ...(options.presets as Preset[]).filter(isDesiredPreset).map((preset) => {
+ const tsPreset = getTsPreset(preset);
+ if (!tsPreset) {
+ return preset;
+ }
+
+ return [
+ tsPreset[0],
+ {
+ ...tsPreset[1],
+ allowNamespaces: true,
+ allowDeclareFields: true,
+ },
+ ];
+ }),
+ ];
+ }
}
- return webpackMerge(storybookConfig, config);
+ // copy and modify the webpack plugins added by storybook
+ const filteredStorybookPlugins = [];
+ for (const plugin of storybookConfig.plugins ?? []) {
+ // Remove the progress plugin
+ if (isProgressPlugin(plugin)) {
+ continue;
+ }
+
+ // This is the hacky part. We find something that looks like the
+ // HtmlWebpackPlugin and mutate its `options.template` to point at our
+ // revised template.
+ if (isHtmlPlugin(plugin)) {
+ plugin.options.template = require.resolve('../templates/index.ejs');
+ }
+
+ filteredStorybookPlugins.push(plugin);
+ }
+
+ return webpackMerge(
+ {
+ ...storybookConfig,
+ plugins: filteredStorybookPlugins,
+ module: {
+ ...storybookConfig.module,
+ rules: updatedModuleRules,
+ },
+ },
+ config
+ );
}
diff --git a/src/plugins/console/public/services/history.ts b/src/plugins/console/public/services/history.ts
index ee1e97ceb386e..972e5283274de 100644
--- a/src/plugins/console/public/services/history.ts
+++ b/src/plugins/console/public/services/history.ts
@@ -14,9 +14,11 @@ const MAX_NUMBER_OF_HISTORY_ITEMS = 100;
export const isQuotaExceededError = (e: Error): boolean => e.name === 'QuotaExceededError';
export class History {
- constructor(private readonly storage: Storage) {}
+ private changeEmitter: BehaviorSubject;
- private changeEmitter = new BehaviorSubject(this.getHistory() || []);
+ constructor(private readonly storage: Storage) {
+ this.changeEmitter = new BehaviorSubject(this.getHistory() || []);
+ }
getHistoryKeys() {
return this.storage
diff --git a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx
index 611a426dd4d71..1e19e495585fe 100644
--- a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx
@@ -32,7 +32,7 @@ interface State {
export class DashboardViewport extends React.Component {
static contextType = context;
- public readonly context!: DashboardReactContextValue;
+ public declare readonly context: DashboardReactContextValue;
private controlsRoot: React.RefObject;
diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx
index 007c3e306372e..1601ea481cf2d 100644
--- a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx
+++ b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx
@@ -104,7 +104,7 @@ describe('rolesManagementApp', () => {
expect(docTitle.reset).not.toHaveBeenCalled();
expect(container).toMatchInlineSnapshot(`
- Role Edit Page: {"action":"edit","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}},"fieldCache":{}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit","search":"","hash":""}}}
+ Role Edit Page: {"action":"edit","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit","search":"","hash":""}}}
`);
@@ -129,7 +129,7 @@ describe('rolesManagementApp', () => {
expect(docTitle.reset).not.toHaveBeenCalled();
expect(container).toMatchInlineSnapshot(`
- Role Edit Page: {"action":"edit","roleName":"role@name","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}},"fieldCache":{}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/role@name","search":"","hash":""}}}
+ Role Edit Page: {"action":"edit","roleName":"role@name","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/role@name","search":"","hash":""}}}
`);
@@ -154,7 +154,7 @@ describe('rolesManagementApp', () => {
expect(docTitle.reset).not.toHaveBeenCalled();
expect(container).toMatchInlineSnapshot(`
- Role Edit Page: {"action":"clone","roleName":"someRoleName","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}},"fieldCache":{}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/clone/someRoleName","search":"","hash":""}}}
+ Role Edit Page: {"action":"clone","roleName":"someRoleName","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/clone/someRoleName","search":"","hash":""}}}
`);
From 57ae8db66a53a87c976e67d82a297baf3857f1c1 Mon Sep 17 00:00:00 2001
From: Ryland Herrick
Date: Mon, 29 Nov 2021 12:39:55 -0600
Subject: [PATCH 22/47] [RAC,Security Solution]Update alerts mappings to ECS
1.12 (#118812)
* Update output directory for generative script
These files were moved in #98935 but the script has become out of date.
* Update ECS fieldmap with ECS 1.12
This fieldmap was missing fields from ECS 1.11+. Notable ommissions were
the threat.indicator and threat.enrichments fieldsets.
* Remove non-additive mappings changes
These are incompatible with the current alerts framework.
* Add only necessary threat fields for CTI features
This could probably be pared down further, as most of these fields are
not critical for CTI features. Additionally, these additions now exceed
the limit of 1000 fields and is causing an error in the ruleRegistry
bootstrapping.
* Remove file.pe threat fields
* Remove geo threat indicator fields
* Remove all threat.indicator mappings
These are not relevant for alerts, which will only have enrichments.
* increments index mappings total fields limit to 1200
Co-authored-by: Ece Ozalp
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../common/assets/field_maps/ecs_field_map.ts | 420 ++++++++++++++++++
.../scripts/generate_ecs_fieldmap/index.js | 2 +-
.../resource_installer.ts | 2 +-
3 files changed, 422 insertions(+), 2 deletions(-)
diff --git a/x-pack/plugins/rule_registry/common/assets/field_maps/ecs_field_map.ts b/x-pack/plugins/rule_registry/common/assets/field_maps/ecs_field_map.ts
index 859070bd498e3..1ea85e5a5434e 100644
--- a/x-pack/plugins/rule_registry/common/assets/field_maps/ecs_field_map.ts
+++ b/x-pack/plugins/rule_registry/common/assets/field_maps/ecs_field_map.ts
@@ -2550,6 +2550,426 @@ export const ecsFieldMap = {
array: false,
required: false,
},
+ 'threat.enrichments': {
+ type: 'nested',
+ array: true,
+ required: false,
+ },
+ 'threat.enrichments.indicator': {
+ type: 'object',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.as.number': {
+ type: 'long',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.as.organization.name': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.confidence': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.description': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.email.address': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.accessed': {
+ type: 'date',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.attributes': {
+ type: 'keyword',
+ array: true,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.code_signature.digest_algorithm': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.code_signature.exists': {
+ type: 'boolean',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.code_signature.signing_id': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.code_signature.status': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.code_signature.subject_name': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.code_signature.team_id': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.code_signature.timestamp': {
+ type: 'date',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.code_signature.trusted': {
+ type: 'boolean',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.code_signature.valid': {
+ type: 'boolean',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.created': {
+ type: 'date',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.ctime': {
+ type: 'date',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.device': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.directory': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.drive_letter': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.extension': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.fork_name': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.gid': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.group': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.hash.md5': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.hash.sha1': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.hash.sha256': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.hash.sha512': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.hash.ssdeep': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.inode': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.mime_type': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.mode': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.mtime': {
+ type: 'date',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.name': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.owner': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.path': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.size': {
+ type: 'long',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.target_path': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.type': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.file.uid': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.first_seen': {
+ type: 'date',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.ip': {
+ type: 'ip',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.last_seen': {
+ type: 'date',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.marking.tlp': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.modified_at': {
+ type: 'date',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.port': {
+ type: 'long',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.provider': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.reference': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.registry.data.bytes': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.registry.data.strings': {
+ type: 'wildcard',
+ array: true,
+ required: false,
+ },
+ 'threat.enrichments.indicator.registry.data.type': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.registry.hive': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.registry.key': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.registry.path': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.registry.value': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.scanner_stats': {
+ type: 'long',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.sightings': {
+ type: 'long',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.type': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.url.domain': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.url.extension': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.url.fragment': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.url.full': {
+ type: 'wildcard',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.url.original': {
+ type: 'wildcard',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.url.password': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.url.path': {
+ type: 'wildcard',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.url.port': {
+ type: 'long',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.url.query': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.url.registered_domain': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.url.scheme': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.url.subdomain': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.url.top_level_domain': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.indicator.url.username': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.matched.atomic': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.matched.field': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.matched.id': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.matched.index': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.enrichments.matched.type': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.group.alias': {
+ type: 'keyword',
+ array: true,
+ required: false,
+ },
+ 'threat.group.id': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.group.name': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
+ 'threat.group.reference': {
+ type: 'keyword',
+ array: false,
+ required: false,
+ },
'threat.tactic.id': {
type: 'keyword',
array: true,
diff --git a/x-pack/plugins/rule_registry/scripts/generate_ecs_fieldmap/index.js b/x-pack/plugins/rule_registry/scripts/generate_ecs_fieldmap/index.js
index 6b10ca5f837d5..bbcf651bd6d69 100644
--- a/x-pack/plugins/rule_registry/scripts/generate_ecs_fieldmap/index.js
+++ b/x-pack/plugins/rule_registry/scripts/generate_ecs_fieldmap/index.js
@@ -19,7 +19,7 @@ const exec = util.promisify(execCb);
const ecsDir = path.resolve(__dirname, '../../../../../../ecs');
const ecsYamlFilename = path.join(ecsDir, 'generated/ecs/ecs_flat.yml');
-const outputDir = path.join(__dirname, '../../common/field_map');
+const outputDir = path.join(__dirname, '../../common/assets/field_maps');
const outputFieldMapFilename = path.join(outputDir, 'ecs_field_map.ts');
diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts
index bfdec28a50987..bbfa17c5694f1 100644
--- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts
+++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts
@@ -316,7 +316,7 @@ export class ResourceInstaller {
// @ts-expect-error
rollover_alias: primaryNamespacedAlias,
},
- 'index.mapping.total_fields.limit': 1100,
+ 'index.mapping.total_fields.limit': 1200,
},
mappings: {
dynamic: false,
From 2a0312cd48704c2bf76fa0ca3289211e7d57f263 Mon Sep 17 00:00:00 2001
From: Ersin Erdal <92688503+ersin-erdal@users.noreply.github.com>
Date: Mon, 29 Nov 2021 19:44:17 +0100
Subject: [PATCH 23/47] 119061 refactor observability (#119211)
* group containers and components, create index files
---
x-pack/plugins/observability/public/index.ts | 4 +-
.../{ => components}/alerts_disclaimer.tsx | 0
.../alerts_flyout/alerts_flyout.stories.tsx | 10 ++---
.../alerts_flyout/alerts_flyout.test.tsx | 10 ++---
.../alerts_flyout/alerts_flyout.tsx} | 14 +++----
.../alerts_flyout}/example_data.ts | 0
.../alerts/components/alerts_flyout/index.ts | 8 ++++
.../{ => components}/alerts_search_bar.tsx | 4 +-
.../{ => components}/alerts_status_filter.tsx | 4 +-
.../{ => components}/default_cell_actions.tsx | 6 +--
.../{ => components}/filter_for_value.tsx | 0
.../public/pages/alerts/components/index.ts | 17 +++++++++
.../alerts/{ => components}/parse_alert.ts | 8 ++--
.../components/render_cell_value/index.ts | 8 ++++
.../render_cell_value.test.tsx | 8 ++--
.../render_cell_value}/render_cell_value.tsx | 16 ++++----
.../alerts/components/severity_badge/index.ts | 8 ++++
.../severity_badge.stories.tsx | 0
.../severity_badge}/severity_badge.tsx | 0
.../workflow_status_filter/index.ts | 8 ++++
.../workflow_status_filter.stories.tsx | 2 +-
.../workflow_status_filter.test.tsx | 2 +-
.../workflow_status_filter.tsx | 2 +-
.../alerts_page/alerts_page.tsx} | 38 +++++++++----------
.../alerts/containers/alerts_page/index.ts | 9 +++++
.../{ => containers/alerts_page}/styles.scss | 0
.../alerts_table_t_grid.tsx | 28 +++++++-------
.../containers/alerts_table_t_grid/index.ts | 8 ++++
.../public/pages/alerts/containers/index.ts | 10 +++++
.../state_container/index.tsx | 0
.../state_container/state_container.tsx | 4 +-
.../use_alerts_page_state_container.tsx | 6 +--
.../public/pages/alerts/index.ts | 9 +++++
.../public/pages/cases/helpers.ts | 4 +-
.../observability/public/routes/index.tsx | 2 +-
35 files changed, 171 insertions(+), 86 deletions(-)
rename x-pack/plugins/observability/public/pages/alerts/{ => components}/alerts_disclaimer.tsx (100%)
rename x-pack/plugins/observability/public/pages/alerts/{ => components}/alerts_flyout/alerts_flyout.stories.tsx (85%)
rename x-pack/plugins/observability/public/pages/alerts/{ => components}/alerts_flyout/alerts_flyout.test.tsx (91%)
rename x-pack/plugins/observability/public/pages/alerts/{alerts_flyout/index.tsx => components/alerts_flyout/alerts_flyout.tsx} (89%)
rename x-pack/plugins/observability/public/pages/alerts/{ => components/alerts_flyout}/example_data.ts (100%)
create mode 100644 x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/index.ts
rename x-pack/plugins/observability/public/pages/alerts/{ => components}/alerts_search_bar.tsx (92%)
rename x-pack/plugins/observability/public/pages/alerts/{ => components}/alerts_status_filter.tsx (94%)
rename x-pack/plugins/observability/public/pages/alerts/{ => components}/default_cell_actions.tsx (85%)
rename x-pack/plugins/observability/public/pages/alerts/{ => components}/filter_for_value.tsx (100%)
create mode 100644 x-pack/plugins/observability/public/pages/alerts/components/index.ts
rename x-pack/plugins/observability/public/pages/alerts/{ => components}/parse_alert.ts (78%)
create mode 100644 x-pack/plugins/observability/public/pages/alerts/components/render_cell_value/index.ts
rename x-pack/plugins/observability/public/pages/alerts/{ => components/render_cell_value}/render_cell_value.test.tsx (87%)
rename x-pack/plugins/observability/public/pages/alerts/{ => components/render_cell_value}/render_cell_value.tsx (86%)
create mode 100644 x-pack/plugins/observability/public/pages/alerts/components/severity_badge/index.ts
rename x-pack/plugins/observability/public/pages/alerts/{ => components/severity_badge}/severity_badge.stories.tsx (100%)
rename x-pack/plugins/observability/public/pages/alerts/{ => components/severity_badge}/severity_badge.tsx (100%)
create mode 100644 x-pack/plugins/observability/public/pages/alerts/components/workflow_status_filter/index.ts
rename x-pack/plugins/observability/public/pages/alerts/{ => components/workflow_status_filter}/workflow_status_filter.stories.tsx (92%)
rename x-pack/plugins/observability/public/pages/alerts/{ => components/workflow_status_filter}/workflow_status_filter.test.tsx (95%)
rename x-pack/plugins/observability/public/pages/alerts/{ => components/workflow_status_filter}/workflow_status_filter.tsx (95%)
rename x-pack/plugins/observability/public/pages/alerts/{index.tsx => containers/alerts_page/alerts_page.tsx} (87%)
create mode 100644 x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/index.ts
rename x-pack/plugins/observability/public/pages/alerts/{ => containers/alerts_page}/styles.scss (100%)
rename x-pack/plugins/observability/public/pages/alerts/{ => containers/alerts_table_t_grid}/alerts_table_t_grid.tsx (94%)
create mode 100644 x-pack/plugins/observability/public/pages/alerts/containers/alerts_table_t_grid/index.ts
create mode 100644 x-pack/plugins/observability/public/pages/alerts/containers/index.ts
rename x-pack/plugins/observability/public/pages/alerts/{ => containers}/state_container/index.tsx (100%)
rename x-pack/plugins/observability/public/pages/alerts/{ => containers}/state_container/state_container.tsx (92%)
rename x-pack/plugins/observability/public/pages/alerts/{ => containers}/state_container/use_alerts_page_state_container.tsx (92%)
create mode 100644 x-pack/plugins/observability/public/pages/alerts/index.ts
diff --git a/x-pack/plugins/observability/public/index.ts b/x-pack/plugins/observability/public/index.ts
index 7646ac9bec9bb..2383044bc14c2 100644
--- a/x-pack/plugins/observability/public/index.ts
+++ b/x-pack/plugins/observability/public/index.ts
@@ -64,7 +64,9 @@ export {
METRIC_TYPE,
} from './hooks/use_track_metric';
-export const LazyAlertsFlyout = lazy(() => import('./pages/alerts/alerts_flyout'));
+export const LazyAlertsFlyout = lazy(
+ () => import('./pages/alerts/components/alerts_flyout/alerts_flyout')
+);
export { useFetcher, FETCH_STATUS } from './hooks/use_fetcher';
export { useEsSearch, createEsParams } from './hooks/use_es_search';
diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_disclaimer.tsx b/x-pack/plugins/observability/public/pages/alerts/components/alerts_disclaimer.tsx
similarity index 100%
rename from x-pack/plugins/observability/public/pages/alerts/alerts_disclaimer.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/alerts_disclaimer.tsx
diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_flyout/alerts_flyout.stories.tsx b/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout.stories.tsx
similarity index 85%
rename from x-pack/plugins/observability/public/pages/alerts/alerts_flyout/alerts_flyout.stories.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout.stories.tsx
index 64d495dbbc798..36b1fc2f2b6e2 100644
--- a/x-pack/plugins/observability/public/pages/alerts/alerts_flyout/alerts_flyout.stories.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout.stories.tsx
@@ -7,11 +7,11 @@
import { ALERT_UUID } from '@kbn/rule-data-utils/technical_field_names';
import React, { ComponentType } from 'react';
-import { KibanaContextProvider } from '../../../../../../../src/plugins/kibana_react/public';
-import { PluginContext, PluginContextValue } from '../../../context/plugin_context';
-import { createObservabilityRuleTypeRegistryMock } from '../../../rules/observability_rule_type_registry_mock';
-import { apmAlertResponseExample } from '../example_data';
-import { AlertsFlyout } from './';
+import { KibanaContextProvider } from '../../../../../../../../src/plugins/kibana_react/public';
+import { PluginContext, PluginContextValue } from '../../../../context/plugin_context';
+import { createObservabilityRuleTypeRegistryMock } from '../../../../rules/observability_rule_type_registry_mock';
+import { apmAlertResponseExample } from './example_data';
+import { AlertsFlyout } from '..';
interface Args {
alerts: Array>;
diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_flyout/alerts_flyout.test.tsx b/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout.test.tsx
similarity index 91%
rename from x-pack/plugins/observability/public/pages/alerts/alerts_flyout/alerts_flyout.test.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout.test.tsx
index 4fdc8d245799a..13fb5d805fb81 100644
--- a/x-pack/plugins/observability/public/pages/alerts/alerts_flyout/alerts_flyout.test.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout.test.tsx
@@ -6,11 +6,11 @@
*/
import React from 'react';
-import * as useUiSettingHook from '../../../../../../../src/plugins/kibana_react/public/ui_settings/use_ui_setting';
-import { createObservabilityRuleTypeRegistryMock } from '../../../rules/observability_rule_type_registry_mock';
-import { render } from '../../../utils/test_helper';
-import type { TopAlert } from '../';
-import { AlertsFlyout } from './';
+import * as useUiSettingHook from '../../../../../../../../src/plugins/kibana_react/public/ui_settings/use_ui_setting';
+import { createObservabilityRuleTypeRegistryMock } from '../../../../rules/observability_rule_type_registry_mock';
+import { render } from '../../../../utils/test_helper';
+import type { TopAlert } from '../../containers/alerts_page';
+import { AlertsFlyout } from '..';
describe('AlertsFlyout', () => {
jest
diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_flyout/index.tsx b/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout.tsx
similarity index 89%
rename from x-pack/plugins/observability/public/pages/alerts/alerts_flyout/index.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout.tsx
index c5cad5f3b1c8c..ced4896c5f31d 100644
--- a/x-pack/plugins/observability/public/pages/alerts/alerts_flyout/index.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout.tsx
@@ -35,14 +35,14 @@ import {
} from '@kbn/rule-data-utils/alerts_as_data_status';
import moment from 'moment-timezone';
import React, { useMemo } from 'react';
-import type { TopAlert } from '../';
-import { useKibana, useUiSetting } from '../../../../../../../src/plugins/kibana_react/public';
-import { asDuration } from '../../../../common/utils/formatters';
-import type { ObservabilityRuleTypeRegistry } from '../../../rules/create_observability_rule_type_registry';
+import type { TopAlert } from '../../containers';
+import { useKibana, useUiSetting } from '../../../../../../../../src/plugins/kibana_react/public';
+import { asDuration } from '../../../../../common/utils/formatters';
+import type { ObservabilityRuleTypeRegistry } from '../../../../rules/create_observability_rule_type_registry';
import { parseAlert } from '../parse_alert';
-import { AlertStatusIndicator } from '../../../components/shared/alert_status_indicator';
-import { ExperimentalBadge } from '../../../components/shared/experimental_badge';
-import { translations, paths } from '../../../config';
+import { AlertStatusIndicator } from '../../../../components/shared/alert_status_indicator';
+import { ExperimentalBadge } from '../../../../components/shared/experimental_badge';
+import { translations, paths } from '../../../../config';
type AlertsFlyoutProps = {
alert?: TopAlert;
diff --git a/x-pack/plugins/observability/public/pages/alerts/example_data.ts b/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/example_data.ts
similarity index 100%
rename from x-pack/plugins/observability/public/pages/alerts/example_data.ts
rename to x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/example_data.ts
diff --git a/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/index.ts b/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/index.ts
new file mode 100644
index 0000000000000..4153ab6e5b596
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/index.ts
@@ -0,0 +1,8 @@
+/*
+ * 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 { AlertsFlyout } from './alerts_flyout';
diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_search_bar.tsx b/x-pack/plugins/observability/public/pages/alerts/components/alerts_search_bar.tsx
similarity index 92%
rename from x-pack/plugins/observability/public/pages/alerts/alerts_search_bar.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/alerts_search_bar.tsx
index 926f03acf01d8..14d47d1e7e9d3 100644
--- a/x-pack/plugins/observability/public/pages/alerts/alerts_search_bar.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/components/alerts_search_bar.tsx
@@ -8,8 +8,8 @@
import { IndexPatternBase } from '@kbn/es-query';
import { i18n } from '@kbn/i18n';
import React, { useMemo, useState } from 'react';
-import { SearchBar, TimeHistory } from '../../../../../../src/plugins/data/public';
-import { Storage } from '../../../../../../src/plugins/kibana_utils/public';
+import { SearchBar, TimeHistory } from '../../../../../../../src/plugins/data/public';
+import { Storage } from '../../../../../../../src/plugins/kibana_utils/public';
export function AlertsSearchBar({
dynamicIndexPatterns,
diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx b/x-pack/plugins/observability/public/pages/alerts/components/alerts_status_filter.tsx
similarity index 94%
rename from x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/alerts_status_filter.tsx
index 38c753bbebf3b..d717e916de2c6 100644
--- a/x-pack/plugins/observability/public/pages/alerts/alerts_status_filter.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/components/alerts_status_filter.tsx
@@ -13,8 +13,8 @@ import {
ALERT_STATUS_RECOVERED,
} from '@kbn/rule-data-utils/alerts_as_data_status';
import { ALERT_STATUS } from '@kbn/rule-data-utils/technical_field_names';
-import { AlertStatusFilterButton } from '../../../common/typings';
-import { AlertStatusFilter } from '../../../common/typings';
+import { AlertStatusFilterButton } from '../../../../common/typings';
+import { AlertStatusFilter } from '../../../../common/typings';
export interface AlertStatusFilterProps {
status: AlertStatusFilterButton;
diff --git a/x-pack/plugins/observability/public/pages/alerts/default_cell_actions.tsx b/x-pack/plugins/observability/public/pages/alerts/components/default_cell_actions.tsx
similarity index 85%
rename from x-pack/plugins/observability/public/pages/alerts/default_cell_actions.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/default_cell_actions.tsx
index 3adfb0a1d9c89..5126647161fa5 100644
--- a/x-pack/plugins/observability/public/pages/alerts/default_cell_actions.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/components/default_cell_actions.tsx
@@ -9,9 +9,9 @@ import React from 'react';
import { i18n } from '@kbn/i18n';
import { getMappedNonEcsValue } from './render_cell_value';
import FilterForValueButton from './filter_for_value';
-import { TimelineNonEcsData } from '../../../../timelines/common/search_strategy';
-import { TGridCellAction } from '../../../../timelines/common/types/timeline';
-import { getPageRowIndex } from '../../../../timelines/public';
+import { TimelineNonEcsData } from '../../../../../timelines/common/search_strategy';
+import { TGridCellAction } from '../../../../../timelines/common/types/timeline';
+import { getPageRowIndex } from '../../../../../timelines/public';
export const FILTER_FOR_VALUE = i18n.translate('xpack.observability.hoverActions.filterForValue', {
defaultMessage: 'Filter for value',
diff --git a/x-pack/plugins/observability/public/pages/alerts/filter_for_value.tsx b/x-pack/plugins/observability/public/pages/alerts/components/filter_for_value.tsx
similarity index 100%
rename from x-pack/plugins/observability/public/pages/alerts/filter_for_value.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/filter_for_value.tsx
diff --git a/x-pack/plugins/observability/public/pages/alerts/components/index.ts b/x-pack/plugins/observability/public/pages/alerts/components/index.ts
new file mode 100644
index 0000000000000..57ad311f65d1c
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/alerts/components/index.ts
@@ -0,0 +1,17 @@
+/*
+ * 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 * from './alerts_flyout';
+export * from './render_cell_value';
+export * from './severity_badge';
+export * from './workflow_status_filter';
+export * from './alerts_search_bar';
+export * from './alerts_disclaimer';
+export * from './default_cell_actions';
+export * from './filter_for_value';
+export * from './parse_alert';
+export * from './alerts_status_filter';
diff --git a/x-pack/plugins/observability/public/pages/alerts/parse_alert.ts b/x-pack/plugins/observability/public/pages/alerts/components/parse_alert.ts
similarity index 78%
rename from x-pack/plugins/observability/public/pages/alerts/parse_alert.ts
rename to x-pack/plugins/observability/public/pages/alerts/components/parse_alert.ts
index 7b28803084067..680798811e9ab 100644
--- a/x-pack/plugins/observability/public/pages/alerts/parse_alert.ts
+++ b/x-pack/plugins/observability/public/pages/alerts/components/parse_alert.ts
@@ -12,10 +12,10 @@ import {
ALERT_RULE_NAME,
} from '@kbn/rule-data-utils/technical_field_names';
import { ALERT_STATUS_ACTIVE } from '@kbn/rule-data-utils/alerts_as_data_status';
-import type { TopAlert } from '.';
-import { parseTechnicalFields } from '../../../../rule_registry/common/parse_technical_fields';
-import { asDuration, asPercent } from '../../../common/utils/formatters';
-import { ObservabilityRuleTypeRegistry } from '../../rules/create_observability_rule_type_registry';
+import type { TopAlert } from '../';
+import { parseTechnicalFields } from '../../../../../rule_registry/common/parse_technical_fields';
+import { asDuration, asPercent } from '../../../../common/utils/formatters';
+import { ObservabilityRuleTypeRegistry } from '../../../rules/create_observability_rule_type_registry';
export const parseAlert =
(observabilityRuleTypeRegistry: ObservabilityRuleTypeRegistry) =>
diff --git a/x-pack/plugins/observability/public/pages/alerts/components/render_cell_value/index.ts b/x-pack/plugins/observability/public/pages/alerts/components/render_cell_value/index.ts
new file mode 100644
index 0000000000000..b6df77f075888
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/alerts/components/render_cell_value/index.ts
@@ -0,0 +1,8 @@
+/*
+ * 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 { getRenderCellValue, getMappedNonEcsValue } from './render_cell_value';
diff --git a/x-pack/plugins/observability/public/pages/alerts/render_cell_value.test.tsx b/x-pack/plugins/observability/public/pages/alerts/components/render_cell_value/render_cell_value.test.tsx
similarity index 87%
rename from x-pack/plugins/observability/public/pages/alerts/render_cell_value.test.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/render_cell_value/render_cell_value.test.tsx
index 79a27faa96c69..25de2e36b08c3 100644
--- a/x-pack/plugins/observability/public/pages/alerts/render_cell_value.test.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/components/render_cell_value/render_cell_value.test.tsx
@@ -10,10 +10,10 @@ import {
ALERT_STATUS_RECOVERED,
} from '@kbn/rule-data-utils/alerts_as_data_status';
import { ALERT_STATUS } from '@kbn/rule-data-utils/technical_field_names';
-import type { CellValueElementProps } from '../../../../timelines/common';
-import { createObservabilityRuleTypeRegistryMock } from '../../rules/observability_rule_type_registry_mock';
-import * as PluginHook from '../../hooks/use_plugin_context';
-import { render } from '../../utils/test_helper';
+import type { CellValueElementProps } from '../../../../../../timelines/common';
+import { createObservabilityRuleTypeRegistryMock } from '../../../../rules/observability_rule_type_registry_mock';
+import * as PluginHook from '../../../../hooks/use_plugin_context';
+import { render } from '../../../../utils/test_helper';
import { getRenderCellValue } from './render_cell_value';
interface AlertsTableRow {
diff --git a/x-pack/plugins/observability/public/pages/alerts/render_cell_value.tsx b/x-pack/plugins/observability/public/pages/alerts/components/render_cell_value/render_cell_value.tsx
similarity index 86%
rename from x-pack/plugins/observability/public/pages/alerts/render_cell_value.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/render_cell_value/render_cell_value.tsx
index 80ccd4a69b281..d9fa6c6e2221b 100644
--- a/x-pack/plugins/observability/public/pages/alerts/render_cell_value.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/components/render_cell_value/render_cell_value.tsx
@@ -17,14 +17,14 @@ import {
ALERT_STATUS_ACTIVE,
ALERT_STATUS_RECOVERED,
} from '@kbn/rule-data-utils/alerts_as_data_status';
-import type { CellValueElementProps, TimelineNonEcsData } from '../../../../timelines/common';
-import { AlertStatusIndicator } from '../../components/shared/alert_status_indicator';
-import { TimestampTooltip } from '../../components/shared/timestamp_tooltip';
-import { asDuration } from '../../../common/utils/formatters';
-import { SeverityBadge } from './severity_badge';
-import { TopAlert } from '.';
-import { parseAlert } from './parse_alert';
-import { usePluginContext } from '../../hooks/use_plugin_context';
+import type { CellValueElementProps, TimelineNonEcsData } from '../../../../../../timelines/common';
+import { AlertStatusIndicator } from '../../../../components/shared/alert_status_indicator';
+import { TimestampTooltip } from '../../../../components/shared/timestamp_tooltip';
+import { asDuration } from '../../../../../common/utils/formatters';
+import { SeverityBadge } from '../severity_badge';
+import { TopAlert } from '../../';
+import { parseAlert } from '../parse_alert';
+import { usePluginContext } from '../../../../hooks/use_plugin_context';
export const getMappedNonEcsValue = ({
data,
diff --git a/x-pack/plugins/observability/public/pages/alerts/components/severity_badge/index.ts b/x-pack/plugins/observability/public/pages/alerts/components/severity_badge/index.ts
new file mode 100644
index 0000000000000..7974156327085
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/alerts/components/severity_badge/index.ts
@@ -0,0 +1,8 @@
+/*
+ * 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 { SeverityBadge } from './severity_badge';
diff --git a/x-pack/plugins/observability/public/pages/alerts/severity_badge.stories.tsx b/x-pack/plugins/observability/public/pages/alerts/components/severity_badge/severity_badge.stories.tsx
similarity index 100%
rename from x-pack/plugins/observability/public/pages/alerts/severity_badge.stories.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/severity_badge/severity_badge.stories.tsx
diff --git a/x-pack/plugins/observability/public/pages/alerts/severity_badge.tsx b/x-pack/plugins/observability/public/pages/alerts/components/severity_badge/severity_badge.tsx
similarity index 100%
rename from x-pack/plugins/observability/public/pages/alerts/severity_badge.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/severity_badge/severity_badge.tsx
diff --git a/x-pack/plugins/observability/public/pages/alerts/components/workflow_status_filter/index.ts b/x-pack/plugins/observability/public/pages/alerts/components/workflow_status_filter/index.ts
new file mode 100644
index 0000000000000..84badecd29dcd
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/alerts/components/workflow_status_filter/index.ts
@@ -0,0 +1,8 @@
+/*
+ * 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 { WorkflowStatusFilter } from './workflow_status_filter';
diff --git a/x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.stories.tsx b/x-pack/plugins/observability/public/pages/alerts/components/workflow_status_filter/workflow_status_filter.stories.tsx
similarity index 92%
rename from x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.stories.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/workflow_status_filter/workflow_status_filter.stories.tsx
index e06b5d333a9a6..4dce3ee80b833 100644
--- a/x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.stories.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/components/workflow_status_filter/workflow_status_filter.stories.tsx
@@ -6,7 +6,7 @@
*/
import React, { ComponentProps, useState } from 'react';
-import type { AlertWorkflowStatus } from '../../../common/typings';
+import type { AlertWorkflowStatus } from '../../../../../common/typings';
import { WorkflowStatusFilter } from './workflow_status_filter';
type Args = ComponentProps;
diff --git a/x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.test.tsx b/x-pack/plugins/observability/public/pages/alerts/components/workflow_status_filter/workflow_status_filter.test.tsx
similarity index 95%
rename from x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.test.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/workflow_status_filter/workflow_status_filter.test.tsx
index 29c5e88788a89..a9819a6619dc5 100644
--- a/x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.test.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/components/workflow_status_filter/workflow_status_filter.test.tsx
@@ -8,7 +8,7 @@
import { render } from '@testing-library/react';
import { Simulate } from 'react-dom/test-utils';
import React from 'react';
-import type { AlertWorkflowStatus } from '../../../common/typings';
+import type { AlertWorkflowStatus } from '../../../../../common/typings';
import { WorkflowStatusFilter } from './workflow_status_filter';
describe('StatusFilter', () => {
diff --git a/x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.tsx b/x-pack/plugins/observability/public/pages/alerts/components/workflow_status_filter/workflow_status_filter.tsx
similarity index 95%
rename from x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.tsx
rename to x-pack/plugins/observability/public/pages/alerts/components/workflow_status_filter/workflow_status_filter.tsx
index d857b9d6bd650..86116fb969682 100644
--- a/x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/components/workflow_status_filter/workflow_status_filter.tsx
@@ -8,7 +8,7 @@
import { EuiButtonGroup, EuiButtonGroupOptionProps } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
-import type { AlertWorkflowStatus } from '../../../common/typings';
+import type { AlertWorkflowStatus } from '../../../../../common/typings';
export interface WorkflowStatusFilterProps {
status: AlertWorkflowStatus;
diff --git a/x-pack/plugins/observability/public/pages/alerts/index.tsx b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx
similarity index 87%
rename from x-pack/plugins/observability/public/pages/alerts/index.tsx
rename to x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx
index 2636463bcfd7a..b19a1dbe86fe1 100644
--- a/x-pack/plugins/observability/public/pages/alerts/index.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx
@@ -14,23 +14,25 @@ import useAsync from 'react-use/lib/useAsync';
import { AlertStatus } from '@kbn/rule-data-utils/alerts_as_data_status';
import { ALERT_STATUS } from '@kbn/rule-data-utils/technical_field_names';
-import { AlertStatusFilterButton } from '../../../common/typings';
-import { ParsedTechnicalFields } from '../../../../rule_registry/common/parse_technical_fields';
-import { ExperimentalBadge } from '../../components/shared/experimental_badge';
-import { useBreadcrumbs } from '../../hooks/use_breadcrumbs';
-import { useFetcher } from '../../hooks/use_fetcher';
-import { useHasData } from '../../hooks/use_has_data';
-import { usePluginContext } from '../../hooks/use_plugin_context';
-import { useTimefilterService } from '../../hooks/use_timefilter_service';
-import { callObservabilityApi } from '../../services/call_observability_api';
-import { getNoDataConfig } from '../../utils/no_data_config';
-import { LoadingObservability } from '../overview/loading_observability';
-import { AlertsSearchBar } from './alerts_search_bar';
-import { AlertsTableTGrid } from './alerts_table_t_grid';
-import { Provider, alertsPageStateContainer, useAlertsPageStateContainer } from './state_container';
+import { AlertStatusFilterButton } from '../../../../../common/typings';
+import { ParsedTechnicalFields } from '../../../../../../rule_registry/common/parse_technical_fields';
+import { ExperimentalBadge } from '../../../../components/shared/experimental_badge';
+import { useBreadcrumbs } from '../../../../hooks/use_breadcrumbs';
+import { useFetcher } from '../../../../hooks/use_fetcher';
+import { useHasData } from '../../../../hooks/use_has_data';
+import { usePluginContext } from '../../../../hooks/use_plugin_context';
+import { useTimefilterService } from '../../../../hooks/use_timefilter_service';
+import { callObservabilityApi } from '../../../../services/call_observability_api';
+import { getNoDataConfig } from '../../../../utils/no_data_config';
+import { LoadingObservability } from '../../../overview/loading_observability';
+import { AlertsTableTGrid } from '../alerts_table_t_grid';
+import {
+ Provider,
+ alertsPageStateContainer,
+ useAlertsPageStateContainer,
+} from '../state_container';
import './styles.scss';
-import { AlertsStatusFilter } from './alerts_status_filter';
-import { AlertsDisclaimer } from './alerts_disclaimer';
+import { AlertsStatusFilter, AlertsDisclaimer, AlertsSearchBar } from '../../components';
export interface TopAlert {
fields: ParsedTechnicalFields;
@@ -243,12 +245,10 @@ function AlertsPage() {
);
}
-function WrappedAlertsPage() {
+export function WrappedAlertsPage() {
return (
);
}
-
-export { WrappedAlertsPage as AlertsPage };
diff --git a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/index.ts b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/index.ts
new file mode 100644
index 0000000000000..e3509e04b2f2b
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/index.ts
@@ -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 { WrappedAlertsPage as AlertsPage } from './alerts_page';
+export type { TopAlert } from './alerts_page';
diff --git a/x-pack/plugins/observability/public/pages/alerts/styles.scss b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/styles.scss
similarity index 100%
rename from x-pack/plugins/observability/public/pages/alerts/styles.scss
rename to x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/styles.scss
diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_table_t_grid/alerts_table_t_grid.tsx
similarity index 94%
rename from x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx
rename to x-pack/plugins/observability/public/pages/alerts/containers/alerts_table_t_grid/alerts_table_t_grid.tsx
index 4b64ae07ddf06..bf99bcedc16be 100644
--- a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_table_t_grid/alerts_table_t_grid.tsx
@@ -33,33 +33,33 @@ import styled from 'styled-components';
import React, { Suspense, useMemo, useState, useCallback, useEffect } from 'react';
import usePrevious from 'react-use/lib/usePrevious';
import { pick } from 'lodash';
-import { getAlertsPermissions } from '../../hooks/use_alert_permission';
+import { getAlertsPermissions } from '../../../../hooks/use_alert_permission';
import type {
TimelinesUIStart,
TGridType,
TGridState,
TGridModel,
SortDirection,
-} from '../../../../timelines/public';
+} from '../../../../../../timelines/public';
-import type { TopAlert } from './';
-import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
+import type { TopAlert } from '../alerts_page/alerts_page';
+import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public';
import type {
ActionProps,
AlertWorkflowStatus,
ColumnHeaderOptions,
ControlColumnProps,
RowRenderer,
-} from '../../../../timelines/common';
-
-import { getRenderCellValue } from './render_cell_value';
-import { observabilityAppId, observabilityFeatureId } from '../../../common';
-import { useGetUserCasesPermissions } from '../../hooks/use_get_user_cases_permissions';
-import { usePluginContext } from '../../hooks/use_plugin_context';
-import { LazyAlertsFlyout } from '../..';
-import { parseAlert } from './parse_alert';
-import { CoreStart } from '../../../../../../src/core/public';
-import { translations, paths } from '../../config';
+} from '../../../../../../timelines/common';
+
+import { getRenderCellValue } from '../../components/render_cell_value';
+import { observabilityAppId, observabilityFeatureId } from '../../../../../common';
+import { useGetUserCasesPermissions } from '../../../../hooks/use_get_user_cases_permissions';
+import { usePluginContext } from '../../../../hooks/use_plugin_context';
+import { LazyAlertsFlyout } from '../../../..';
+import { parseAlert } from '../../components/parse_alert';
+import { CoreStart } from '../../../../../../../../src/core/public';
+import { translations, paths } from '../../../../config';
const ALERT_TABLE_STATE_STORAGE_KEY = 'xpack.observability.alert.tableState';
diff --git a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_table_t_grid/index.ts b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_table_t_grid/index.ts
new file mode 100644
index 0000000000000..7bbcc43230a44
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_table_t_grid/index.ts
@@ -0,0 +1,8 @@
+/*
+ * 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 { AlertsTableTGrid } from './alerts_table_t_grid';
diff --git a/x-pack/plugins/observability/public/pages/alerts/containers/index.ts b/x-pack/plugins/observability/public/pages/alerts/containers/index.ts
new file mode 100644
index 0000000000000..074f48f426640
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/alerts/containers/index.ts
@@ -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 * from './alerts_page';
+export * from './alerts_table_t_grid';
+export * from './state_container';
diff --git a/x-pack/plugins/observability/public/pages/alerts/state_container/index.tsx b/x-pack/plugins/observability/public/pages/alerts/containers/state_container/index.tsx
similarity index 100%
rename from x-pack/plugins/observability/public/pages/alerts/state_container/index.tsx
rename to x-pack/plugins/observability/public/pages/alerts/containers/state_container/index.tsx
diff --git a/x-pack/plugins/observability/public/pages/alerts/state_container/state_container.tsx b/x-pack/plugins/observability/public/pages/alerts/containers/state_container/state_container.tsx
similarity index 92%
rename from x-pack/plugins/observability/public/pages/alerts/state_container/state_container.tsx
rename to x-pack/plugins/observability/public/pages/alerts/containers/state_container/state_container.tsx
index 3e0a801fedbe2..d00109cc5d63f 100644
--- a/x-pack/plugins/observability/public/pages/alerts/state_container/state_container.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/containers/state_container/state_container.tsx
@@ -8,8 +8,8 @@
import {
createStateContainer,
createStateContainerReactHelpers,
-} from '../../../../../../../src/plugins/kibana_utils/public';
-import type { AlertWorkflowStatus } from '../../../../common/typings';
+} from '../../../../../../../../src/plugins/kibana_utils/public';
+import type { AlertWorkflowStatus } from '../../../../../common/typings';
interface AlertsPageContainerState {
rangeFrom: string;
diff --git a/x-pack/plugins/observability/public/pages/alerts/state_container/use_alerts_page_state_container.tsx b/x-pack/plugins/observability/public/pages/alerts/containers/state_container/use_alerts_page_state_container.tsx
similarity index 92%
rename from x-pack/plugins/observability/public/pages/alerts/state_container/use_alerts_page_state_container.tsx
rename to x-pack/plugins/observability/public/pages/alerts/containers/state_container/use_alerts_page_state_container.tsx
index dfa4afcd939cc..5e81286affba7 100644
--- a/x-pack/plugins/observability/public/pages/alerts/state_container/use_alerts_page_state_container.tsx
+++ b/x-pack/plugins/observability/public/pages/alerts/containers/state_container/use_alerts_page_state_container.tsx
@@ -8,14 +8,14 @@
import { useEffect } from 'react';
import { useHistory } from 'react-router-dom';
-import { TimefilterContract } from '../../../../../../../src/plugins/data/public';
+import { TimefilterContract } from '../../../../../../../../src/plugins/data/public';
import {
createKbnUrlStateStorage,
syncState,
IKbnUrlStateStorage,
useContainerSelector,
-} from '../../../../../../../src/plugins/kibana_utils/public';
-import { useTimefilterService } from '../../../hooks/use_timefilter_service';
+} from '../../../../../../../../src/plugins/kibana_utils/public';
+import { useTimefilterService } from '../../../../hooks/use_timefilter_service';
import {
useContainer,
diff --git a/x-pack/plugins/observability/public/pages/alerts/index.ts b/x-pack/plugins/observability/public/pages/alerts/index.ts
new file mode 100644
index 0000000000000..525f3441c4470
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/alerts/index.ts
@@ -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 * from './components';
+export * from './containers';
diff --git a/x-pack/plugins/observability/public/pages/cases/helpers.ts b/x-pack/plugins/observability/public/pages/cases/helpers.ts
index 91f45c711d6a6..f4bc5af7f604d 100644
--- a/x-pack/plugins/observability/public/pages/cases/helpers.ts
+++ b/x-pack/plugins/observability/public/pages/cases/helpers.ts
@@ -6,10 +6,8 @@
*/
import { useEffect, useState } from 'react';
import { isEmpty } from 'lodash';
-
import { usePluginContext } from '../../hooks/use_plugin_context';
-import { parseAlert } from '../../pages/alerts/parse_alert';
-import { TopAlert } from '../../pages/alerts/';
+import { TopAlert, parseAlert } from '../../pages/alerts/';
import { useKibana } from '../../utils/kibana_react';
import { Ecs } from '../../../../cases/common';
diff --git a/x-pack/plugins/observability/public/routes/index.tsx b/x-pack/plugins/observability/public/routes/index.tsx
index 169f4b5254c04..6f38a66cdb643 100644
--- a/x-pack/plugins/observability/public/routes/index.tsx
+++ b/x-pack/plugins/observability/public/routes/index.tsx
@@ -8,8 +8,8 @@
import * as t from 'io-ts';
import React from 'react';
import { casesPath } from '../../common';
-import { AlertsPage } from '../pages/alerts';
import { CasesPage } from '../pages/cases';
+import { AlertsPage } from '../pages/alerts/containers/alerts_page';
import { HomePage } from '../pages/home';
import { LandingPage } from '../pages/landing';
import { OverviewPage } from '../pages/overview';
From 7e9b1bce092ae22ffb6ee081e43267b9da6ba9e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ece=20=C3=96zalp?=
Date: Mon, 29 Nov 2021 13:44:39 -0500
Subject: [PATCH 24/47] [Security Solution] updates host risk score decimal
count (UI) (#119228)
* updates host risk score decimal count
* fix function
* changes isNaN to Number.isNaN
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Ece Ozalp
---
.../overview_risky_host_links/risky_hosts_panel_view.tsx | 2 ++
1 file changed, 2 insertions(+)
diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_panel_view.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_panel_view.tsx
index eb4e226940c5f..87a5710ab0372 100644
--- a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_panel_view.tsx
+++ b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_panel_view.tsx
@@ -30,6 +30,8 @@ const columns: Array> = [
align: 'right',
field: 'count',
name: 'Risk Score',
+ render: (riskScore) =>
+ Number.isNaN(riskScore) ? riskScore : Number.parseFloat(riskScore).toFixed(2),
sortable: true,
truncateText: true,
width: '15%',
From a0ca3d90bceff111cb48b3cb4973f273b58a1499 Mon Sep 17 00:00:00 2001
From: Kate Patticha
Date: Mon, 29 Nov 2021 19:51:06 +0100
Subject: [PATCH 25/47] [APM] Add service icon for the originating service in
traces table (#119421)
* [APM] Add service icon for the originating service in traces table
* Fix api test
* Fix agentName type
---
.../app/trace_overview/trace_list.tsx | 17 +++-
.../__snapshots__/queries.test.ts.snap | 6 ++
.../server/lib/transaction_groups/fetcher.ts | 5 +-
.../get_transaction_group_stats.ts | 13 ++-
.../traces/__snapshots__/top_traces.spec.snap | 81 +++++++++++++++++++
.../tests/traces/top_traces.spec.ts | 2 +
6 files changed, 120 insertions(+), 4 deletions(-)
diff --git a/x-pack/plugins/apm/public/components/app/trace_overview/trace_list.tsx b/x-pack/plugins/apm/public/components/app/trace_overview/trace_list.tsx
index 0fc25b28b60e8..58179366fa42d 100644
--- a/x-pack/plugins/apm/public/components/app/trace_overview/trace_list.tsx
+++ b/x-pack/plugins/apm/public/components/app/trace_overview/trace_list.tsx
@@ -5,7 +5,13 @@
* 2.0.
*/
-import { EuiIcon, EuiToolTip, RIGHT_ALIGNMENT } from '@elastic/eui';
+import {
+ EuiIcon,
+ EuiToolTip,
+ EuiFlexGroup,
+ EuiFlexItem,
+ RIGHT_ALIGNMENT,
+} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common';
@@ -19,6 +25,7 @@ import { EmptyMessage } from '../../shared/EmptyMessage';
import { ImpactBar } from '../../shared/ImpactBar';
import { TransactionDetailLink } from '../../shared/Links/apm/transaction_detail_link';
import { ITableColumn, ManagedTable } from '../../shared/managed_table';
+import { AgentIcon } from '../../shared/agent_icon';
type TraceGroup = APIReturnType<'GET /internal/apm/traces'>['items'][0];
@@ -65,6 +72,14 @@ const traceListColumns: Array> = [
}
),
sortable: true,
+ render: (_: string, { serviceName, agentName }) => (
+
+
+
+
+ {serviceName}
+
+ ),
},
{
field: 'averageResponseTime',
diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/transaction_groups/__snapshots__/queries.test.ts.snap
index 17c43e36e5cc3..00440b2b51853 100644
--- a/x-pack/plugins/apm/server/lib/transaction_groups/__snapshots__/queries.test.ts.snap
+++ b/x-pack/plugins/apm/server/lib/transaction_groups/__snapshots__/queries.test.ts.snap
@@ -18,6 +18,9 @@ Array [
Object {
"field": "transaction.type",
},
+ Object {
+ "field": "agent.name",
+ },
],
"sort": Object {
"@timestamp": "desc",
@@ -228,6 +231,9 @@ Array [
Object {
"field": "transaction.type",
},
+ Object {
+ "field": "agent.name",
+ },
],
"sort": Object {
"@timestamp": "desc",
diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts
index aea92d06b7589..bca71ed71b1f6 100644
--- a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts
+++ b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts
@@ -31,7 +31,7 @@ import {
} from '../helpers/transactions';
import { Setup } from '../helpers/setup_request';
import { getAverages, getCounts, getSums } from './get_transaction_group_stats';
-
+import { AgentName } from '../../../typings/es_schemas/ui/fields/agent';
export interface TopTraceOptions {
environment: string;
kuery: string;
@@ -51,6 +51,7 @@ export interface TransactionGroup {
averageResponseTime: number | null | undefined;
transactionsPerMinute: number;
impact: number;
+ agentName: AgentName;
}
export type ESResponse = Promise<{ items: TransactionGroup[] }>;
@@ -142,6 +143,7 @@ function getItemsWithRelativeImpact(
avg?: number | null;
count?: number | null;
transactionType?: string;
+ agentName?: AgentName;
}>,
start: number,
end: number
@@ -166,6 +168,7 @@ function getItemsWithRelativeImpact(
item.sum !== null && item.sum !== undefined
? ((item.sum - min) / (max - min)) * 100 || 0
: 0,
+ agentName: item.agentName as AgentName,
};
});
diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_group_stats.ts b/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_group_stats.ts
index c79dde721d138..fd638a6731c63 100644
--- a/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_group_stats.ts
+++ b/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_group_stats.ts
@@ -7,11 +7,14 @@
import { merge } from 'lodash';
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
-import { TRANSACTION_TYPE } from '../../../common/elasticsearch_fieldnames';
+import {
+ TRANSACTION_TYPE,
+ AGENT_NAME,
+} from '../../../common/elasticsearch_fieldnames';
import { arrayUnionToCallable } from '../../../common/utils/array_union_to_callable';
import { TransactionGroupRequestBase, TransactionGroupSetup } from './fetcher';
import { getTransactionDurationFieldForTransactions } from '../helpers/transactions';
-
+import { AgentName } from '../../../typings/es_schemas/ui/fields/agent';
interface MetricParams {
request: TransactionGroupRequestBase;
setup: TransactionGroupSetup;
@@ -79,6 +82,9 @@ export async function getCounts({ request, setup }: MetricParams) {
{
field: TRANSACTION_TYPE,
} as const,
+ {
+ field: AGENT_NAME,
+ } as const,
],
},
},
@@ -98,6 +104,9 @@ export async function getCounts({ request, setup }: MetricParams) {
transactionType: bucket.transaction_type.top[0].metrics[
TRANSACTION_TYPE
] as string,
+ agentName: bucket.transaction_type.top[0].metrics[
+ AGENT_NAME
+ ] as AgentName,
};
});
}
diff --git a/x-pack/test/apm_api_integration/tests/traces/__snapshots__/top_traces.spec.snap b/x-pack/test/apm_api_integration/tests/traces/__snapshots__/top_traces.spec.snap
index 604348355f38c..528963709712d 100644
--- a/x-pack/test/apm_api_integration/tests/traces/__snapshots__/top_traces.spec.snap
+++ b/x-pack/test/apm_api_integration/tests/traces/__snapshots__/top_traces.spec.snap
@@ -3,6 +3,7 @@
exports[`APM API tests basic apm_8.0.0 Top traces when data is loaded returns the correct buckets 1`] = `
Array [
Object {
+ "agentName": "java",
"averageResponseTime": 1639,
"impact": 0,
"key": Object {
@@ -15,6 +16,7 @@ Array [
"transactionsPerMinute": 0.0333333333333333,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 3279,
"impact": 0.00144735571024101,
"key": Object {
@@ -27,6 +29,7 @@ Array [
"transactionsPerMinute": 0.0333333333333333,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 6175,
"impact": 0.00400317408637392,
"key": Object {
@@ -39,6 +42,7 @@ Array [
"transactionsPerMinute": 0.0333333333333333,
},
Object {
+ "agentName": "dotnet",
"averageResponseTime": 3495,
"impact": 0.00472243927164613,
"key": Object {
@@ -51,6 +55,7 @@ Array [
"transactionsPerMinute": 0.0666666666666667,
},
Object {
+ "agentName": "python",
"averageResponseTime": 7039,
"impact": 0.00476568343615943,
"key": Object {
@@ -63,6 +68,7 @@ Array [
"transactionsPerMinute": 0.0333333333333333,
},
Object {
+ "agentName": "ruby",
"averageResponseTime": 6303,
"impact": 0.00967875004525193,
"key": Object {
@@ -75,6 +81,7 @@ Array [
"transactionsPerMinute": 0.0666666666666667,
},
Object {
+ "agentName": "java",
"averageResponseTime": 7209.66666666667,
"impact": 0.0176418540534865,
"key": Object {
@@ -87,6 +94,7 @@ Array [
"transactionsPerMinute": 0.1,
},
Object {
+ "agentName": "java",
"averageResponseTime": 4511,
"impact": 0.0224401912465233,
"key": Object {
@@ -99,6 +107,7 @@ Array [
"transactionsPerMinute": 0.2,
},
Object {
+ "agentName": "python",
"averageResponseTime": 7607,
"impact": 0.0254072704525173,
"key": Object {
@@ -111,6 +120,7 @@ Array [
"transactionsPerMinute": 0.133333333333333,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 10143,
"impact": 0.025408152986487,
"key": Object {
@@ -123,6 +133,7 @@ Array [
"transactionsPerMinute": 0.1,
},
Object {
+ "agentName": "ruby",
"averageResponseTime": 6105.66666666667,
"impact": 0.0308842762682221,
"key": Object {
@@ -135,6 +146,7 @@ Array [
"transactionsPerMinute": 0.2,
},
Object {
+ "agentName": "java",
"averageResponseTime": 6116.33333333333,
"impact": 0.0309407584422802,
"key": Object {
@@ -147,6 +159,7 @@ Array [
"transactionsPerMinute": 0.2,
},
Object {
+ "agentName": "java",
"averageResponseTime": 12543,
"impact": 0.0317623975680329,
"key": Object {
@@ -159,6 +172,7 @@ Array [
"transactionsPerMinute": 0.1,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 5551,
"impact": 0.0328461492827744,
"key": Object {
@@ -171,6 +185,7 @@ Array [
"transactionsPerMinute": 0.233333333333333,
},
Object {
+ "agentName": "java",
"averageResponseTime": 13183,
"impact": 0.0334568627897785,
"key": Object {
@@ -183,6 +198,7 @@ Array [
"transactionsPerMinute": 0.1,
},
Object {
+ "agentName": "go",
"averageResponseTime": 8050.2,
"impact": 0.0340764016364792,
"key": Object {
@@ -195,6 +211,7 @@ Array [
"transactionsPerMinute": 0.166666666666667,
},
Object {
+ "agentName": "ruby",
"averageResponseTime": 10079,
"impact": 0.0341337663445071,
"key": Object {
@@ -207,6 +224,7 @@ Array [
"transactionsPerMinute": 0.133333333333333,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 8463,
"impact": 0.0358979517498557,
"key": Object {
@@ -219,6 +237,7 @@ Array [
"transactionsPerMinute": 0.166666666666667,
},
Object {
+ "agentName": "ruby",
"averageResponseTime": 10799,
"impact": 0.0366754641771254,
"key": Object {
@@ -231,6 +250,7 @@ Array [
"transactionsPerMinute": 0.133333333333333,
},
Object {
+ "agentName": "ruby",
"averageResponseTime": 7428.33333333333,
"impact": 0.0378880658514371,
"key": Object {
@@ -243,6 +263,7 @@ Array [
"transactionsPerMinute": 0.2,
},
Object {
+ "agentName": "java",
"averageResponseTime": 3105.13333333333,
"impact": 0.039659311528543,
"key": Object {
@@ -255,6 +276,7 @@ Array [
"transactionsPerMinute": 0.5,
},
Object {
+ "agentName": "java",
"averageResponseTime": 6883.57142857143,
"impact": 0.0410784261517549,
"key": Object {
@@ -267,6 +289,7 @@ Array [
"transactionsPerMinute": 0.233333333333333,
},
Object {
+ "agentName": "dotnet",
"averageResponseTime": 3505,
"impact": 0.0480460318422139,
"key": Object {
@@ -279,6 +302,7 @@ Array [
"transactionsPerMinute": 0.533333333333333,
},
Object {
+ "agentName": "java",
"averageResponseTime": 5621.4,
"impact": 0.0481642913941483,
"key": Object {
@@ -291,6 +315,7 @@ Array [
"transactionsPerMinute": 0.333333333333333,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 8428.71428571429,
"impact": 0.0506239135675883,
"key": Object {
@@ -303,6 +328,7 @@ Array [
"transactionsPerMinute": 0.233333333333333,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 8520.14285714286,
"impact": 0.0511887353081702,
"key": Object {
@@ -315,6 +341,7 @@ Array [
"transactionsPerMinute": 0.233333333333333,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 6683.44444444444,
"impact": 0.0516388276326964,
"key": Object {
@@ -327,6 +354,7 @@ Array [
"transactionsPerMinute": 0.3,
},
Object {
+ "agentName": "dotnet",
"averageResponseTime": 3482.78947368421,
"impact": 0.0569534471979838,
"key": Object {
@@ -339,6 +367,7 @@ Array [
"transactionsPerMinute": 0.633333333333333,
},
Object {
+ "agentName": "python",
"averageResponseTime": 16703,
"impact": 0.057517386404596,
"key": Object {
@@ -351,6 +380,7 @@ Array [
"transactionsPerMinute": 0.133333333333333,
},
Object {
+ "agentName": "dotnet",
"averageResponseTime": 4943,
"impact": 0.0596266425920813,
"key": Object {
@@ -363,6 +393,7 @@ Array [
"transactionsPerMinute": 0.466666666666667,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 7892.33333333333,
"impact": 0.0612407972225879,
"key": Object {
@@ -375,6 +406,7 @@ Array [
"transactionsPerMinute": 0.3,
},
Object {
+ "agentName": "dotnet",
"averageResponseTime": 6346.42857142857,
"impact": 0.0769666700279444,
"key": Object {
@@ -387,6 +419,7 @@ Array [
"transactionsPerMinute": 0.466666666666667,
},
Object {
+ "agentName": "go",
"averageResponseTime": 7052.84615384615,
"impact": 0.0794704188998674,
"key": Object {
@@ -399,6 +432,7 @@ Array [
"transactionsPerMinute": 0.433333333333333,
},
Object {
+ "agentName": "java",
"averageResponseTime": 10484.3333333333,
"impact": 0.0818285496667966,
"key": Object {
@@ -411,6 +445,7 @@ Array [
"transactionsPerMinute": 0.3,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 23711,
"impact": 0.0822565786420813,
"key": Object {
@@ -423,6 +458,7 @@ Array [
"transactionsPerMinute": 0.133333333333333,
},
Object {
+ "agentName": "dotnet",
"averageResponseTime": 4491.36363636364,
"impact": 0.0857567083657495,
"key": Object {
@@ -435,6 +471,7 @@ Array [
"transactionsPerMinute": 0.733333333333333,
},
Object {
+ "agentName": "python",
"averageResponseTime": 20715.8,
"impact": 0.089965512867054,
"key": Object {
@@ -447,6 +484,7 @@ Array [
"transactionsPerMinute": 0.166666666666667,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 9036.33333333333,
"impact": 0.0942519803576885,
"key": Object {
@@ -459,6 +497,7 @@ Array [
"transactionsPerMinute": 0.4,
},
Object {
+ "agentName": "java",
"averageResponseTime": 7504.06666666667,
"impact": 0.0978924329825326,
"key": Object {
@@ -471,6 +510,7 @@ Array [
"transactionsPerMinute": 0.5,
},
Object {
+ "agentName": "go",
"averageResponseTime": 4250.55555555556,
"impact": 0.0998375378516613,
"key": Object {
@@ -483,6 +523,7 @@ Array [
"transactionsPerMinute": 0.9,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 21343,
"impact": 0.11156906191034,
"key": Object {
@@ -495,6 +536,7 @@ Array [
"transactionsPerMinute": 0.2,
},
Object {
+ "agentName": "ruby",
"averageResponseTime": 16655,
"impact": 0.116142352941114,
"key": Object {
@@ -507,6 +549,7 @@ Array [
"transactionsPerMinute": 0.266666666666667,
},
Object {
+ "agentName": "go",
"averageResponseTime": 5749,
"impact": 0.12032203382142,
"key": Object {
@@ -519,6 +562,7 @@ Array [
"transactionsPerMinute": 0.8,
},
Object {
+ "agentName": "ruby",
"averageResponseTime": 9951,
"impact": 0.121502864272824,
"key": Object {
@@ -531,6 +575,7 @@ Array [
"transactionsPerMinute": 0.466666666666667,
},
Object {
+ "agentName": "go",
"averageResponseTime": 14040.6,
"impact": 0.122466591367692,
"key": Object {
@@ -543,6 +588,7 @@ Array [
"transactionsPerMinute": 0.333333333333333,
},
Object {
+ "agentName": "ruby",
"averageResponseTime": 20963.5714285714,
"impact": 0.128060974201361,
"key": Object {
@@ -555,6 +601,7 @@ Array [
"transactionsPerMinute": 0.233333333333333,
},
Object {
+ "agentName": "python",
"averageResponseTime": 22874.4285714286,
"impact": 0.139865748579522,
"key": Object {
@@ -567,6 +614,7 @@ Array [
"transactionsPerMinute": 0.233333333333333,
},
Object {
+ "agentName": "python",
"averageResponseTime": 32203.8,
"impact": 0.140658264084276,
"key": Object {
@@ -579,6 +627,7 @@ Array [
"transactionsPerMinute": 0.166666666666667,
},
Object {
+ "agentName": "go",
"averageResponseTime": 4482.11111111111,
"impact": 0.140955678032051,
"key": Object {
@@ -591,6 +640,7 @@ Array [
"transactionsPerMinute": 1.2,
},
Object {
+ "agentName": "ruby",
"averageResponseTime": 12582.3846153846,
"impact": 0.142910490774846,
"key": Object {
@@ -603,6 +653,7 @@ Array [
"transactionsPerMinute": 0.433333333333333,
},
Object {
+ "agentName": "ruby",
"averageResponseTime": 10009.9473684211,
"impact": 0.166401779979233,
"key": Object {
@@ -615,6 +666,7 @@ Array [
"transactionsPerMinute": 0.633333333333333,
},
Object {
+ "agentName": "python",
"averageResponseTime": 27825.2857142857,
"impact": 0.170450845832029,
"key": Object {
@@ -627,6 +679,7 @@ Array [
"transactionsPerMinute": 0.233333333333333,
},
Object {
+ "agentName": "python",
"averageResponseTime": 20562.2,
"impact": 0.180021926732983,
"key": Object {
@@ -639,6 +692,7 @@ Array [
"transactionsPerMinute": 0.333333333333333,
},
Object {
+ "agentName": "dotnet",
"averageResponseTime": 7106.76470588235,
"impact": 0.21180020991247,
"key": Object {
@@ -651,6 +705,7 @@ Array [
"transactionsPerMinute": 1.13333333333333,
},
Object {
+ "agentName": "go",
"averageResponseTime": 8612.51724137931,
"impact": 0.218977858687708,
"key": Object {
@@ -663,6 +718,7 @@ Array [
"transactionsPerMinute": 0.966666666666667,
},
Object {
+ "agentName": "ruby",
"averageResponseTime": 11295,
"impact": 0.277663720068132,
"key": Object {
@@ -675,6 +731,7 @@ Array [
"transactionsPerMinute": 0.933333333333333,
},
Object {
+ "agentName": "python",
"averageResponseTime": 65035.8,
"impact": 0.285535040543522,
"key": Object {
@@ -687,6 +744,7 @@ Array [
"transactionsPerMinute": 0.166666666666667,
},
Object {
+ "agentName": "go",
"averageResponseTime": 30999.4705882353,
"impact": 0.463640986028375,
"key": Object {
@@ -699,6 +757,7 @@ Array [
"transactionsPerMinute": 0.566666666666667,
},
Object {
+ "agentName": "go",
"averageResponseTime": 20197.4,
"impact": 0.622424732781511,
"key": Object {
@@ -711,6 +770,7 @@ Array [
"transactionsPerMinute": 1.16666666666667,
},
Object {
+ "agentName": "python",
"averageResponseTime": 64681.6666666667,
"impact": 0.68355874339377,
"key": Object {
@@ -723,6 +783,7 @@ Array [
"transactionsPerMinute": 0.4,
},
Object {
+ "agentName": "dotnet",
"averageResponseTime": 41416.1428571429,
"impact": 0.766127739061111,
"key": Object {
@@ -735,6 +796,7 @@ Array [
"transactionsPerMinute": 0.7,
},
Object {
+ "agentName": "go",
"averageResponseTime": 19429,
"impact": 0.821597646656097,
"key": Object {
@@ -747,6 +809,7 @@ Array [
"transactionsPerMinute": 1.6,
},
Object {
+ "agentName": "dotnet",
"averageResponseTime": 62390.652173913,
"impact": 1.26497653527507,
"key": Object {
@@ -759,6 +822,7 @@ Array [
"transactionsPerMinute": 0.766666666666667,
},
Object {
+ "agentName": "python",
"averageResponseTime": 33266.2,
"impact": 1.76006661931225,
"key": Object {
@@ -771,6 +835,7 @@ Array [
"transactionsPerMinute": 2,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 38491.4444444444,
"impact": 1.83293391905112,
"key": Object {
@@ -783,6 +848,7 @@ Array [
"transactionsPerMinute": 1.8,
},
Object {
+ "agentName": "dotnet",
"averageResponseTime": 118488.6,
"impact": 2.08995781717084,
"key": Object {
@@ -795,6 +861,7 @@ Array [
"transactionsPerMinute": 0.666666666666667,
},
Object {
+ "agentName": "dotnet",
"averageResponseTime": 250440.142857143,
"impact": 4.64001412901584,
"key": Object {
@@ -807,6 +874,7 @@ Array [
"transactionsPerMinute": 0.7,
},
Object {
+ "agentName": "java",
"averageResponseTime": 312096.523809524,
"impact": 5.782704992387,
"key": Object {
@@ -819,6 +887,7 @@ Array [
"transactionsPerMinute": 0.7,
},
Object {
+ "agentName": "ruby",
"averageResponseTime": 91519.7032967033,
"impact": 7.34855500859826,
"key": Object {
@@ -831,6 +900,7 @@ Array [
"transactionsPerMinute": 3.03333333333333,
},
Object {
+ "agentName": "rum-js",
"averageResponseTime": 648269.769230769,
"impact": 7.43611473386403,
"key": Object {
@@ -843,6 +913,7 @@ Array [
"transactionsPerMinute": 0.433333333333333,
},
Object {
+ "agentName": "python",
"averageResponseTime": 1398919.72727273,
"impact": 13.5790895084132,
"key": Object {
@@ -855,6 +926,7 @@ Array [
"transactionsPerMinute": 0.366666666666667,
},
Object {
+ "agentName": "rum-js",
"averageResponseTime": 1199907.57142857,
"impact": 14.8239822181408,
"key": Object {
@@ -867,6 +939,7 @@ Array [
"transactionsPerMinute": 0.466666666666667,
},
Object {
+ "agentName": "rum-js",
"averageResponseTime": 955876.052631579,
"impact": 16.026822184214,
"key": Object {
@@ -879,6 +952,7 @@ Array [
"transactionsPerMinute": 0.633333333333333,
},
Object {
+ "agentName": "go",
"averageResponseTime": 965009.526315789,
"impact": 16.1799735991728,
"key": Object {
@@ -891,6 +965,7 @@ Array [
"transactionsPerMinute": 0.633333333333333,
},
Object {
+ "agentName": "rum-js",
"averageResponseTime": 1213675.30769231,
"impact": 27.8474053933734,
"key": Object {
@@ -903,6 +978,7 @@ Array [
"transactionsPerMinute": 0.866666666666667,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 924019.363636364,
"impact": 35.8796065162284,
"key": Object {
@@ -915,6 +991,7 @@ Array [
"transactionsPerMinute": 1.46666666666667,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 1060469.15384615,
"impact": 36.498655556576,
"key": Object {
@@ -927,6 +1004,7 @@ Array [
"transactionsPerMinute": 1.3,
},
Object {
+ "agentName": "python",
"averageResponseTime": 118686.822222222,
"impact": 37.7068083771466,
"key": Object {
@@ -939,6 +1017,7 @@ Array [
"transactionsPerMinute": 12,
},
Object {
+ "agentName": "nodejs",
"averageResponseTime": 1039228.27659574,
"impact": 43.1048035741496,
"key": Object {
@@ -951,6 +1030,7 @@ Array [
"transactionsPerMinute": 1.56666666666667,
},
Object {
+ "agentName": "python",
"averageResponseTime": 1949922.55555556,
"impact": 61.9499776921889,
"key": Object {
@@ -963,6 +1043,7 @@ Array [
"transactionsPerMinute": 1.2,
},
Object {
+ "agentName": "dotnet",
"averageResponseTime": 5963775,
"impact": 100,
"key": Object {
diff --git a/x-pack/test/apm_api_integration/tests/traces/top_traces.spec.ts b/x-pack/test/apm_api_integration/tests/traces/top_traces.spec.ts
index 51b14809982d8..06a24cbd34a4b 100644
--- a/x-pack/test/apm_api_integration/tests/traces/top_traces.spec.ts
+++ b/x-pack/test/apm_api_integration/tests/traces/top_traces.spec.ts
@@ -63,6 +63,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
expectSnapshot(firstItem).toMatchInline(`
Object {
+ "agentName": "java",
"averageResponseTime": 1639,
"impact": 0,
"key": Object {
@@ -78,6 +79,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
expectSnapshot(lastItem).toMatchInline(`
Object {
+ "agentName": "dotnet",
"averageResponseTime": 5963775,
"impact": 100,
"key": Object {
From 9f47e386c98056a3eb07cb44b78b5822f3f1d2e0 Mon Sep 17 00:00:00 2001
From: Nicolas Chaulet
Date: Mon, 29 Nov 2021 14:13:06 -0500
Subject: [PATCH 26/47] [Fleet] Fix preconfiguration variable values (#119749)
---
.../server/services/package_policy.test.ts | 786 +++++++++++++++++-
.../fleet/server/services/package_policy.ts | 157 +++-
.../fleet/server/services/preconfiguration.ts | 4 +-
3 files changed, 909 insertions(+), 38 deletions(-)
diff --git a/x-pack/plugins/fleet/server/services/package_policy.test.ts b/x-pack/plugins/fleet/server/services/package_policy.test.ts
index 36976bea4a970..ac88204f082b7 100644
--- a/x-pack/plugins/fleet/server/services/package_policy.test.ts
+++ b/x-pack/plugins/fleet/server/services/package_policy.test.ts
@@ -39,7 +39,8 @@ import type {
import { IngestManagerError } from '../errors';
import {
- overridePackageInputs,
+ preconfigurePackageInputs,
+ updatePackageInputs,
packagePolicyService,
_applyIndexPrivileges,
} from './package_policy';
@@ -1170,7 +1171,776 @@ describe('Package policy service', () => {
});
});
- describe('overridePackageInputs', () => {
+ describe('preconfigurePackageInputs', () => {
+ describe('when variable is already defined', () => {
+ it('override original variable value', () => {
+ const basePackagePolicy: NewPackagePolicy = {
+ name: 'base-package-policy',
+ description: 'Base Package Policy',
+ namespace: 'default',
+ enabled: true,
+ policy_id: 'xxxx',
+ output_id: 'xxxx',
+ package: {
+ name: 'test-package',
+ title: 'Test Package',
+ version: '0.0.1',
+ },
+ inputs: [
+ {
+ type: 'logs',
+ policy_template: 'template_1',
+ enabled: true,
+ vars: {
+ path: {
+ type: 'text',
+ value: ['/var/log/logfile.log'],
+ },
+ },
+ streams: [],
+ },
+ ],
+ };
+
+ const packageInfo: PackageInfo = {
+ name: 'test-package',
+ description: 'Test Package',
+ title: 'Test Package',
+ version: '0.0.1',
+ latestVersion: '0.0.1',
+ release: 'experimental',
+ format_version: '1.0.0',
+ owner: { github: 'elastic/fleet' },
+ policy_templates: [
+ {
+ name: 'template_1',
+ title: 'Template 1',
+ description: 'Template 1',
+ inputs: [
+ {
+ type: 'logs',
+ title: 'Log',
+ description: 'Log Input',
+ vars: [
+ {
+ name: 'path',
+ type: 'text',
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ // @ts-ignore
+ assets: {},
+ };
+
+ const inputsOverride: NewPackagePolicyInput[] = [
+ {
+ type: 'logs',
+ enabled: true,
+ streams: [],
+ vars: {
+ path: {
+ type: 'text',
+ value: '/var/log/new-logfile.log',
+ },
+ },
+ },
+ ];
+
+ const result = preconfigurePackageInputs(
+ basePackagePolicy,
+ packageInfo,
+ // TODO: Update this type assertion when the `InputsOverride` type is updated such
+ // that it no longer causes unresolvable type errors when used directly
+ inputsOverride as InputsOverride[]
+ );
+ expect(result.inputs[0]?.vars?.path.value).toEqual('/var/log/new-logfile.log');
+ });
+ });
+
+ describe('when variable is undefined in original object', () => {
+ it('adds the variable definition to the resulting object', () => {
+ const basePackagePolicy: NewPackagePolicy = {
+ name: 'base-package-policy',
+ description: 'Base Package Policy',
+ namespace: 'default',
+ enabled: true,
+ policy_id: 'xxxx',
+ output_id: 'xxxx',
+ package: {
+ name: 'test-package',
+ title: 'Test Package',
+ version: '0.0.1',
+ },
+ inputs: [
+ {
+ type: 'logs',
+ policy_template: 'template_1',
+ enabled: true,
+ vars: {
+ path: {
+ type: 'text',
+ value: ['/var/log/logfile.log'],
+ },
+ },
+ streams: [],
+ },
+ ],
+ };
+
+ const packageInfo: PackageInfo = {
+ name: 'test-package',
+ description: 'Test Package',
+ title: 'Test Package',
+ version: '0.0.1',
+ latestVersion: '0.0.1',
+ release: 'experimental',
+ format_version: '1.0.0',
+ owner: { github: 'elastic/fleet' },
+ policy_templates: [
+ {
+ name: 'template_1',
+ title: 'Template 1',
+ description: 'Template 1',
+ inputs: [
+ {
+ type: 'logs',
+ title: 'Log',
+ description: 'Log Input',
+ vars: [
+ {
+ name: 'path',
+ type: 'text',
+ },
+ {
+ name: 'path_2',
+ type: 'text',
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ // @ts-ignore
+ assets: {},
+ };
+
+ const inputsOverride: NewPackagePolicyInput[] = [
+ {
+ type: 'logs',
+ enabled: true,
+ streams: [],
+ policy_template: 'template_1',
+ vars: {
+ path: {
+ type: 'text',
+ value: '/var/log/new-logfile.log',
+ },
+ path_2: {
+ type: 'text',
+ value: '/var/log/custom.log',
+ },
+ },
+ },
+ ];
+
+ const result = preconfigurePackageInputs(
+ basePackagePolicy,
+ packageInfo,
+ // TODO: Update this type assertion when the `InputsOverride` type is updated such
+ // that it no longer causes unresolvable type errors when used directly
+ inputsOverride as InputsOverride[]
+ );
+
+ expect(result.inputs[0]?.vars?.path_2.value).toEqual('/var/log/custom.log');
+ });
+ });
+
+ describe('when variable is undefined in original object and policy_template is undefined', () => {
+ it('adds the variable definition to the resulting object', () => {
+ const basePackagePolicy: NewPackagePolicy = {
+ name: 'base-package-policy',
+ description: 'Base Package Policy',
+ namespace: 'default',
+ enabled: true,
+ policy_id: 'xxxx',
+ output_id: 'xxxx',
+ package: {
+ name: 'test-package',
+ title: 'Test Package',
+ version: '0.0.1',
+ },
+ inputs: [
+ {
+ type: 'logs',
+ policy_template: 'template_1',
+ enabled: true,
+ vars: {
+ path: {
+ type: 'text',
+ value: ['/var/log/logfile.log'],
+ },
+ },
+ streams: [],
+ },
+ ],
+ };
+
+ const packageInfo: PackageInfo = {
+ name: 'test-package',
+ description: 'Test Package',
+ title: 'Test Package',
+ version: '0.0.1',
+ latestVersion: '0.0.1',
+ release: 'experimental',
+ format_version: '1.0.0',
+ owner: { github: 'elastic/fleet' },
+ policy_templates: [
+ {
+ name: 'template_1',
+ title: 'Template 1',
+ description: 'Template 1',
+ inputs: [
+ {
+ type: 'logs',
+ title: 'Log',
+ description: 'Log Input',
+ vars: [
+ {
+ name: 'path',
+ type: 'text',
+ },
+ {
+ name: 'path_2',
+ type: 'text',
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ // @ts-ignore
+ assets: {},
+ };
+
+ const inputsOverride: NewPackagePolicyInput[] = [
+ {
+ type: 'logs',
+ enabled: true,
+ streams: [],
+ policy_template: undefined, // preconfigured input overrides don't have a policy_template
+ vars: {
+ path: {
+ type: 'text',
+ value: '/var/log/new-logfile.log',
+ },
+ path_2: {
+ type: 'text',
+ value: '/var/log/custom.log',
+ },
+ },
+ },
+ ];
+
+ const result = preconfigurePackageInputs(
+ basePackagePolicy,
+ packageInfo,
+ // TODO: Update this type assertion when the `InputsOverride` type is updated such
+ // that it no longer causes unresolvable type errors when used directly
+ inputsOverride as InputsOverride[]
+ );
+
+ expect(result.inputs[0]?.vars?.path_2.value).toEqual('/var/log/custom.log');
+ });
+ });
+
+ describe('when an input of the same type exists under multiple policy templates', () => {
+ it('adds variable definitions to the proper streams', () => {
+ const basePackagePolicy: NewPackagePolicy = {
+ name: 'base-package-policy',
+ description: 'Base Package Policy',
+ namespace: 'default',
+ enabled: true,
+ policy_id: 'xxxx',
+ output_id: 'xxxx',
+ package: {
+ name: 'test-package',
+ title: 'Test Package',
+ version: '0.0.1',
+ },
+ inputs: [
+ {
+ type: 'logs',
+ policy_template: 'template_1',
+ enabled: true,
+ streams: [
+ {
+ enabled: true,
+ data_stream: {
+ dataset: 'test.logs',
+ type: 'logfile',
+ },
+ vars: {
+ log_file_path: {
+ type: 'text',
+ },
+ },
+ },
+ ],
+ },
+ {
+ type: 'logs',
+ policy_template: 'template_2',
+ enabled: true,
+ streams: [
+ {
+ enabled: true,
+ data_stream: {
+ dataset: 'test.logs',
+ type: 'logfile',
+ },
+ vars: {
+ log_file_path: {
+ type: 'text',
+ },
+ },
+ },
+ ],
+ },
+ ],
+ };
+
+ const packageInfo: PackageInfo = {
+ name: 'test-package',
+ description: 'Test Package',
+ title: 'Test Package',
+ version: '0.0.1',
+ latestVersion: '0.0.1',
+ release: 'experimental',
+ format_version: '1.0.0',
+ owner: { github: 'elastic/fleet' },
+ policy_templates: [
+ {
+ name: 'template_1',
+ title: 'Template 1',
+ description: 'Template 1',
+ inputs: [
+ {
+ type: 'logs',
+ title: 'Log',
+ description: 'Log Input',
+ vars: [],
+ },
+ ],
+ },
+ {
+ name: 'template_2',
+ title: 'Template 2',
+ description: 'Template 2',
+ inputs: [
+ {
+ type: 'logs',
+ title: 'Log',
+ description: 'Log Input',
+ vars: [],
+ },
+ ],
+ },
+ ],
+ // @ts-ignore
+ assets: {},
+ };
+
+ const inputsOverride: NewPackagePolicyInput[] = [
+ {
+ type: 'logs',
+ enabled: true,
+ policy_template: 'template_1',
+ streams: [
+ {
+ enabled: true,
+ data_stream: {
+ dataset: 'test.logs',
+ type: 'logfile',
+ },
+ vars: {
+ log_file_path: {
+ type: 'text',
+ value: '/var/log/template1-logfile.log',
+ },
+ },
+ },
+ ],
+ },
+ {
+ type: 'logs',
+ enabled: true,
+ policy_template: 'template_2',
+ streams: [
+ {
+ enabled: true,
+ data_stream: {
+ dataset: 'test.logs',
+ type: 'logfile',
+ },
+ vars: {
+ log_file_path: {
+ type: 'text',
+ value: '/var/log/template2-logfile.log',
+ },
+ },
+ },
+ ],
+ },
+ ];
+
+ const result = preconfigurePackageInputs(
+ basePackagePolicy,
+ packageInfo,
+ // TODO: Update this type assertion when the `InputsOverride` type is updated such
+ // that it no longer causes unresolvable type errors when used directly
+ inputsOverride as InputsOverride[]
+ );
+
+ expect(result.inputs).toHaveLength(2);
+
+ const template1Input = result.inputs.find(
+ (input) => input.policy_template === 'template_1'
+ );
+ const template2Input = result.inputs.find(
+ (input) => input.policy_template === 'template_2'
+ );
+
+ expect(template1Input).toBeDefined();
+ expect(template2Input).toBeDefined();
+
+ expect(template1Input?.streams[0].vars?.log_file_path.value).toBe(
+ '/var/log/template1-logfile.log'
+ );
+
+ expect(template2Input?.streams[0].vars?.log_file_path.value).toBe(
+ '/var/log/template2-logfile.log'
+ );
+ });
+ });
+
+ describe('when an input or stream is disabled on the original policy object', () => {
+ it('remains disabled on the resulting policy object', () => {
+ const basePackagePolicy: NewPackagePolicy = {
+ name: 'base-package-policy',
+ description: 'Base Package Policy',
+ namespace: 'default',
+ enabled: true,
+ policy_id: 'xxxx',
+ output_id: 'xxxx',
+ package: {
+ name: 'test-package',
+ title: 'Test Package',
+ version: '0.0.1',
+ },
+ inputs: [
+ {
+ type: 'logs',
+ policy_template: 'template_1',
+ enabled: false,
+ streams: [
+ {
+ enabled: false,
+ data_stream: {
+ dataset: 'test.logs',
+ type: 'logfile',
+ },
+ vars: {
+ log_file_path: {
+ type: 'text',
+ },
+ },
+ },
+ {
+ enabled: true,
+ data_stream: {
+ dataset: 'test.logs',
+ type: 'logfile2',
+ },
+ vars: {
+ log_file_path_2: {
+ type: 'text',
+ },
+ },
+ },
+ ],
+ },
+ {
+ type: 'logs_2',
+ policy_template: 'template_1',
+ enabled: true,
+ streams: [
+ {
+ enabled: true,
+ data_stream: {
+ dataset: 'test.logs',
+ type: 'logfile',
+ },
+ vars: {
+ log_file_path: {
+ type: 'text',
+ },
+ },
+ },
+ ],
+ },
+ {
+ type: 'logs',
+ policy_template: 'template_2',
+ enabled: true,
+ streams: [
+ {
+ enabled: true,
+ data_stream: {
+ dataset: 'test.logs',
+ type: 'logfile',
+ },
+ vars: {
+ log_file_path: {
+ type: 'text',
+ },
+ },
+ },
+ ],
+ },
+ ],
+ };
+
+ const packageInfo: PackageInfo = {
+ name: 'test-package',
+ description: 'Test Package',
+ title: 'Test Package',
+ version: '0.0.1',
+ latestVersion: '0.0.1',
+ release: 'experimental',
+ format_version: '1.0.0',
+ owner: { github: 'elastic/fleet' },
+ policy_templates: [
+ {
+ name: 'template_1',
+ title: 'Template 1',
+ description: 'Template 1',
+ inputs: [
+ {
+ type: 'logs',
+ title: 'Log',
+ description: 'Log Input',
+ vars: [],
+ },
+ {
+ type: 'logs_2',
+ title: 'Log 2',
+ description: 'Log Input 2',
+ vars: [],
+ },
+ ],
+ },
+ {
+ name: 'template_2',
+ title: 'Template 2',
+ description: 'Template 2',
+ inputs: [
+ {
+ type: 'logs',
+ title: 'Log',
+ description: 'Log Input',
+ vars: [],
+ },
+ ],
+ },
+ ],
+ // @ts-ignore
+ assets: {},
+ };
+
+ const inputsOverride: NewPackagePolicyInput[] = [
+ {
+ type: 'logs',
+ enabled: true,
+ policy_template: 'template_1',
+ streams: [
+ {
+ enabled: true,
+ data_stream: {
+ dataset: 'test.logs',
+ type: 'logfile',
+ },
+ vars: {
+ log_file_path: {
+ type: 'text',
+ value: '/var/log/template1-logfile.log',
+ },
+ },
+ },
+ {
+ enabled: true,
+ data_stream: {
+ dataset: 'test.logs',
+ type: 'logfile2',
+ },
+ vars: {
+ log_file_path_2: {
+ type: 'text',
+ value: '/var/log/template1-logfile2.log',
+ },
+ },
+ },
+ ],
+ },
+ {
+ type: 'logs',
+ enabled: true,
+ policy_template: 'template_2',
+ streams: [
+ {
+ enabled: true,
+ data_stream: {
+ dataset: 'test.logs',
+ type: 'logfile',
+ },
+ vars: {
+ log_file_path: {
+ type: 'text',
+ value: '/var/log/template2-logfile.log',
+ },
+ },
+ },
+ ],
+ },
+ ];
+
+ const result = preconfigurePackageInputs(
+ basePackagePolicy,
+ packageInfo,
+ // TODO: Update this type assertion when the `InputsOverride` type is updated such
+ // that it no longer causes unresolvable type errors when used directly
+ inputsOverride as InputsOverride[]
+ );
+
+ const template1Inputs = result.inputs.filter(
+ (input) => input.policy_template === 'template_1'
+ );
+
+ const template2Inputs = result.inputs.filter(
+ (input) => input.policy_template === 'template_2'
+ );
+
+ expect(template1Inputs).toHaveLength(2);
+ expect(template2Inputs).toHaveLength(1);
+
+ const logsInput = template1Inputs?.find((input) => input.type === 'logs');
+ expect(logsInput?.enabled).toBe(false);
+
+ const logfileStream = logsInput?.streams.find(
+ (stream) => stream.data_stream.type === 'logfile'
+ );
+
+ expect(logfileStream?.enabled).toBe(false);
+ });
+ });
+
+ describe('when a datastream is deleted from an input', () => {
+ it('it remove the non existing datastream', () => {
+ const basePackagePolicy: NewPackagePolicy = {
+ name: 'base-package-policy',
+ description: 'Base Package Policy',
+ namespace: 'default',
+ enabled: true,
+ policy_id: 'xxxx',
+ output_id: 'xxxx',
+ package: {
+ name: 'test-package',
+ title: 'Test Package',
+ version: '0.0.1',
+ },
+ inputs: [
+ {
+ type: 'logs',
+ policy_template: 'template_1',
+ enabled: true,
+ vars: {
+ path: {
+ type: 'text',
+ value: ['/var/log/logfile.log'],
+ },
+ },
+ streams: [
+ {
+ enabled: true,
+ data_stream: { dataset: 'dataset.test123', type: 'log' },
+ },
+ ],
+ },
+ ],
+ };
+
+ const packageInfo: PackageInfo = {
+ name: 'test-package',
+ description: 'Test Package',
+ title: 'Test Package',
+ version: '0.0.1',
+ latestVersion: '0.0.1',
+ release: 'experimental',
+ format_version: '1.0.0',
+ owner: { github: 'elastic/fleet' },
+ policy_templates: [
+ {
+ name: 'template_1',
+ title: 'Template 1',
+ description: 'Template 1',
+ inputs: [
+ {
+ type: 'logs',
+ title: 'Log',
+ description: 'Log Input',
+ vars: [
+ {
+ name: 'path',
+ type: 'text',
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ // @ts-ignore
+ assets: {},
+ };
+
+ const inputsOverride: NewPackagePolicyInput[] = [
+ {
+ type: 'logs',
+ enabled: true,
+ streams: [],
+ vars: {
+ path: {
+ type: 'text',
+ value: '/var/log/new-logfile.log',
+ },
+ },
+ },
+ ];
+
+ const result = preconfigurePackageInputs(
+ basePackagePolicy,
+ packageInfo,
+ // TODO: Update this type assertion when the `InputsOverride` type is updated such
+ // that it no longer causes unresolvable type errors when used directly
+ inputsOverride as InputsOverride[]
+ );
+ expect(result.inputs[0]?.vars?.path.value).toEqual('/var/log/new-logfile.log');
+ });
+ });
+ });
+
+ describe('updatePackageInputs', () => {
describe('when variable is already defined', () => {
it('preserves original variable value without overwriting', () => {
const basePackagePolicy: NewPackagePolicy = {
@@ -1248,7 +2018,7 @@ describe('Package policy service', () => {
},
];
- const result = overridePackageInputs(
+ const result = updatePackageInputs(
basePackagePolicy,
packageInfo,
// TODO: Update this type assertion when the `InputsOverride` type is updated such
@@ -1346,7 +2116,7 @@ describe('Package policy service', () => {
},
];
- const result = overridePackageInputs(
+ const result = updatePackageInputs(
basePackagePolicy,
packageInfo,
// TODO: Update this type assertion when the `InputsOverride` type is updated such
@@ -1445,7 +2215,7 @@ describe('Package policy service', () => {
},
];
- const result = overridePackageInputs(
+ const result = updatePackageInputs(
basePackagePolicy,
packageInfo,
// TODO: Update this type assertion when the `InputsOverride` type is updated such
@@ -1598,7 +2368,7 @@ describe('Package policy service', () => {
},
];
- const result = overridePackageInputs(
+ const result = updatePackageInputs(
basePackagePolicy,
packageInfo,
// TODO: Update this type assertion when the `InputsOverride` type is updated such
@@ -1819,7 +2589,7 @@ describe('Package policy service', () => {
},
];
- const result = overridePackageInputs(
+ const result = updatePackageInputs(
basePackagePolicy,
packageInfo,
// TODO: Update this type assertion when the `InputsOverride` type is updated such
@@ -1932,7 +2702,7 @@ describe('Package policy service', () => {
},
];
- const result = overridePackageInputs(
+ const result = updatePackageInputs(
basePackagePolicy,
packageInfo,
// TODO: Update this type assertion when the `InputsOverride` type is updated such
diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts
index 535d93cc3eceb..5ac348ad7c8a2 100644
--- a/x-pack/plugins/fleet/server/services/package_policy.ts
+++ b/x-pack/plugins/fleet/server/services/package_policy.ts
@@ -590,7 +590,7 @@ class PackagePolicyService {
try {
const { packagePolicy, packageInfo } = await this.getUpgradePackagePolicyInfo(soClient, id);
- const updatePackagePolicy = overridePackageInputs(
+ const updatePackagePolicy = updatePackageInputs(
{
...omit(packagePolicy, 'id'),
inputs: packagePolicy.inputs,
@@ -648,7 +648,7 @@ class PackagePolicyService {
packageVersion
);
- const updatedPackagePolicy = overridePackageInputs(
+ const updatedPackagePolicy = updatePackageInputs(
{
...omit(packagePolicy, 'id'),
inputs: packagePolicy.inputs,
@@ -1030,13 +1030,13 @@ export const packagePolicyService = new PackagePolicyService();
export type { PackagePolicyService };
-export function overridePackageInputs(
+export function updatePackageInputs(
basePackagePolicy: NewPackagePolicy,
packageInfo: PackageInfo,
- inputsOverride?: InputsOverride[],
+ inputsUpdated?: InputsOverride[],
dryRun?: boolean
): DryRunPackagePolicy {
- if (!inputsOverride) return basePackagePolicy;
+ if (!inputsUpdated) return basePackagePolicy;
const availablePolicyTemplates = packageInfo.policy_templates ?? [];
@@ -1065,42 +1065,40 @@ export function overridePackageInputs(
}),
];
- for (const override of inputsOverride) {
- // Preconfiguration does not currently support multiple policy templates, so overrides will have an undefined
- // policy template, so we only match on `type` in that case.
- let originalInput = override.policy_template
- ? inputs.find(
- (i) => i.type === override.type && i.policy_template === override.policy_template
- )
- : inputs.find((i) => i.type === override.type);
+ for (const update of inputsUpdated) {
+ // If update have an undefined policy template
+ // we only match on `type` .
+ let originalInput = update.policy_template
+ ? inputs.find((i) => i.type === update.type && i.policy_template === update.policy_template)
+ : inputs.find((i) => i.type === update.type);
// If there's no corresponding input on the original package policy, just
// take the override value from the new package as-is. This case typically
// occurs when inputs or package policy templates are added/removed between versions.
if (originalInput === undefined) {
- inputs.push(override as NewPackagePolicyInput);
+ inputs.push(update as NewPackagePolicyInput);
continue;
}
// For flags like this, we only want to override the original value if it was set
// as `undefined` in the original object. An explicit true/false value should be
// persisted from the original object to the result after the override process is complete.
- if (originalInput.enabled === undefined && override.enabled !== undefined) {
- originalInput.enabled = override.enabled;
+ if (originalInput.enabled === undefined && update.enabled !== undefined) {
+ originalInput.enabled = update.enabled;
}
- if (originalInput.keep_enabled === undefined && override.keep_enabled !== undefined) {
- originalInput.keep_enabled = override.keep_enabled;
+ if (originalInput.keep_enabled === undefined && update.keep_enabled !== undefined) {
+ originalInput.keep_enabled = update.keep_enabled;
}
- if (override.vars) {
+ if (update.vars) {
const indexOfInput = inputs.indexOf(originalInput);
- inputs[indexOfInput] = deepMergeVars(originalInput, override) as NewPackagePolicyInput;
+ inputs[indexOfInput] = deepMergeVars(originalInput, update, true) as NewPackagePolicyInput;
originalInput = inputs[indexOfInput];
}
- if (override.streams) {
- for (const stream of override.streams) {
+ if (update.streams) {
+ for (const stream of update.streams) {
let originalStream = originalInput?.streams.find(
(s) => s.data_stream.dataset === stream.data_stream.dataset
);
@@ -1118,7 +1116,8 @@ export function overridePackageInputs(
const indexOfStream = originalInput.streams.indexOf(originalStream);
originalInput.streams[indexOfStream] = deepMergeVars(
originalStream,
- stream as InputsOverride
+ stream as InputsOverride,
+ true
);
originalStream = originalInput.streams[indexOfStream];
}
@@ -1128,9 +1127,8 @@ export function overridePackageInputs(
// Filter all stream that have been removed from the input
originalInput.streams = originalInput.streams.filter((originalStream) => {
return (
- override.streams?.some(
- (s) => s.data_stream.dataset === originalStream.data_stream.dataset
- ) ?? false
+ update.streams?.some((s) => s.data_stream.dataset === originalStream.data_stream.dataset) ??
+ false
);
});
}
@@ -1171,7 +1169,110 @@ export function overridePackageInputs(
return resultingPackagePolicy;
}
-function deepMergeVars(original: any, override: any): any {
+export function preconfigurePackageInputs(
+ basePackagePolicy: NewPackagePolicy,
+ packageInfo: PackageInfo,
+ preconfiguredInputs?: InputsOverride[]
+): NewPackagePolicy {
+ if (!preconfiguredInputs) return basePackagePolicy;
+
+ const inputs = [...basePackagePolicy.inputs];
+
+ for (const preconfiguredInput of preconfiguredInputs) {
+ // Preconfiguration does not currently support multiple policy templates, so overrides will have an undefined
+ // policy template, so we only match on `type` in that case.
+ let originalInput = preconfiguredInput.policy_template
+ ? inputs.find(
+ (i) =>
+ i.type === preconfiguredInput.type &&
+ i.policy_template === preconfiguredInput.policy_template
+ )
+ : inputs.find((i) => i.type === preconfiguredInput.type);
+
+ // If the input do not exist skip
+ if (originalInput === undefined) {
+ continue;
+ }
+
+ // For flags like this, we only want to override the original value if it was set
+ // as `undefined` in the original object. An explicit true/false value should be
+ // persisted from the original object to the result after the override process is complete.
+ if (originalInput.enabled === undefined && preconfiguredInput.enabled !== undefined) {
+ originalInput.enabled = preconfiguredInput.enabled;
+ }
+
+ if (originalInput.keep_enabled === undefined && preconfiguredInput.keep_enabled !== undefined) {
+ originalInput.keep_enabled = preconfiguredInput.keep_enabled;
+ }
+
+ if (preconfiguredInput.vars) {
+ const indexOfInput = inputs.indexOf(originalInput);
+ inputs[indexOfInput] = deepMergeVars(
+ originalInput,
+ preconfiguredInput
+ ) as NewPackagePolicyInput;
+ originalInput = inputs[indexOfInput];
+ }
+
+ if (preconfiguredInput.streams) {
+ for (const stream of preconfiguredInput.streams) {
+ let originalStream = originalInput?.streams.find(
+ (s) => s.data_stream.dataset === stream.data_stream.dataset
+ );
+
+ if (originalStream === undefined) {
+ continue;
+ }
+
+ if (originalStream?.enabled === undefined) {
+ originalStream.enabled = stream.enabled;
+ }
+
+ if (stream.vars) {
+ const indexOfStream = originalInput.streams.indexOf(originalStream);
+ originalInput.streams[indexOfStream] = deepMergeVars(
+ originalStream,
+ stream as InputsOverride
+ );
+ originalStream = originalInput.streams[indexOfStream];
+ }
+ }
+ }
+ }
+
+ const resultingPackagePolicy: NewPackagePolicy = {
+ ...basePackagePolicy,
+ inputs,
+ };
+
+ const validationResults = validatePackagePolicy(resultingPackagePolicy, packageInfo, safeLoad);
+
+ if (validationHasErrors(validationResults)) {
+ const responseFormattedValidationErrors = Object.entries(getFlattenedObject(validationResults))
+ .map(([key, value]) => ({
+ key,
+ message: value,
+ }))
+ .filter(({ message }) => !!message);
+
+ if (responseFormattedValidationErrors.length) {
+ throw new PackagePolicyValidationError(
+ i18n.translate('xpack.fleet.packagePolicyInvalidError', {
+ defaultMessage: 'Package policy is invalid: {errors}',
+ values: {
+ errors: responseFormattedValidationErrors
+ .map(({ key, message }) => `${key}: ${message}`)
+ .join('\n'),
+ },
+ })
+ );
+ }
+ }
+
+ return resultingPackagePolicy;
+}
+
+function deepMergeVars(original: any, override: any, keepOriginalValue = false): any {
if (!original.vars) {
original.vars = { ...override.vars };
}
@@ -1192,7 +1293,7 @@ function deepMergeVars(original: any, override: any): any {
// Ensure that any value from the original object is persisted on the newly merged resulting object,
// even if we merge other data about the given variable
- if (originalVar?.value) {
+ if (keepOriginalValue && originalVar?.value) {
result.vars[name].value = originalVar.value;
}
}
diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.ts b/x-pack/plugins/fleet/server/services/preconfiguration.ts
index 8b906b68556a4..76fa7778eafa2 100644
--- a/x-pack/plugins/fleet/server/services/preconfiguration.ts
+++ b/x-pack/plugins/fleet/server/services/preconfiguration.ts
@@ -34,7 +34,7 @@ import { ensurePackagesCompletedInstall } from './epm/packages/install';
import { bulkInstallPackages } from './epm/packages/bulk_install_packages';
import { agentPolicyService, addPackageToAgentPolicy } from './agent_policy';
import type { InputsOverride } from './package_policy';
-import { overridePackageInputs, packagePolicyService } from './package_policy';
+import { preconfigurePackageInputs, packagePolicyService } from './package_policy';
import { appContextService } from './app_context';
import type { UpgradeManagedPackagePoliciesResult } from './managed_package_policies';
import { upgradeManagedPackagePolicies } from './managed_package_policies';
@@ -428,7 +428,7 @@ async function addPreconfiguredPolicyPackages(
defaultOutput,
name,
description,
- (policy) => overridePackageInputs(policy, packageInfo, inputs),
+ (policy) => preconfigurePackageInputs(policy, packageInfo, inputs),
bumpAgentPolicyRevison
);
}
From ab47ac64ad512329e59f99cbc1245582ead7c524 Mon Sep 17 00:00:00 2001
From: Luke Elmers
Date: Mon, 29 Nov 2021 12:27:42 -0700
Subject: [PATCH 27/47] [saved objects] Updates import docs to make it clearer
which versions are supported. (#119879)
---
docs/api/saved-objects/import.asciidoc | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/docs/api/saved-objects/import.asciidoc b/docs/api/saved-objects/import.asciidoc
index 923482954aa2e..a214598af31af 100644
--- a/docs/api/saved-objects/import.asciidoc
+++ b/docs/api/saved-objects/import.asciidoc
@@ -11,11 +11,13 @@ Saved objects can only be imported into the same version, a newer minor on the s
|=======
| Exporting version | Importing version | Compatible?
-| 6.7.0 | 6.8.1 | Yes
-| 6.8.1 | 7.3.0 | Yes
-| 7.3.0 | 7.11.1 | Yes
-| 7.11.1 | 7.6.0 | No
-| 6.8.1 | 8.0.0 | No
+| 6.7.x | 6.8.x | Yes
+| 6.x.x | 7.x.x | Yes
+| 7.x.x | 8.x.x | Yes
+| 7.1.x | 7.15.x | Yes
+| 7.x.x | 6.x.x | No
+| 7.15.x | 7.1.x | No
+| 6.x.x | 8.x.x | No
|=======
[[saved-objects-api-import-request]]
From db7423506c858354e593430e1832942fb1a13f6b Mon Sep 17 00:00:00 2001
From: Lisa Cawley
Date: Mon, 29 Nov 2021 11:46:33 -0800
Subject: [PATCH 28/47] Add workplace search links to doc link service
(#118814)
Co-authored-by: Scotty Bollinger
---
...-plugin-core-public.doclinksstart.links.md | 63 ++++++-
...kibana-plugin-core-public.doclinksstart.md | 2 +-
.../public/doc_links/doc_links_service.ts | 129 ++++++++++++-
src/core/public/public.api.md | 63 ++++++-
.../api_logs/components/empty_state.test.tsx | 4 +-
.../api_logs/components/empty_state.tsx | 10 +-
.../crawler/components/crawl_rules_table.tsx | 8 +-
.../deduplication_panel.tsx | 8 +-
.../crawler/components/entry_points_table.tsx | 8 +-
.../automatic_crawl_scheduler.tsx | 4 +-
.../components/crawler/crawler_overview.tsx | 10 +-
.../components/credentials/constants.ts | 4 +-
.../credentials_list/credentials_list.tsx | 9 +-
.../curations/components/empty_state.test.tsx | 4 +-
.../curations/components/empty_state.tsx | 9 +-
.../curations_settings.test.tsx | 4 +-
.../curations_settings/curations_settings.tsx | 6 +-
.../api_code_example.tsx | 6 +-
.../document_creation_buttons.tsx | 4 +-
.../documents/components/empty_state.test.tsx | 4 +-
.../documents/components/empty_state.tsx | 9 +-
.../engine_overview_empty.test.tsx | 2 +-
.../engine_overview/engine_overview_empty.tsx | 4 +-
.../empty_meta_engines_state.test.tsx | 4 +-
.../components/empty_meta_engines_state.tsx | 9 +-
.../components/engines/constants.tsx | 4 +-
.../meta_engine_creation/constants.tsx | 4 +-
.../components/empty_state.test.tsx | 4 +-
.../components/empty_state.tsx | 9 +-
.../precision_slider.test.tsx | 4 +-
.../precision_slider/precision_slider.tsx | 8 +-
.../relevance_tuning_callouts.tsx | 4 +-
.../components/empty_state.test.tsx | 4 +-
.../components/empty_state.tsx | 9 +-
.../role_mappings/role_mappings.tsx | 8 +-
.../schema/components/empty_state.test.tsx | 4 +-
.../schema/components/empty_state.tsx | 9 +-
.../search_ui/components/empty_state.test.tsx | 4 +-
.../search_ui/components/empty_state.tsx | 9 +-
.../components/search_ui/search_ui.tsx | 4 +-
.../log_retention/log_retention_panel.tsx | 4 +-
.../components/setup_guide/setup_guide.tsx | 6 +-
.../synonyms/components/empty_state.test.tsx | 4 +-
.../synonyms/components/empty_state.tsx | 9 +-
.../public/applications/app_search/routes.ts | 24 ++-
.../components/setup_guide/setup_guide.tsx | 6 +-
.../shared/doc_links/doc_links.test.ts | 22 +--
.../shared/doc_links/doc_links.ts | 175 ++++++++++++++++--
.../licensing/manage_license_button.test.tsx | 4 +-
.../licensing/manage_license_button.tsx | 7 +-
.../role_mapping/role_mappings_table.tsx | 2 +-
.../shared/role_mapping/user_selector.tsx | 2 +-
.../role_mapping/users_empty_prompt.tsx | 2 +-
.../shared/setup_guide/cloud/instructions.tsx | 10 +-
.../applications/workplace_search/routes.ts | 61 +++---
.../components/oauth_application.test.tsx | 4 +-
.../views/setup_guide/setup_guide.tsx | 12 +-
57 files changed, 585 insertions(+), 244 deletions(-)
diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md
index 5c2c1d5317543..7669b9b644916 100644
--- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md
+++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md
@@ -24,6 +24,9 @@ readonly links: {
readonly canvas: {
readonly guide: string;
};
+ readonly cloud: {
+ readonly indexManagement: string;
+ };
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
@@ -55,10 +58,64 @@ readonly links: {
readonly install: string;
readonly start: string;
};
+ readonly appSearch: {
+ readonly apiRef: string;
+ readonly apiClients: string;
+ readonly apiKeys: string;
+ readonly authentication: string;
+ readonly crawlRules: string;
+ readonly curations: string;
+ readonly duplicateDocuments: string;
+ readonly entryPoints: string;
+ readonly guide: string;
+ readonly indexingDocuments: string;
+ readonly indexingDocumentsSchema: string;
+ readonly logSettings: string;
+ readonly metaEngines: string;
+ readonly nativeAuth: string;
+ readonly precisionTuning: string;
+ readonly relevanceTuning: string;
+ readonly resultSettings: string;
+ readonly searchUI: string;
+ readonly security: string;
+ readonly standardAuth: string;
+ readonly synonyms: string;
+ readonly webCrawler: string;
+ readonly webCrawlerEventLogs: string;
+ };
readonly enterpriseSearch: {
- readonly base: string;
- readonly appSearchBase: string;
- readonly workplaceSearchBase: string;
+ readonly configuration: string;
+ readonly licenseManagement: string;
+ readonly mailService: string;
+ readonly usersAccess: string;
+ };
+ readonly workplaceSearch: {
+ readonly box: string;
+ readonly confluenceCloud: string;
+ readonly confluenceServer: string;
+ readonly customSources: string;
+ readonly customSourcePermissions: string;
+ readonly documentPermissions: string;
+ readonly dropbox: string;
+ readonly externalIdentities: string;
+ readonly gitHub: string;
+ readonly gettingStarted: string;
+ readonly gmail: string;
+ readonly googleDrive: string;
+ readonly indexingSchedule: string;
+ readonly jiraCloud: string;
+ readonly jiraServer: string;
+ readonly nativeAuth: string;
+ readonly oneDrive: string;
+ readonly permissions: string;
+ readonly salesforce: string;
+ readonly security: string;
+ readonly serviceNow: string;
+ readonly sharePoint: string;
+ readonly slack: string;
+ readonly standardAuth: string;
+ readonly synch: string;
+ readonly zendesk: string;
};
readonly heartbeat: {
readonly base: string;
diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md
index cbfe53d3eaea0..6aa528d4f04d1 100644
--- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md
+++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md
@@ -17,5 +17,5 @@ export interface DocLinksStart
| --- | --- | --- |
| [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) | string | |
| [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) | string | |
-| [links](./kibana-plugin-core-public.doclinksstart.links.md) | { readonly settings: string; readonly elasticStackGetStarted: string; readonly upgrade: { readonly upgradingElasticStack: string; }; readonly apm: { readonly kibanaSettings: string; readonly supportedServiceMaps: string; readonly customLinks: string; readonly droppedTransactionSpans: string; readonly upgrading: string; readonly metaData: string; }; readonly canvas: { readonly guide: string; }; readonly dashboard: { readonly guide: string; readonly drilldowns: string; readonly drilldownsTriggerPicker: string; readonly urlDrilldownTemplateSyntax: string; readonly urlDrilldownVariables: string; }; readonly discover: Record<string, string>; readonly filebeat: { readonly base: string; readonly installation: string; readonly configuration: string; readonly elasticsearchOutput: string; readonly elasticsearchModule: string; readonly startup: string; readonly exportedFields: string; readonly suricataModule: string; readonly zeekModule: string; }; readonly auditbeat: { readonly base: string; readonly auditdModule: string; readonly systemModule: string; }; readonly metricbeat: { readonly base: string; readonly configure: string; readonly httpEndpoint: string; readonly install: string; readonly start: string; }; readonly enterpriseSearch: { readonly base: string; readonly appSearchBase: string; readonly workplaceSearchBase: string; }; readonly heartbeat: { readonly base: string; }; readonly libbeat: { readonly getStarted: string; }; readonly logstash: { readonly base: string; }; readonly functionbeat: { readonly base: string; }; readonly winlogbeat: { readonly base: string; }; readonly aggs: { readonly composite: string; readonly composite\_missing\_bucket: string; readonly date\_histogram: string; readonly date\_range: string; readonly date\_format\_pattern: string; readonly filter: string; readonly filters: string; readonly geohash\_grid: string; readonly histogram: string; readonly ip\_range: string; readonly range: string; readonly significant\_terms: string; readonly terms: string; readonly terms\_doc\_count\_error: string; readonly avg: string; readonly avg\_bucket: string; readonly max\_bucket: string; readonly min\_bucket: string; readonly sum\_bucket: string; readonly cardinality: string; readonly count: string; readonly cumulative\_sum: string; readonly derivative: string; readonly geo\_bounds: string; readonly geo\_centroid: string; readonly max: string; readonly median: string; readonly min: string; readonly moving\_avg: string; readonly percentile\_ranks: string; readonly serial\_diff: string; readonly std\_dev: string; readonly sum: string; readonly top\_hits: string; }; readonly runtimeFields: { readonly overview: string; readonly mapping: string; }; readonly scriptedFields: { readonly scriptFields: string; readonly scriptAggs: string; readonly painless: string; readonly painlessApi: string; readonly painlessLangSpec: string; readonly painlessSyntax: string; readonly painlessWalkthrough: string; readonly luceneExpressions: string; }; readonly search: { readonly sessions: string; readonly sessionLimits: string; }; readonly indexPatterns: { readonly introduction: string; readonly fieldFormattersNumber: string; readonly fieldFormattersString: string; readonly runtimeFields: string; }; readonly addData: string; readonly kibana: string; readonly upgradeAssistant: { readonly overview: string; readonly batchReindex: string; readonly remoteReindex: string; }; readonly rollupJobs: string; readonly elasticsearch: Record<string, string>; readonly siem: { readonly privileges: string; readonly guide: string; readonly gettingStarted: string; readonly ml: string; readonly ruleChangeLog: string; readonly detectionsReq: string; readonly networkMap: string; readonly troubleshootGaps: string; }; readonly securitySolution: { readonly trustedApps: string; }; readonly query: { readonly eql: string; readonly kueryQuerySyntax: string; readonly luceneQuerySyntax: string; readonly percolate: string; readonly queryDsl: string; }; readonly date: { readonly dateMath: string; readonly dateMathIndexNames: string; }; readonly management: Record<string, string>; readonly ml: Record<string, string>; readonly transforms: Record<string, string>; readonly visualize: Record<string, string>; readonly apis: Readonly<{ bulkIndexAlias: string; byteSizeUnits: string; createAutoFollowPattern: string; createFollower: string; createIndex: string; createSnapshotLifecyclePolicy: string; createRoleMapping: string; createRoleMappingTemplates: string; createRollupJobsRequest: string; createApiKey: string; createPipeline: string; createTransformRequest: string; cronExpressions: string; executeWatchActionModes: string; indexExists: string; openIndex: string; putComponentTemplate: string; painlessExecute: string; painlessExecuteAPIContexts: string; putComponentTemplateMetadata: string; putSnapshotLifecyclePolicy: string; putIndexTemplateV1: string; putWatch: string; simulatePipeline: string; timeUnits: string; updateTransform: string; }>; readonly observability: Readonly<{ guide: string; infrastructureThreshold: string; logsThreshold: string; metricsThreshold: string; monitorStatus: string; monitorUptime: string; tlsCertificate: string; uptimeDurationAnomaly: string; }>; readonly alerting: Record<string, string>; readonly maps: Readonly<{ guide: string; importGeospatialPrivileges: string; gdalTutorial: string; }>; readonly monitoring: Record<string, string>; readonly security: Readonly<{ apiKeyServiceSettings: string; clusterPrivileges: string; elasticsearchSettings: string; elasticsearchEnableSecurity: string; elasticsearchEnableApiKeys: string; indicesPrivileges: string; kibanaTLS: string; kibanaPrivileges: string; mappingRoles: string; mappingRolesFieldRules: string; runAsPrivilege: string; }>; readonly spaces: Readonly<{ kibanaLegacyUrlAliases: string; kibanaDisableLegacyUrlAliasesApi: string; }>; readonly watcher: Record<string, string>; readonly ccs: Record<string, string>; readonly plugins: Record<string, string>; readonly snapshotRestore: Record<string, string>; readonly ingest: Record<string, string>; readonly fleet: Readonly<{ beatsAgentComparison: string; guide: string; fleetServer: string; fleetServerAddFleetServer: string; settings: string; settingsFleetServerHostSettings: string; settingsFleetServerProxySettings: string; troubleshooting: string; elasticAgent: string; datastreams: string; datastreamsNamingScheme: string; installElasticAgent: string; installElasticAgentStandalone: string; upgradeElasticAgent: string; upgradeElasticAgent712lower: string; learnMoreBlog: string; apiKeysLearnMore: string; onPremRegistry: string; }>; readonly ecs: { readonly guide: string; }; readonly clients: { readonly guide: string; readonly goOverview: string; readonly javaIndex: string; readonly jsIntro: string; readonly netGuide: string; readonly perlGuide: string; readonly phpGuide: string; readonly pythonGuide: string; readonly rubyOverview: string; readonly rustGuide: string; }; readonly endpoints: { readonly troubleshooting: string; }; } | |
+| [links](./kibana-plugin-core-public.doclinksstart.links.md) | { readonly settings: string; readonly elasticStackGetStarted: string; readonly upgrade: { readonly upgradingElasticStack: string; }; readonly apm: { readonly kibanaSettings: string; readonly supportedServiceMaps: string; readonly customLinks: string; readonly droppedTransactionSpans: string; readonly upgrading: string; readonly metaData: string; }; readonly canvas: { readonly guide: string; }; readonly cloud: { readonly indexManagement: string; }; readonly dashboard: { readonly guide: string; readonly drilldowns: string; readonly drilldownsTriggerPicker: string; readonly urlDrilldownTemplateSyntax: string; readonly urlDrilldownVariables: string; }; readonly discover: Record<string, string>; readonly filebeat: { readonly base: string; readonly installation: string; readonly configuration: string; readonly elasticsearchOutput: string; readonly elasticsearchModule: string; readonly startup: string; readonly exportedFields: string; readonly suricataModule: string; readonly zeekModule: string; }; readonly auditbeat: { readonly base: string; readonly auditdModule: string; readonly systemModule: string; }; readonly metricbeat: { readonly base: string; readonly configure: string; readonly httpEndpoint: string; readonly install: string; readonly start: string; }; readonly appSearch: { readonly apiRef: string; readonly apiClients: string; readonly apiKeys: string; readonly authentication: string; readonly crawlRules: string; readonly curations: string; readonly duplicateDocuments: string; readonly entryPoints: string; readonly guide: string; readonly indexingDocuments: string; readonly indexingDocumentsSchema: string; readonly logSettings: string; readonly metaEngines: string; readonly nativeAuth: string; readonly precisionTuning: string; readonly relevanceTuning: string; readonly resultSettings: string; readonly searchUI: string; readonly security: string; readonly standardAuth: string; readonly synonyms: string; readonly webCrawler: string; readonly webCrawlerEventLogs: string; }; readonly enterpriseSearch: { readonly configuration: string; readonly licenseManagement: string; readonly mailService: string; readonly usersAccess: string; }; readonly workplaceSearch: { readonly box: string; readonly confluenceCloud: string; readonly confluenceServer: string; readonly customSources: string; readonly customSourcePermissions: string; readonly documentPermissions: string; readonly dropbox: string; readonly externalIdentities: string; readonly gitHub: string; readonly gettingStarted: string; readonly gmail: string; readonly googleDrive: string; readonly indexingSchedule: string; readonly jiraCloud: string; readonly jiraServer: string; readonly nativeAuth: string; readonly oneDrive: string; readonly permissions: string; readonly salesforce: string; readonly security: string; readonly serviceNow: string; readonly sharePoint: string; readonly slack: string; readonly standardAuth: string; readonly synch: string; readonly zendesk: string; }; readonly heartbeat: { readonly base: string; }; readonly libbeat: { readonly getStarted: string; }; readonly logstash: { readonly base: string; }; readonly functionbeat: { readonly base: string; }; readonly winlogbeat: { readonly base: string; }; readonly aggs: { readonly composite: string; readonly composite\_missing\_bucket: string; readonly date\_histogram: string; readonly date\_range: string; readonly date\_format\_pattern: string; readonly filter: string; readonly filters: string; readonly geohash\_grid: string; readonly histogram: string; readonly ip\_range: string; readonly range: string; readonly significant\_terms: string; readonly terms: string; readonly terms\_doc\_count\_error: string; readonly avg: string; readonly avg\_bucket: string; readonly max\_bucket: string; readonly min\_bucket: string; readonly sum\_bucket: string; readonly cardinality: string; readonly count: string; readonly cumulative\_sum: string; readonly derivative: string; readonly geo\_bounds: string; readonly geo\_centroid: string; readonly max: string; readonly median: string; readonly min: string; readonly moving\_avg: string; readonly percentile\_ranks: string; readonly serial\_diff: string; readonly std\_dev: string; readonly sum: string; readonly top\_hits: string; }; readonly runtimeFields: { readonly overview: string; readonly mapping: string; }; readonly scriptedFields: { readonly scriptFields: string; readonly scriptAggs: string; readonly painless: string; readonly painlessApi: string; readonly painlessLangSpec: string; readonly painlessSyntax: string; readonly painlessWalkthrough: string; readonly luceneExpressions: string; }; readonly search: { readonly sessions: string; readonly sessionLimits: string; }; readonly indexPatterns: { readonly introduction: string; readonly fieldFormattersNumber: string; readonly fieldFormattersString: string; readonly runtimeFields: string; }; readonly addData: string; readonly kibana: string; readonly upgradeAssistant: { readonly overview: string; readonly batchReindex: string; readonly remoteReindex: string; }; readonly rollupJobs: string; readonly elasticsearch: Record<string, string>; readonly siem: { readonly privileges: string; readonly guide: string; readonly gettingStarted: string; readonly ml: string; readonly ruleChangeLog: string; readonly detectionsReq: string; readonly networkMap: string; readonly troubleshootGaps: string; }; readonly securitySolution: { readonly trustedApps: string; }; readonly query: { readonly eql: string; readonly kueryQuerySyntax: string; readonly luceneQuerySyntax: string; readonly percolate: string; readonly queryDsl: string; }; readonly date: { readonly dateMath: string; readonly dateMathIndexNames: string; }; readonly management: Record<string, string>; readonly ml: Record<string, string>; readonly transforms: Record<string, string>; readonly visualize: Record<string, string>; readonly apis: Readonly<{ bulkIndexAlias: string; byteSizeUnits: string; createAutoFollowPattern: string; createFollower: string; createIndex: string; createSnapshotLifecyclePolicy: string; createRoleMapping: string; createRoleMappingTemplates: string; createRollupJobsRequest: string; createApiKey: string; createPipeline: string; createTransformRequest: string; cronExpressions: string; executeWatchActionModes: string; indexExists: string; openIndex: string; putComponentTemplate: string; painlessExecute: string; painlessExecuteAPIContexts: string; putComponentTemplateMetadata: string; putSnapshotLifecyclePolicy: string; putIndexTemplateV1: string; putWatch: string; simulatePipeline: string; timeUnits: string; updateTransform: string; }>; readonly observability: Readonly<{ guide: string; infrastructureThreshold: string; logsThreshold: string; metricsThreshold: string; monitorStatus: string; monitorUptime: string; tlsCertificate: string; uptimeDurationAnomaly: string; }>; readonly alerting: Record<string, string>; readonly maps: Readonly<{ guide: string; importGeospatialPrivileges: string; gdalTutorial: string; }>; readonly monitoring: Record<string, string>; readonly security: Readonly<{ apiKeyServiceSettings: string; clusterPrivileges: string; elasticsearchSettings: string; elasticsearchEnableSecurity: string; elasticsearchEnableApiKeys: string; indicesPrivileges: string; kibanaTLS: string; kibanaPrivileges: string; mappingRoles: string; mappingRolesFieldRules: string; runAsPrivilege: string; }>; readonly spaces: Readonly<{ kibanaLegacyUrlAliases: string; kibanaDisableLegacyUrlAliasesApi: string; }>; readonly watcher: Record<string, string>; readonly ccs: Record<string, string>; readonly plugins: Record<string, string>; readonly snapshotRestore: Record<string, string>; readonly ingest: Record<string, string>; readonly fleet: Readonly<{ beatsAgentComparison: string; guide: string; fleetServer: string; fleetServerAddFleetServer: string; settings: string; settingsFleetServerHostSettings: string; settingsFleetServerProxySettings: string; troubleshooting: string; elasticAgent: string; datastreams: string; datastreamsNamingScheme: string; installElasticAgent: string; installElasticAgentStandalone: string; upgradeElasticAgent: string; upgradeElasticAgent712lower: string; learnMoreBlog: string; apiKeysLearnMore: string; onPremRegistry: string; }>; readonly ecs: { readonly guide: string; }; readonly clients: { readonly guide: string; readonly goOverview: string; readonly javaIndex: string; readonly jsIntro: string; readonly netGuide: string; readonly perlGuide: string; readonly phpGuide: string; readonly pythonGuide: string; readonly rubyOverview: string; readonly rustGuide: string; }; readonly endpoints: { readonly troubleshooting: string; }; } | |
diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts
index 92b4c815f2249..5bc7691d6a40f 100644
--- a/src/core/public/doc_links/doc_links_service.ts
+++ b/src/core/public/doc_links/doc_links_service.ts
@@ -30,6 +30,9 @@ export class DocLinksService {
const APM_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/apm/`;
const SECURITY_SOLUTION_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/`;
const STACK_GETTING_STARTED = `${ELASTIC_WEBSITE_URL}guide/en/elastic-stack-get-started/${DOC_LINK_VERSION}/`;
+ const APP_SEARCH_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/app-search/${DOC_LINK_VERSION}/`;
+ const ENTERPRISE_SEARCH_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/enterprise-search/${DOC_LINK_VERSION}/`;
+ const WORKPLACE_SEARCH_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/workplace-search/${DOC_LINK_VERSION}/`;
return deepFreeze({
DOC_LINK_VERSION,
@@ -51,6 +54,9 @@ export class DocLinksService {
canvas: {
guide: `${KIBANA_DOCS}canvas.html`,
},
+ cloud: {
+ indexManagement: `${ELASTIC_WEBSITE_URL}/guide/en/cloud/current/ec-configure-index-management.html`,
+ },
dashboard: {
guide: `${KIBANA_DOCS}dashboard.html`,
drilldowns: `${KIBANA_DOCS}drilldowns.html`,
@@ -77,10 +83,64 @@ export class DocLinksService {
auditdModule: `${ELASTIC_WEBSITE_URL}guide/en/beats/auditbeat/${DOC_LINK_VERSION}/auditbeat-module-auditd.html`,
systemModule: `${ELASTIC_WEBSITE_URL}guide/en/beats/auditbeat/${DOC_LINK_VERSION}/auditbeat-module-system.html`,
},
+ appSearch: {
+ apiRef: `${APP_SEARCH_DOCS}api-reference.html`,
+ apiClients: `${APP_SEARCH_DOCS}api-clients.html`,
+ apiKeys: `${APP_SEARCH_DOCS}authentication.html#authentication-api-keys`,
+ authentication: `${APP_SEARCH_DOCS}authentication.html`,
+ crawlRules: `${APP_SEARCH_DOCS}crawl-web-content.html#crawl-web-content-manage-crawl-rules`,
+ curations: `${APP_SEARCH_DOCS}curations-guide.html`,
+ duplicateDocuments: `${APP_SEARCH_DOCS}web-crawler-reference.html#web-crawler-reference-content-deduplication`,
+ entryPoints: `${APP_SEARCH_DOCS}crawl-web-content.html#crawl-web-content-manage-entry-points`,
+ guide: `${APP_SEARCH_DOCS}index.html`,
+ indexingDocuments: `${APP_SEARCH_DOCS}indexing-documents-guide.html`,
+ indexingDocumentsSchema: `${APP_SEARCH_DOCS}indexing-documents-guide.html#indexing-documents-guide-schema`,
+ logSettings: `${APP_SEARCH_DOCS}logs.html`,
+ metaEngines: `${APP_SEARCH_DOCS}meta-engines-guide.html`,
+ nativeAuth: `${APP_SEARCH_DOCS}security-and-users.html#app-search-self-managed-security-and-user-management-elasticsearch-native-realm`,
+ precisionTuning: `${APP_SEARCH_DOCS}precision-tuning.html`,
+ relevanceTuning: `${APP_SEARCH_DOCS}relevance-tuning-guide.html`,
+ resultSettings: `${APP_SEARCH_DOCS}result-settings-guide.html`,
+ searchUI: `${APP_SEARCH_DOCS}reference-ui-guide.html`,
+ security: `${APP_SEARCH_DOCS}security-and-users.html`,
+ standardAuth: `${APP_SEARCH_DOCS}security-and-users.html#app-search-self-managed-security-and-user-management-standard`,
+ synonyms: `${APP_SEARCH_DOCS}synonyms-guide.html`,
+ webCrawler: `${APP_SEARCH_DOCS}web-crawler.html`,
+ webCrawlerEventLogs: `${APP_SEARCH_DOCS}view-web-crawler-events-logs.html`,
+ },
enterpriseSearch: {
- base: `${ELASTIC_WEBSITE_URL}guide/en/enterprise-search/${DOC_LINK_VERSION}`,
- appSearchBase: `${ELASTIC_WEBSITE_URL}guide/en/app-search/${DOC_LINK_VERSION}`,
- workplaceSearchBase: `${ELASTIC_WEBSITE_URL}guide/en/workplace-search/${DOC_LINK_VERSION}`,
+ configuration: `${ENTERPRISE_SEARCH_DOCS}configuration.html`,
+ licenseManagement: `${ENTERPRISE_SEARCH_DOCS}license-management.html`,
+ mailService: `${ENTERPRISE_SEARCH_DOCS}mailer-configuration.html`,
+ usersAccess: `${ENTERPRISE_SEARCH_DOCS}users-access.html`,
+ },
+ workplaceSearch: {
+ box: `${WORKPLACE_SEARCH_DOCS}workplace-search-box-connector.html`,
+ confluenceCloud: `${WORKPLACE_SEARCH_DOCS}workplace-search-confluence-cloud-connector.html`,
+ confluenceServer: `${WORKPLACE_SEARCH_DOCS}workplace-search-confluence-server-connector.html`,
+ customSources: `${WORKPLACE_SEARCH_DOCS}workplace-search-custom-api-sources.html`,
+ customSourcePermissions: `${WORKPLACE_SEARCH_DOCS}workplace-search-custom-api-sources.html#custom-api-source-document-level-access-control`,
+ documentPermissions: `${WORKPLACE_SEARCH_DOCS}workplace-search-sources-document-permissions.html`,
+ dropbox: `${WORKPLACE_SEARCH_DOCS}workplace-search-dropbox-connector.html`,
+ externalIdentities: `${WORKPLACE_SEARCH_DOCS}workplace-search-external-identities-api.html`,
+ gettingStarted: `${WORKPLACE_SEARCH_DOCS}workplace-search-getting-started.html`,
+ gitHub: `${WORKPLACE_SEARCH_DOCS}workplace-search-github-connector.html`,
+ gmail: `${WORKPLACE_SEARCH_DOCS}workplace-search-gmail-connector.html`,
+ googleDrive: `${WORKPLACE_SEARCH_DOCS}workplace-search-google-drive-connector.html`,
+ indexingSchedule: `${WORKPLACE_SEARCH_DOCS}workplace-search-customizing-indexing-rules.html#_indexing_schedule`,
+ jiraCloud: `${WORKPLACE_SEARCH_DOCS}workplace-search-jira-cloud-connector.html`,
+ jiraServer: `${WORKPLACE_SEARCH_DOCS}workplace-search-jira-server-connector.html`,
+ nativeAuth: `${WORKPLACE_SEARCH_DOCS}workplace-search-security.html#elasticsearch-native-realm`,
+ oneDrive: `${WORKPLACE_SEARCH_DOCS}workplace-search-onedrive-connector.html`,
+ permissions: `${WORKPLACE_SEARCH_DOCS}workplace-search-permissions.html#organizational-sources-private-sources`,
+ salesforce: `${WORKPLACE_SEARCH_DOCS}workplace-search-salesforce-connector.html`,
+ security: `${WORKPLACE_SEARCH_DOCS}workplace-search-security.html`,
+ serviceNow: `${WORKPLACE_SEARCH_DOCS}workplace-search-servicenow-connector.html`,
+ sharePoint: `${WORKPLACE_SEARCH_DOCS}workplace-search-sharepoint-online-connector.html`,
+ slack: `${WORKPLACE_SEARCH_DOCS}workplace-search-slack-connector.html`,
+ standardAuth: `${WORKPLACE_SEARCH_DOCS}workplace-search-security.html#standard`,
+ synch: `${WORKPLACE_SEARCH_DOCS}workplace-search-customizing-indexing-rules.html`,
+ zendesk: `${WORKPLACE_SEARCH_DOCS}workplace-search-zendesk-connector.html`,
},
metricbeat: {
base: `${ELASTIC_WEBSITE_URL}guide/en/beats/metricbeat/${DOC_LINK_VERSION}`,
@@ -550,6 +610,9 @@ export interface DocLinksStart {
readonly canvas: {
readonly guide: string;
};
+ readonly cloud: {
+ readonly indexManagement: string;
+ };
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
@@ -581,10 +644,64 @@ export interface DocLinksStart {
readonly install: string;
readonly start: string;
};
+ readonly appSearch: {
+ readonly apiRef: string;
+ readonly apiClients: string;
+ readonly apiKeys: string;
+ readonly authentication: string;
+ readonly crawlRules: string;
+ readonly curations: string;
+ readonly duplicateDocuments: string;
+ readonly entryPoints: string;
+ readonly guide: string;
+ readonly indexingDocuments: string;
+ readonly indexingDocumentsSchema: string;
+ readonly logSettings: string;
+ readonly metaEngines: string;
+ readonly nativeAuth: string;
+ readonly precisionTuning: string;
+ readonly relevanceTuning: string;
+ readonly resultSettings: string;
+ readonly searchUI: string;
+ readonly security: string;
+ readonly standardAuth: string;
+ readonly synonyms: string;
+ readonly webCrawler: string;
+ readonly webCrawlerEventLogs: string;
+ };
readonly enterpriseSearch: {
- readonly base: string;
- readonly appSearchBase: string;
- readonly workplaceSearchBase: string;
+ readonly configuration: string;
+ readonly licenseManagement: string;
+ readonly mailService: string;
+ readonly usersAccess: string;
+ };
+ readonly workplaceSearch: {
+ readonly box: string;
+ readonly confluenceCloud: string;
+ readonly confluenceServer: string;
+ readonly customSources: string;
+ readonly customSourcePermissions: string;
+ readonly documentPermissions: string;
+ readonly dropbox: string;
+ readonly externalIdentities: string;
+ readonly gitHub: string;
+ readonly gettingStarted: string;
+ readonly gmail: string;
+ readonly googleDrive: string;
+ readonly indexingSchedule: string;
+ readonly jiraCloud: string;
+ readonly jiraServer: string;
+ readonly nativeAuth: string;
+ readonly oneDrive: string;
+ readonly permissions: string;
+ readonly salesforce: string;
+ readonly security: string;
+ readonly serviceNow: string;
+ readonly sharePoint: string;
+ readonly slack: string;
+ readonly standardAuth: string;
+ readonly synch: string;
+ readonly zendesk: string;
};
readonly heartbeat: {
readonly base: string;
diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md
index 772faa5321d98..cec80af843c4c 100644
--- a/src/core/public/public.api.md
+++ b/src/core/public/public.api.md
@@ -506,6 +506,9 @@ export interface DocLinksStart {
readonly canvas: {
readonly guide: string;
};
+ readonly cloud: {
+ readonly indexManagement: string;
+ };
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
@@ -537,10 +540,64 @@ export interface DocLinksStart {
readonly install: string;
readonly start: string;
};
+ readonly appSearch: {
+ readonly apiRef: string;
+ readonly apiClients: string;
+ readonly apiKeys: string;
+ readonly authentication: string;
+ readonly crawlRules: string;
+ readonly curations: string;
+ readonly duplicateDocuments: string;
+ readonly entryPoints: string;
+ readonly guide: string;
+ readonly indexingDocuments: string;
+ readonly indexingDocumentsSchema: string;
+ readonly logSettings: string;
+ readonly metaEngines: string;
+ readonly nativeAuth: string;
+ readonly precisionTuning: string;
+ readonly relevanceTuning: string;
+ readonly resultSettings: string;
+ readonly searchUI: string;
+ readonly security: string;
+ readonly standardAuth: string;
+ readonly synonyms: string;
+ readonly webCrawler: string;
+ readonly webCrawlerEventLogs: string;
+ };
readonly enterpriseSearch: {
- readonly base: string;
- readonly appSearchBase: string;
- readonly workplaceSearchBase: string;
+ readonly configuration: string;
+ readonly licenseManagement: string;
+ readonly mailService: string;
+ readonly usersAccess: string;
+ };
+ readonly workplaceSearch: {
+ readonly box: string;
+ readonly confluenceCloud: string;
+ readonly confluenceServer: string;
+ readonly customSources: string;
+ readonly customSourcePermissions: string;
+ readonly documentPermissions: string;
+ readonly dropbox: string;
+ readonly externalIdentities: string;
+ readonly gitHub: string;
+ readonly gettingStarted: string;
+ readonly gmail: string;
+ readonly googleDrive: string;
+ readonly indexingSchedule: string;
+ readonly jiraCloud: string;
+ readonly jiraServer: string;
+ readonly nativeAuth: string;
+ readonly oneDrive: string;
+ readonly permissions: string;
+ readonly salesforce: string;
+ readonly security: string;
+ readonly serviceNow: string;
+ readonly sharePoint: string;
+ readonly slack: string;
+ readonly standardAuth: string;
+ readonly synch: string;
+ readonly zendesk: string;
};
readonly heartbeat: {
readonly base: string;
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/empty_state.test.tsx
index 19f45ced5dc5d..cb1c34a19c018 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/empty_state.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/empty_state.test.tsx
@@ -11,6 +11,8 @@ import { shallow } from 'enzyme';
import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';
+import { docLinks } from '../../../../shared/doc_links';
+
import { EmptyState } from './';
describe('EmptyState', () => {
@@ -21,7 +23,7 @@ describe('EmptyState', () => {
expect(wrapper.find('h2').text()).toEqual('No API events in the last 24 hours');
expect(wrapper.find(EuiButton).prop('href')).toEqual(
- expect.stringContaining('/api-reference.html')
+ expect.stringContaining(docLinks.appSearchApis)
);
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/empty_state.tsx
index 76bd0cba1731f..c78bf3e918737 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/empty_state.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/empty_state.tsx
@@ -8,9 +8,10 @@
import React from 'react';
import { EuiButton, EuiEmptyPrompt } from '@elastic/eui';
+
import { i18n } from '@kbn/i18n';
-import { DOCS_PREFIX } from '../../../routes';
+import { API_DOCS_URL } from '../../../routes';
export const EmptyState: React.FC = () => (
(
}
actions={
-
+
{i18n.translate('xpack.enterpriseSearch.appSearch.engine.apiLogs.empty.buttonLabel', {
defaultMessage: 'View the API reference',
})}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_rules_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_rules_table.tsx
index d447db60fb25b..bef8ed4462fdc 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_rules_table.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_rules_table.tsx
@@ -27,7 +27,7 @@ import { clearFlashMessages, flashSuccessToast } from '../../../../shared/flash_
import { GenericEndpointInlineEditableTable } from '../../../../shared/tables/generic_endpoint_inline_editable_table';
import { InlineEditableTableColumn } from '../../../../shared/tables/inline_editable_table/types';
import { ItemWithAnID } from '../../../../shared/tables/types';
-import { DOCS_PREFIX } from '../../../routes';
+import { CRAWL_RULES_DOCS_URL } from '../../../routes';
import { CrawlerSingleDomainLogic } from '../crawler_single_domain_logic';
import {
CrawlerPolicies,
@@ -53,11 +53,7 @@ const DEFAULT_DESCRIPTION = (
defaultMessage="Create a crawl rule to include or exclude pages whose URL matches the rule. Rules run in sequential order, and each URL is evaluated according to the first match. {link}"
values={{
link: (
-
+
{i18n.translate(
'xpack.enterpriseSearch.appSearch.crawler.crawlRulesTable.descriptionLinkText',
{ defaultMessage: 'Learn more about crawl rules' }
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/deduplication_panel/deduplication_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/deduplication_panel/deduplication_panel.tsx
index ea894e2b00acf..26794d0421353 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/deduplication_panel/deduplication_panel.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/deduplication_panel/deduplication_panel.tsx
@@ -27,7 +27,7 @@ import { EuiSelectableLIOption } from '@elastic/eui/src/components/selectable/se
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
-import { DOCS_PREFIX } from '../../../../routes';
+import { DUPLICATE_DOCS_URL } from '../../../../routes';
import { DataPanel } from '../../../data_panel';
import { CrawlerSingleDomainLogic } from '../../crawler_single_domain_logic';
@@ -84,11 +84,7 @@ export const DeduplicationPanel: React.FC = () => {
documents on this domain. {documentationLink}."
values={{
documentationLink: (
-
+
{i18n.translate(
'xpack.enterpriseSearch.appSearch.crawler.deduplicationPanel.learnMoreMessage',
{
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/entry_points_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/entry_points_table.tsx
index aaf3cc4516067..4fc7a0569ba0e 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/entry_points_table.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/entry_points_table.tsx
@@ -17,7 +17,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { GenericEndpointInlineEditableTable } from '../../../../shared/tables/generic_endpoint_inline_editable_table';
import { InlineEditableTableColumn } from '../../../../shared/tables/inline_editable_table/types';
import { ItemWithAnID } from '../../../../shared/tables/types';
-import { DOCS_PREFIX } from '../../../routes';
+import { ENTRY_POINTS_DOCS_URL } from '../../../routes';
import { CrawlerDomain, EntryPoint } from '../types';
import { EntryPointsTableLogic } from './entry_points_table_logic';
@@ -80,11 +80,7 @@ export const EntryPointsTable: React.FC = ({
defaultMessage:
'Include the most important URLs for your website here. Entry point URLs will be the first pages to be indexed and processed for links to other pages.',
})}{' '}
-
+
{i18n.translate(
'xpack.enterpriseSearch.appSearch.crawler.entryPointsTable.learnMoreLinkText',
{ defaultMessage: 'Learn more about entry points.' }
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/manage_crawls_popover/automatic_crawl_scheduler.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/manage_crawls_popover/automatic_crawl_scheduler.tsx
index 5f7200cb826df..128dcdcb778cf 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/manage_crawls_popover/automatic_crawl_scheduler.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/manage_crawls_popover/automatic_crawl_scheduler.tsx
@@ -37,7 +37,7 @@ import {
} from '../../../../..//shared/constants/units';
import { CANCEL_BUTTON_LABEL, SAVE_BUTTON_LABEL } from '../../../../../shared/constants';
-import { DOCS_PREFIX } from '../../../../routes';
+import { WEB_CRAWLER_DOCS_URL } from '../../../../routes';
import { CrawlUnits } from '../../types';
import { AutomaticCrawlSchedulerLogic } from './automatic_crawl_scheduler_logic';
@@ -81,7 +81,7 @@ export const AutomaticCrawlScheduler: React.FC = () => {
defaultMessage="Don't worry about it, we'll start a crawl for you. {readMoreMessage}."
values={{
readMoreMessage: (
-
+
{i18n.translate(
'xpack.enterpriseSearch.appSearch.crawler.automaticCrawlSchedule.readMoreLink',
{
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_overview.tsx
index 6c3cb51111ae1..c84deb3cb0c99 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_overview.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_overview.tsx
@@ -13,7 +13,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiLink, EuiSpacer, EuiText, EuiTitle } from
import { i18n } from '@kbn/i18n';
-import { DOCS_PREFIX } from '../../routes';
+import { WEB_CRAWLER_DOCS_URL, WEB_CRAWLER_LOG_DOCS_URL } from '../../routes';
import { getEngineBreadcrumbs } from '../engine';
import { AppSearchPageTemplate } from '../layout';
@@ -77,7 +77,7 @@ export const CrawlerOverview: React.FC = () => {
defaultMessage:
"Easily index your website's content. To get started, enter your domain name, provide optional entry points and crawl rules, and we will handle the rest.",
})}{' '}
-
+
{i18n.translate(
'xpack.enterpriseSearch.appSearch.crawler.empty.crawlerDocumentationLinkDescription',
{
@@ -114,11 +114,7 @@ export const CrawlerOverview: React.FC = () => {
defaultMessage:
"Recent crawl requests are logged here. Using the request ID of each crawl, you can track progress and examine crawl events in Kibana's Discover or Logs user interfaces.",
})}{' '}
-
+
{i18n.translate(
'xpack.enterpriseSearch.appSearch.crawler.configurationDocumentationLinkDescription',
{
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts
index 6a5f3df0e86f6..315b4d864b3f2 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts
@@ -7,7 +7,7 @@
import { i18n } from '@kbn/i18n';
-import { DOCS_PREFIX } from '../../routes';
+import { AUTHENTICATION_DOCS_URL } from '../../routes';
export const CREDENTIALS_TITLE = i18n.translate(
'xpack.enterpriseSearch.appSearch.credentials.title',
@@ -109,4 +109,4 @@ export const TOKEN_TYPE_INFO = [
export const FLYOUT_ARIA_LABEL_ID = 'credentialsFlyoutTitle';
-export const DOCS_HREF = `${DOCS_PREFIX}/authentication.html`;
+export const DOCS_HREF = AUTHENTICATION_DOCS_URL;
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.tsx
index 040f313b12205..3ea2c022ec489 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.tsx
@@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { EDIT_BUTTON_LABEL, DELETE_BUTTON_LABEL } from '../../../../shared/constants';
import { HiddenText } from '../../../../shared/hidden_text';
import { convertMetaToPagination, handlePageChange } from '../../../../shared/table_pagination';
-import { DOCS_PREFIX } from '../../../routes';
+import { API_KEYS_DOCS_URL } from '../../../routes';
import { TOKEN_TYPE_DISPLAY_NAMES } from '../constants';
import { CredentialsLogic } from '../credentials_logic';
import { ApiToken } from '../types';
@@ -141,12 +141,7 @@ export const CredentialsList: React.FC = () => {
defaultMessage: 'Allow applications to access Elastic App Search on your behalf.',
})}
actions={
-
+
{i18n.translate('xpack.enterpriseSearch.appSearch.credentials.empty.buttonLabel', {
defaultMessage: 'Learn about API keys',
})}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/empty_state.test.tsx
index 60ae386bea58e..69c2cc4b987b1 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/empty_state.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/empty_state.test.tsx
@@ -11,6 +11,8 @@ import { shallow } from 'enzyme';
import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';
+import { docLinks } from '../../../../shared/doc_links';
+
import { EmptyState } from './';
describe('EmptyState', () => {
@@ -21,7 +23,7 @@ describe('EmptyState', () => {
expect(wrapper.find('h2').text()).toEqual('Create your first curation');
expect(wrapper.find(EuiButton).prop('href')).toEqual(
- expect.stringContaining('/curations-guide.html')
+ expect.stringContaining(docLinks.appSearchCurations)
);
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/empty_state.tsx
index 872a7282136e3..10d81f1623959 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/empty_state.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/empty_state.tsx
@@ -10,7 +10,7 @@ import React from 'react';
import { EuiButton, EuiEmptyPrompt } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { DOCS_PREFIX } from '../../../routes';
+import { CURATIONS_DOCS_URL } from '../../../routes';
export const EmptyState: React.FC = () => (
(
}
actions={
-
+
{i18n.translate('xpack.enterpriseSearch.appSearch.engine.curations.empty.buttonLabel', {
defaultMessage: 'Read the curations guide',
})}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings.test.tsx
index 4b4e11c31d4b8..b95ae0bca5bf6 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings.test.tsx
@@ -19,6 +19,8 @@ import { EuiButtonEmpty, EuiCallOut, EuiSwitch } from '@elastic/eui';
import { mountWithIntl } from '@kbn/test/jest';
+import { docLinks } from '../../../../../shared/doc_links';
+
import { Loading } from '../../../../../shared/loading';
import { EuiButtonTo } from '../../../../../shared/react_router_helpers';
import { DataPanel } from '../../../data_panel';
@@ -227,7 +229,7 @@ describe('CurationsSettings', () => {
const wrapper = shallow();
expect(wrapper.is(DataPanel)).toBe(true);
expect(wrapper.prop('action').props.to).toEqual('/app/management/stack/license_management');
- expect(wrapper.find(EuiButtonEmpty).prop('href')).toEqual('/license-management.html');
+ expect(wrapper.find(EuiButtonEmpty).prop('href')).toEqual(docLinks.licenseManagement);
});
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings.tsx
index d78ca852ee7d1..ffefea96d3a22 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings.tsx
@@ -110,11 +110,7 @@ export const CurationsSettings: React.FC = () => {
}
>
-
+
{i18n.translate('xpack.enterpriseSearch.curations.settings.licenseUpgradeLink', {
defaultMessage: 'Learn more about license upgrades',
})}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/api_code_example.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/api_code_example.tsx
index 793c6250d859c..e86b06b423a9d 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/api_code_example.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/api_code_example.tsx
@@ -30,7 +30,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { CANCEL_BUTTON_LABEL } from '../../../../shared/constants';
import { getEnterpriseSearchUrl } from '../../../../shared/enterprise_search_url';
-import { DOCS_PREFIX } from '../../../routes';
+import { API_CLIENTS_DOCS_URL, INDEXING_DOCS_URL } from '../../../routes';
import { EngineLogic } from '../../engine';
import { EngineDetails } from '../../engine/types';
@@ -74,12 +74,12 @@ export const FlyoutBody: React.FC = () => {
defaultMessage="The {documentsApiLink} can be used to add new documents to your engine, update documents, retrieve documents by id, and delete documents. There are a variety of {clientLibrariesLink} to help you get started."
values={{
documentsApiLink: (
-
+
documents API
),
clientLibrariesLink: (
-
+
client libraries
),
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_buttons.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_buttons.tsx
index 5366c00c0e7fc..a8179f297644f 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_buttons.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_buttons.tsx
@@ -27,7 +27,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { parseQueryParams } from '../../../shared/query_params';
import { EuiCardTo } from '../../../shared/react_router_helpers';
-import { DOCS_PREFIX, ENGINE_CRAWLER_PATH } from '../../routes';
+import { INDEXING_DOCS_URL, ENGINE_CRAWLER_PATH } from '../../routes';
import { generateEnginePath } from '../engine';
import { DocumentCreationLogic } from './';
@@ -66,7 +66,7 @@ export const DocumentCreationButtons: React.FC = ({ disabled = false }) =
jsonCode: .json,
postCode: POST,
documentsApiLink: (
-
+
documents API
),
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/empty_state.test.tsx
index 907dcf8c9c208..b8bb26fa9ad63 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/empty_state.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/empty_state.test.tsx
@@ -11,6 +11,8 @@ import { shallow } from 'enzyme';
import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';
+import { docLinks } from '../../../../shared/doc_links';
+
import { EmptyState } from './';
describe('EmptyState', () => {
@@ -21,7 +23,7 @@ describe('EmptyState', () => {
expect(wrapper.find('h2').text()).toEqual('Add your first documents');
expect(wrapper.find(EuiButton).prop('href')).toEqual(
- expect.stringContaining('/indexing-documents-guide.html')
+ expect.stringContaining(docLinks.appSearchIndexingDocs)
);
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/empty_state.tsx
index 39fe02a84854c..85e834b320751 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/empty_state.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/empty_state.tsx
@@ -10,7 +10,7 @@ import React from 'react';
import { EuiButton, EuiEmptyPrompt } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { DOCS_PREFIX } from '../../../routes';
+import { INDEXING_DOCS_URL } from '../../../routes';
export const EmptyState = () => (
(
}
actions={
-
+
{i18n.translate('xpack.enterpriseSearch.appSearch.engine.documents.empty.buttonLabel', {
defaultMessage: 'Read the documents guide',
})}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.test.tsx
index 6750ebf1140e0..54bc7fb26e9d0 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.test.tsx
@@ -33,7 +33,7 @@ describe('EmptyEngineOverview', () => {
it('renders a documentation link', () => {
expect(getPageHeaderActions(wrapper).find(EuiButton).prop('href')).toEqual(
- `${docLinks.appSearchBase}/index.html`
+ docLinks.appSearchGuide
);
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx
index 6f8332e1e332e..ada2df654d52b 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx
@@ -10,7 +10,7 @@ import React from 'react';
import { EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { DOCS_PREFIX } from '../../routes';
+import { DOCS_URL } from '../../routes';
import { DocumentCreationButtons, DocumentCreationFlyout } from '../document_creation';
import { getEngineBreadcrumbs } from '../engine';
@@ -26,7 +26,7 @@ export const EmptyEngineOverview: React.FC = () => {
{ defaultMessage: 'Engine setup' }
),
rightSideItems: [
-
+
{i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.overview.empty.headingAction',
{ defaultMessage: 'View documentation' }
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_meta_engines_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_meta_engines_state.test.tsx
index 8b4f5a69b8141..350412825b996 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_meta_engines_state.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_meta_engines_state.test.tsx
@@ -11,6 +11,8 @@ import { shallow } from 'enzyme';
import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';
+import { docLinks } from '../../../../shared/doc_links';
+
import { EmptyMetaEnginesState } from './';
describe('EmptyMetaEnginesState', () => {
@@ -21,7 +23,7 @@ describe('EmptyMetaEnginesState', () => {
expect(wrapper.find('h3').text()).toEqual('Create your first meta engine');
expect(wrapper.find(EuiButton).prop('href')).toEqual(
- expect.stringContaining('/meta-engines-guide.html')
+ expect.stringContaining(docLinks.appSearchMetaEngines)
);
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_meta_engines_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_meta_engines_state.tsx
index ad96f21022f2b..3cf461e3f7d45 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_meta_engines_state.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_meta_engines_state.tsx
@@ -10,7 +10,7 @@ import React from 'react';
import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { DOCS_PREFIX } from '../../../routes';
+import { META_ENGINES_DOCS_URL } from '../../../routes';
export const EmptyMetaEnginesState: React.FC = () => (
(
}
actions={
-
+
{i18n.translate(
'xpack.enterpriseSearch.appSearch.engines.metaEngines.emptyPromptButtonLabel',
{ defaultMessage: 'Learn more about meta engines' }
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.tsx
index 8fbbf406cf5d3..bf2a122ead42b 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.tsx
@@ -11,7 +11,7 @@ import { EuiLink } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
-import { DOCS_PREFIX } from '../../routes';
+import { META_ENGINES_DOCS_URL } from '../../routes';
import {
META_ENGINE_CREATION_FORM_META_ENGINE_DESCRIPTION,
META_ENGINE_CREATION_FORM_DOCUMENTATION_LINK,
@@ -40,7 +40,7 @@ export const META_ENGINES_DESCRIPTION = (
defaultMessage="{readDocumentationLink} for more information or upgrade to a Platinum license to get started."
values={{
readDocumentationLink: (
-
+
{META_ENGINE_CREATION_FORM_DOCUMENTATION_LINK}
),
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/constants.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/constants.tsx
index af7b6f3201b3e..e41809054e123 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/constants.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/constants.tsx
@@ -11,7 +11,7 @@ import { EuiLink } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
-import { DOCS_PREFIX } from '../../routes';
+import { META_ENGINES_DOCS_URL } from '../../routes';
export const DEFAULT_LANGUAGE = 'Universal';
@@ -57,7 +57,7 @@ export const META_ENGINE_CREATION_FORM_DOCUMENTATION_DESCRIPTION = (
defaultMessage="{documentationLink} for information about how to get started."
values={{
documentationLink: (
-
+
{META_ENGINE_CREATION_FORM_DOCUMENTATION_LINK}
),
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/empty_state.test.tsx
index a60f68c19f6dc..454437a203bc2 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/empty_state.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/empty_state.test.tsx
@@ -11,6 +11,8 @@ import { shallow } from 'enzyme';
import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';
+import { docLinks } from '../../../../shared/doc_links';
+
import { EmptyState } from './';
describe('EmptyState', () => {
@@ -21,7 +23,7 @@ describe('EmptyState', () => {
expect(wrapper.find('h2').text()).toEqual('Add documents to tune relevance');
expect(wrapper.find(EuiButton).prop('href')).toEqual(
- expect.stringContaining('/relevance-tuning-guide.html')
+ expect.stringContaining(docLinks.appSearchRelevance)
);
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/empty_state.tsx
index df29010bd682f..f17f7a582efdf 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/empty_state.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/empty_state.tsx
@@ -10,7 +10,7 @@ import React from 'react';
import { EuiButton, EuiEmptyPrompt } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { DOCS_PREFIX } from '../../../routes';
+import { RELEVANCE_DOCS_URL } from '../../../routes';
export const EmptyState: React.FC = () => (
(
}
)}
actions={
-
+
{i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.relevanceTuning.empty.buttonLabel',
{ defaultMessage: 'Read the relevance tuning guide' }
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/precision_slider/precision_slider.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/precision_slider/precision_slider.test.tsx
index 3be30b77bc2e4..0554b31c88356 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/precision_slider/precision_slider.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/precision_slider/precision_slider.test.tsx
@@ -11,6 +11,8 @@ import React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
+import { docLinks } from '../../../../../shared/doc_links';
+
import { rerender } from '../../../../../test_helpers';
import { STEP_DESCRIPTIONS } from './constants';
@@ -82,7 +84,7 @@ describe('PrecisionSlider', () => {
it('contains a documentation link', () => {
const documentationLink = wrapper.find('[data-test-subj="documentationLink"]');
- expect(documentationLink.prop('href')).toContain('/precision-tuning.html');
+ expect(documentationLink.prop('href')).toContain(docLinks.appSearchPrecision);
expect(documentationLink.prop('target')).toEqual('_blank');
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/precision_slider/precision_slider.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/precision_slider/precision_slider.tsx
index 8e7a59c290ce2..e4b2027aa3d6d 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/precision_slider/precision_slider.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/precision_slider/precision_slider.tsx
@@ -21,7 +21,7 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { DOCS_PREFIX } from '../../../../routes';
+import { PRECISION_DOCS_URL } from '../../../../routes';
import { RelevanceTuningLogic } from '../../relevance_tuning_logic';
import { STEP_DESCRIPTIONS } from './constants';
@@ -57,11 +57,7 @@ export const PrecisionSlider: React.FC = () => {
defaultMessage: 'Fine tune the precision vs. recall settings on your engine.',
}
)}{' '}
-
+
{i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.relevanceTuning.precisionSlider.learnMore.link',
{
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_callouts.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_callouts.tsx
index d8963b33b8ab2..463c61fb60c99 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_callouts.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_callouts.tsx
@@ -14,7 +14,7 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { EuiLinkTo } from '../../../shared/react_router_helpers';
-import { DOCS_PREFIX, ENGINE_SCHEMA_PATH } from '../../routes';
+import { META_ENGINES_DOCS_URL, ENGINE_SCHEMA_PATH } from '../../routes';
import { EngineLogic, generateEnginePath } from '../engine';
import { RelevanceTuningLogic } from '.';
@@ -98,7 +98,7 @@ export const RelevanceTuningCallouts: React.FC = () => {
values={{
schemaFieldsWithConflictsCount,
link: (
-
+
{i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.relevanceTuning.whatsThisLinkLabel',
{
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/empty_state.test.tsx
index 537fd9ec6a0d4..8798c1a4bc529 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/empty_state.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/empty_state.test.tsx
@@ -11,6 +11,8 @@ import { shallow } from 'enzyme';
import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';
+import { docLinks } from '../../../../shared/doc_links';
+
import { EmptyState } from './';
describe('EmptyState', () => {
@@ -21,7 +23,7 @@ describe('EmptyState', () => {
expect(wrapper.find('h2').text()).toEqual('Add documents to adjust settings');
expect(wrapper.find(EuiButton).prop('href')).toEqual(
- expect.stringContaining('/result-settings-guide.html')
+ expect.stringContaining(docLinks.appSearchResultSettings)
);
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/empty_state.tsx
index dae8390a35fd7..7f91447b910b6 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/empty_state.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/empty_state.tsx
@@ -10,7 +10,7 @@ import React from 'react';
import { EuiButton, EuiEmptyPrompt } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { DOCS_PREFIX } from '../../../routes';
+import { RESULT_SETTINGS_DOCS_URL } from '../../../routes';
export const EmptyState: React.FC = () => (
(
}
)}
actions={
-
+
{i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.resultSettings.empty.buttonLabel',
{ defaultMessage: 'Read the result settings guide' }
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.tsx
index 3e692aa48623e..e2021ac582d0c 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings.tsx
@@ -22,7 +22,7 @@ import {
} from '../../../shared/role_mapping';
import { ROLE_MAPPINGS_TITLE } from '../../../shared/role_mapping/constants';
-import { DOCS_PREFIX } from '../../routes';
+import { SECURITY_DOCS_URL } from '../../routes';
import { AppSearchPageTemplate } from '../layout';
import { ROLE_MAPPINGS_ENGINE_ACCESS_HEADING } from './constants';
@@ -30,8 +30,6 @@ import { RoleMapping } from './role_mapping';
import { RoleMappingsLogic } from './role_mappings_logic';
import { User } from './user';
-const ROLES_DOCS_LINK = `${DOCS_PREFIX}/security-and-users.html`;
-
export const RoleMappings: React.FC = () => {
const {
enableRoleBasedAccess,
@@ -60,7 +58,7 @@ export const RoleMappings: React.FC = () => {
const rolesEmptyState = (
);
@@ -69,7 +67,7 @@ export const RoleMappings: React.FC = () => {
initializeRoleMapping()}
/>
{
expect(wrapper.find('h2').text()).toEqual('Create a schema');
expect(wrapper.find(EuiButton).prop('href')).toEqual(
- expect.stringContaining('#indexing-documents-guide-schema')
+ expect.stringContaining(docLinks.appSearchIndexingDocsSchema)
);
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/components/empty_state.tsx
index ad9285c7b8fef..3c2d5fc4df66a 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/components/empty_state.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/components/empty_state.tsx
@@ -13,7 +13,7 @@ import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { SchemaAddFieldModal } from '../../../../shared/schema';
-import { DOCS_PREFIX } from '../../../routes';
+import { INDEXING_SCHEMA_DOCS_URL } from '../../../routes';
import { SchemaLogic } from '../schema_logic';
export const EmptyState: React.FC = () => {
@@ -40,12 +40,7 @@ export const EmptyState: React.FC = () => {
}
actions={
-
+
{i18n.translate('xpack.enterpriseSearch.appSearch.engine.schema.empty.buttonLabel', {
defaultMessage: 'Read the indexing schema guide',
})}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/components/empty_state.test.tsx
index 39f0cb376b325..3466542c09739 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/components/empty_state.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/components/empty_state.test.tsx
@@ -11,6 +11,8 @@ import { shallow } from 'enzyme';
import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';
+import { docLinks } from '../../../../shared/doc_links';
+
import { EmptyState } from './empty_state';
describe('EmptyState', () => {
@@ -21,7 +23,7 @@ describe('EmptyState', () => {
expect(wrapper.find('h2').text()).toEqual('Add documents to generate a Search UI');
expect(wrapper.find(EuiButton).prop('href')).toEqual(
- expect.stringContaining('/reference-ui-guide.html')
+ expect.stringContaining(docLinks.appSearchSearchUI)
);
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/components/empty_state.tsx
index b7665a58de300..9a663e1372211 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/components/empty_state.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/components/empty_state.tsx
@@ -10,7 +10,7 @@ import React from 'react';
import { EuiButton, EuiEmptyPrompt } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { DOCS_PREFIX } from '../../../routes';
+import { SEARCH_UI_DOCS_URL } from '../../../routes';
export const EmptyState: React.FC = () => (
(
}
actions={
-
+
{i18n.translate('xpack.enterpriseSearch.appSearch.engine.searchUI.empty.buttonLabel', {
defaultMessage: 'Read the Search UI guide',
})}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui.tsx
index 2b210bd07ab4b..43ea60fa84617 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui.tsx
@@ -12,7 +12,7 @@ import { useActions, useValues } from 'kea';
import { EuiText, EuiFlexItem, EuiFlexGroup, EuiSpacer, EuiLink } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
-import { DOCS_PREFIX } from '../../routes';
+import { SEARCH_UI_DOCS_URL } from '../../routes';
import { EngineLogic, getEngineBreadcrumbs } from '../engine';
import { AppSearchPageTemplate } from '../layout';
@@ -62,7 +62,7 @@ export const SearchUI: React.FC = () => {
defaultMessage="Use the fields below to generate a sample search experience built with Search UI. Use the sample to preview search results, or build upon it to create your own custom search experience. {link}."
values={{
link: (
-
+
{
defaultMessage: 'Log retention is determined by the ILM policies for your deployment.',
})}
-
+
{i18n.translate('xpack.enterpriseSearch.appSearch.settings.logRetention.learnMore', {
defaultMessage: 'Learn more about log retention for Enterprise Search.',
})}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.tsx
index d460132dddbb1..f1d9beaca5136 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.tsx
@@ -15,7 +15,7 @@ import { APP_SEARCH_PLUGIN } from '../../../../../common/constants';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { SetupGuideLayout, SETUP_GUIDE_TITLE } from '../../../shared/setup_guide';
import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry';
-import { DOCS_PREFIX } from '../../routes';
+import { NATIVE_AUTH_DOCS_URL, STANDARD_AUTH_DOCS_URL } from '../../routes';
import GettingStarted from './assets/getting_started.png';
@@ -23,8 +23,8 @@ export const SetupGuide: React.FC = () => (
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/synonyms/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/synonyms/components/empty_state.test.tsx
index a43f170e5822f..cdfdbadf6759c 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/synonyms/components/empty_state.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/synonyms/components/empty_state.test.tsx
@@ -11,6 +11,8 @@ import { shallow } from 'enzyme';
import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';
+import { docLinks } from '../../../../shared/doc_links';
+
import { EmptyState, SynonymModal } from './';
describe('EmptyState', () => {
@@ -21,7 +23,7 @@ describe('EmptyState', () => {
expect(wrapper.find('h2').text()).toEqual('Create your first synonym set');
expect(wrapper.find(EuiButton).prop('href')).toEqual(
- expect.stringContaining('/synonyms-guide.html')
+ expect.stringContaining(docLinks.appSearchSynonyms)
);
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/synonyms/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/synonyms/components/empty_state.tsx
index f856a5c035f81..ac8383ccea9ee 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/synonyms/components/empty_state.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/synonyms/components/empty_state.tsx
@@ -10,7 +10,7 @@ import React from 'react';
import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { DOCS_PREFIX } from '../../../routes';
+import { SYNONYMS_DOCS_URL } from '../../../routes';
import { SynonymModal, SynonymIcon } from './';
@@ -35,12 +35,7 @@ export const EmptyState: React.FC = () => {
}
actions={
-
+
{i18n.translate('xpack.enterpriseSearch.appSearch.engine.synonyms.empty.buttonLabel', {
defaultMessage: 'Read the synonyms guide',
})}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/routes.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/routes.ts
index 97a9b407b3cd6..1f2e7c883e1cb 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/routes.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/routes.ts
@@ -7,7 +7,29 @@
import { docLinks } from '../shared/doc_links';
-export const DOCS_PREFIX = docLinks.appSearchBase;
+export const API_DOCS_URL = docLinks.appSearchApis;
+export const API_CLIENTS_DOCS_URL = docLinks.appSearchApiClients;
+export const API_KEYS_DOCS_URL = docLinks.appSearchApiKeys;
+export const AUTHENTICATION_DOCS_URL = docLinks.appSearchAuthentication;
+export const CRAWL_RULES_DOCS_URL = docLinks.appSearchCrawlRules;
+export const CURATIONS_DOCS_URL = docLinks.appSearchCurations;
+export const DOCS_URL = docLinks.appSearchGuide;
+export const DUPLICATE_DOCS_URL = docLinks.appSearchDuplicateDocuments;
+export const ENTRY_POINTS_DOCS_URL = docLinks.appSearchEntryPoints;
+export const INDEXING_DOCS_URL = docLinks.appSearchIndexingDocs;
+export const INDEXING_SCHEMA_DOCS_URL = docLinks.appSearchIndexingDocsSchema;
+export const LOG_SETTINGS_DOCS_URL = docLinks.appSearchLogSettings;
+export const META_ENGINES_DOCS_URL = docLinks.appSearchMetaEngines;
+export const NATIVE_AUTH_DOCS_URL = docLinks.appSearchNativeAuth;
+export const PRECISION_DOCS_URL = docLinks.appSearchPrecision;
+export const RELEVANCE_DOCS_URL = docLinks.appSearchRelevance;
+export const RESULT_SETTINGS_DOCS_URL = docLinks.appSearchResultSettings;
+export const SEARCH_UI_DOCS_URL = docLinks.appSearchSearchUI;
+export const SECURITY_DOCS_URL = docLinks.appSearchSecurity;
+export const STANDARD_AUTH_DOCS_URL = docLinks.appSearchStandardAuth;
+export const SYNONYMS_DOCS_URL = docLinks.appSearchSynonyms;
+export const WEB_CRAWLER_DOCS_URL = docLinks.appSearchWebCrawler;
+export const WEB_CRAWLER_LOG_DOCS_URL = docLinks.appSearchWebCrawlerEventLogs;
export const ROOT_PATH = '/';
export const SETUP_GUIDE_PATH = '/setup_guide';
diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.tsx
index e82dbcaa41135..c7c85fdd49359 100644
--- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.tsx
@@ -12,7 +12,7 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { ENTERPRISE_SEARCH_PLUGIN } from '../../../../../common/constants';
-import { DOCS_PREFIX } from '../../../app_search/routes';
+import { NATIVE_AUTH_DOCS_URL, STANDARD_AUTH_DOCS_URL } from '../../../app_search/routes';
import { SetEnterpriseSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { SetupGuideLayout, SETUP_GUIDE_TITLE } from '../../../shared/setup_guide';
import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry';
@@ -23,8 +23,8 @@ export const SetupGuide: React.FC = () => (
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.test.ts
index cbd7a1c6107b1..b14af1c69795a 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.test.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.test.ts
@@ -5,27 +5,23 @@
* 2.0.
*/
+import { docLinksServiceMock } from '../../../../../../../src/core/public/mocks';
+
import { docLinks } from './';
describe('DocLinks', () => {
it('setDocLinks', () => {
const links = {
- DOC_LINK_VERSION: '',
- ELASTIC_WEBSITE_URL: 'https://elastic.co/',
- links: {
- enterpriseSearch: {
- base: 'http://elastic.enterprise.search',
- appSearchBase: 'http://elastic.app.search',
- workplaceSearchBase: 'http://elastic.workplace.search',
- },
- },
+ DOC_LINK_VERSION: docLinksServiceMock.createStartContract().DOC_LINK_VERSION,
+ ELASTIC_WEBSITE_URL: docLinksServiceMock.createStartContract().ELASTIC_WEBSITE_URL,
+ links: docLinksServiceMock.createStartContract().links,
};
docLinks.setDocLinks(links as any);
- expect(docLinks.enterpriseSearchBase).toEqual('http://elastic.enterprise.search');
- expect(docLinks.appSearchBase).toEqual('http://elastic.app.search');
- expect(docLinks.workplaceSearchBase).toEqual('http://elastic.workplace.search');
- expect(docLinks.cloudBase).toEqual('https://elastic.co/guide/en/cloud/current');
+ expect(docLinks.appSearchApis).toEqual(links.links.appSearch.apiRef);
+ expect(docLinks.cloudIndexManagement).toEqual(links.links.cloud.indexManagement);
+ expect(docLinks.enterpriseSearchConfig).toEqual(links.links.enterpriseSearch.configuration);
+ expect(docLinks.workplaceSearchZendesk).toEqual(links.links.workplaceSearch.zendesk);
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts b/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts
index 6034846fac4f1..93bead4d31f4c 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts
@@ -8,23 +8,174 @@
import { DocLinksStart } from 'kibana/public';
class DocLinks {
- public enterpriseSearchBase: string;
- public appSearchBase: string;
- public workplaceSearchBase: string;
- public cloudBase: string;
+ public appSearchApis: string;
+ public appSearchApiClients: string;
+ public appSearchApiKeys: string;
+ public appSearchAuthentication: string;
+ public appSearchCrawlRules: string;
+ public appSearchCurations: string;
+ public appSearchDuplicateDocuments: string;
+ public appSearchEntryPoints: string;
+ public appSearchGuide: string;
+ public appSearchIndexingDocs: string;
+ public appSearchIndexingDocsSchema: string;
+ public appSearchLogSettings: string;
+ public appSearchMetaEngines: string;
+ public appSearchNativeAuth: string;
+ public appSearchPrecision: string;
+ public appSearchRelevance: string;
+ public appSearchResultSettings: string;
+ public appSearchSearchUI: string;
+ public appSearchSecurity: string;
+ public appSearchStandardAuth: string;
+ public appSearchSynonyms: string;
+ public appSearchWebCrawler: string;
+ public appSearchWebCrawlerEventLogs: string;
+ public cloudIndexManagement: string;
+ public enterpriseSearchConfig: string;
+ public enterpriseSearchMailService: string;
+ public enterpriseSearchUsersAccess: string;
+ public licenseManagement: string;
+ public workplaceSearchBox: string;
+ public workplaceSearchConfluenceCloud: string;
+ public workplaceSearchConfluenceServer: string;
+ public workplaceSearchCustomSources: string;
+ public workplaceSearchCustomSourcePermissions: string;
+ public workplaceSearchDocumentPermissions: string;
+ public workplaceSearchDropbox: string;
+ public workplaceSearchExternalIdentities: string;
+ public workplaceSearchGettingStarted: string;
+ public workplaceSearchGitHub: string;
+ public workplaceSearchGmail: string;
+ public workplaceSearchGoogleDrive: string;
+ public workplaceSearchIndexingSchedule: string;
+ public workplaceSearchJiraCloud: string;
+ public workplaceSearchJiraServer: string;
+ public workplaceSearchNativeAuth: string;
+ public workplaceSearchOneDrive: string;
+ public workplaceSearchPermissions: string;
+ public workplaceSearchSalesforce: string;
+ public workplaceSearchSecurity: string;
+ public workplaceSearchServiceNow: string;
+ public workplaceSearchSharePoint: string;
+ public workplaceSearchSlack: string;
+ public workplaceSearchStandardAuth: string;
+ public workplaceSearchSynch: string;
+ public workplaceSearchZendesk: string;
constructor() {
- this.enterpriseSearchBase = '';
- this.appSearchBase = '';
- this.workplaceSearchBase = '';
- this.cloudBase = '';
+ this.appSearchApis = '';
+ this.appSearchApiClients = '';
+ this.appSearchApiKeys = '';
+ this.appSearchAuthentication = '';
+ this.appSearchCrawlRules = '';
+ this.appSearchCurations = '';
+ this.appSearchDuplicateDocuments = '';
+ this.appSearchEntryPoints = '';
+ this.appSearchGuide = '';
+ this.appSearchIndexingDocs = '';
+ this.appSearchIndexingDocsSchema = '';
+ this.appSearchLogSettings = '';
+ this.appSearchMetaEngines = '';
+ this.appSearchNativeAuth = '';
+ this.appSearchPrecision = '';
+ this.appSearchRelevance = '';
+ this.appSearchResultSettings = '';
+ this.appSearchSearchUI = '';
+ this.appSearchSecurity = '';
+ this.appSearchStandardAuth = '';
+ this.appSearchSynonyms = '';
+ this.appSearchWebCrawler = '';
+ this.appSearchWebCrawlerEventLogs = '';
+ this.cloudIndexManagement = '';
+ this.enterpriseSearchConfig = '';
+ this.enterpriseSearchMailService = '';
+ this.enterpriseSearchUsersAccess = '';
+ this.licenseManagement = '';
+ this.workplaceSearchBox = '';
+ this.workplaceSearchConfluenceCloud = '';
+ this.workplaceSearchConfluenceServer = '';
+ this.workplaceSearchCustomSources = '';
+ this.workplaceSearchCustomSourcePermissions = '';
+ this.workplaceSearchDocumentPermissions = '';
+ this.workplaceSearchDropbox = '';
+ this.workplaceSearchExternalIdentities = '';
+ this.workplaceSearchGettingStarted = '';
+ this.workplaceSearchGitHub = '';
+ this.workplaceSearchGmail = '';
+ this.workplaceSearchGoogleDrive = '';
+ this.workplaceSearchIndexingSchedule = '';
+ this.workplaceSearchJiraCloud = '';
+ this.workplaceSearchJiraServer = '';
+ this.workplaceSearchNativeAuth = '';
+ this.workplaceSearchOneDrive = '';
+ this.workplaceSearchPermissions = '';
+ this.workplaceSearchSalesforce = '';
+ this.workplaceSearchSecurity = '';
+ this.workplaceSearchServiceNow = '';
+ this.workplaceSearchSharePoint = '';
+ this.workplaceSearchSlack = '';
+ this.workplaceSearchStandardAuth = '';
+ this.workplaceSearchSynch = '';
+ this.workplaceSearchZendesk = '';
}
public setDocLinks(docLinks: DocLinksStart): void {
- this.enterpriseSearchBase = docLinks.links.enterpriseSearch.base;
- this.appSearchBase = docLinks.links.enterpriseSearch.appSearchBase;
- this.workplaceSearchBase = docLinks.links.enterpriseSearch.workplaceSearchBase;
- this.cloudBase = `${docLinks.ELASTIC_WEBSITE_URL}guide/en/cloud/current`;
+ this.appSearchApis = docLinks.links.appSearch.apiRef;
+ this.appSearchApiClients = docLinks.links.appSearch.apiClients;
+ this.appSearchApiKeys = docLinks.links.appSearch.apiKeys;
+ this.appSearchAuthentication = docLinks.links.appSearch.authentication;
+ this.appSearchCrawlRules = docLinks.links.appSearch.crawlRules;
+ this.appSearchCurations = docLinks.links.appSearch.curations;
+ this.appSearchDuplicateDocuments = docLinks.links.appSearch.duplicateDocuments;
+ this.appSearchEntryPoints = docLinks.links.appSearch.entryPoints;
+ this.appSearchGuide = docLinks.links.appSearch.guide;
+ this.appSearchIndexingDocs = docLinks.links.appSearch.indexingDocuments;
+ this.appSearchIndexingDocsSchema = docLinks.links.appSearch.indexingDocumentsSchema;
+ this.appSearchLogSettings = docLinks.links.appSearch.logSettings;
+ this.appSearchMetaEngines = docLinks.links.appSearch.metaEngines;
+ this.appSearchNativeAuth = docLinks.links.appSearch.nativeAuth;
+ this.appSearchPrecision = docLinks.links.appSearch.precisionTuning;
+ this.appSearchRelevance = docLinks.links.appSearch.relevanceTuning;
+ this.appSearchResultSettings = docLinks.links.appSearch.resultSettings;
+ this.appSearchSearchUI = docLinks.links.appSearch.searchUI;
+ this.appSearchSecurity = docLinks.links.appSearch.security;
+ this.appSearchStandardAuth = docLinks.links.appSearch.standardAuth;
+ this.appSearchSynonyms = docLinks.links.appSearch.synonyms;
+ this.appSearchWebCrawler = docLinks.links.appSearch.webCrawler;
+ this.appSearchWebCrawlerEventLogs = docLinks.links.appSearch.webCrawlerEventLogs;
+ this.cloudIndexManagement = docLinks.links.cloud.indexManagement;
+ this.enterpriseSearchConfig = docLinks.links.enterpriseSearch.configuration;
+ this.enterpriseSearchMailService = docLinks.links.enterpriseSearch.mailService;
+ this.enterpriseSearchUsersAccess = docLinks.links.enterpriseSearch.usersAccess;
+ this.licenseManagement = docLinks.links.enterpriseSearch.licenseManagement;
+ this.workplaceSearchBox = docLinks.links.workplaceSearch.box;
+ this.workplaceSearchConfluenceCloud = docLinks.links.workplaceSearch.confluenceCloud;
+ this.workplaceSearchConfluenceServer = docLinks.links.workplaceSearch.confluenceServer;
+ this.workplaceSearchCustomSources = docLinks.links.workplaceSearch.customSources;
+ this.workplaceSearchCustomSourcePermissions =
+ docLinks.links.workplaceSearch.customSourcePermissions;
+ this.workplaceSearchDocumentPermissions = docLinks.links.workplaceSearch.documentPermissions;
+ this.workplaceSearchDropbox = docLinks.links.workplaceSearch.dropbox;
+ this.workplaceSearchExternalIdentities = docLinks.links.workplaceSearch.externalIdentities;
+ this.workplaceSearchGettingStarted = docLinks.links.workplaceSearch.gettingStarted;
+ this.workplaceSearchGitHub = docLinks.links.workplaceSearch.gitHub;
+ this.workplaceSearchGmail = docLinks.links.workplaceSearch.gmail;
+ this.workplaceSearchGoogleDrive = docLinks.links.workplaceSearch.googleDrive;
+ this.workplaceSearchIndexingSchedule = docLinks.links.workplaceSearch.indexingSchedule;
+ this.workplaceSearchJiraCloud = docLinks.links.workplaceSearch.jiraCloud;
+ this.workplaceSearchJiraServer = docLinks.links.workplaceSearch.jiraServer;
+ this.workplaceSearchNativeAuth = docLinks.links.workplaceSearch.nativeAuth;
+ this.workplaceSearchOneDrive = docLinks.links.workplaceSearch.oneDrive;
+ this.workplaceSearchPermissions = docLinks.links.workplaceSearch.permissions;
+ this.workplaceSearchSalesforce = docLinks.links.workplaceSearch.salesforce;
+ this.workplaceSearchSecurity = docLinks.links.workplaceSearch.security;
+ this.workplaceSearchServiceNow = docLinks.links.workplaceSearch.serviceNow;
+ this.workplaceSearchSharePoint = docLinks.links.workplaceSearch.sharePoint;
+ this.workplaceSearchSlack = docLinks.links.workplaceSearch.slack;
+ this.workplaceSearchStandardAuth = docLinks.links.workplaceSearch.standardAuth;
+ this.workplaceSearchSynch = docLinks.links.workplaceSearch.synch;
+ this.workplaceSearchZendesk = docLinks.links.workplaceSearch.zendesk;
}
}
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/manage_license_button.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/licensing/manage_license_button.test.tsx
index 1877a4cbd0e42..07c71def01bed 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/manage_license_button.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/licensing/manage_license_button.test.tsx
@@ -13,6 +13,8 @@ import { shallow } from 'enzyme';
import { EuiButton } from '@elastic/eui';
+import { docLinks } from '../../shared/doc_links';
+
import { EuiButtonTo } from '../react_router_helpers';
import { ManageLicenseButton } from './';
@@ -35,7 +37,7 @@ describe('ManageLicenseButton', () => {
const wrapper = shallow();
expect(wrapper.find(EuiButton).prop('href')).toEqual(
- expect.stringContaining('/license-management.html')
+ expect.stringContaining(docLinks.licenseManagement)
);
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/manage_license_button.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/licensing/manage_license_button.tsx
index af3b33e3d7a3d..d0fe98a7c1393 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/manage_license_button.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/licensing/manage_license_button.tsx
@@ -27,12 +27,7 @@ export const ManageLicenseButton: React.FC = (props) => {
})}
) : (
-
+
{i18n.translate('xpack.enterpriseSearch.licenseDocumentationLink', {
defaultMessage: 'Learn more about license features',
})}
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.tsx
index 6e213edf457b1..667980d5f0492 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.tsx
@@ -18,7 +18,7 @@ import { RoleRules } from '../types';
import './role_mappings_table.scss';
-const AUTH_PROVIDER_DOCUMENTATION_URL = `${docLinks.enterpriseSearchBase}/users-access.html`;
+const AUTH_PROVIDER_DOCUMENTATION_URL = `${docLinks.enterpriseSearchUsersAccess}`;
import {
ANY_AUTH_PROVIDER,
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/user_selector.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/user_selector.tsx
index 25aff5077c680..077ef44c66b2f 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/user_selector.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/user_selector.tsx
@@ -24,7 +24,7 @@ import { Role as WSRole } from '../../workplace_search/types';
import { USERNAME_LABEL, EMAIL_LABEL } from '../constants';
import { docLinks } from '../doc_links';
-const SMTP_URL = `${docLinks.enterpriseSearchBase}/mailer-configuration.html`;
+const SMTP_URL = `${docLinks.enterpriseSearchMailService}`;
import {
NEW_USER_LABEL,
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/users_empty_prompt.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/users_empty_prompt.tsx
index 42bf690c388c4..56e0a325aafd0 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/users_empty_prompt.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/users_empty_prompt.tsx
@@ -20,7 +20,7 @@ import { docLinks } from '../doc_links';
import { NO_USERS_TITLE, NO_USERS_DESCRIPTION, ENABLE_USERS_LINK } from './constants';
-const USERS_DOCS_URL = `${docLinks.enterpriseSearchBase}/users-access.html`;
+const USERS_DOCS_URL = `${docLinks.enterpriseSearchUsersAccess}`;
export const UsersEmptyPrompt: React.FC = () => (
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/cloud/instructions.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/cloud/instructions.tsx
index 4845d682b8771..8d41e221a2cc7 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/cloud/instructions.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/cloud/instructions.tsx
@@ -80,10 +80,7 @@ export const CloudSetupInstructions: React.FC = ({ productName, cloudDepl
defaultMessage="After enabling Enterprise Search for your instance you can customize the instance, including fault tolerance, RAM, and other {optionsLink}."
values={{
optionsLink: (
-
+
{i18n.translate(
'xpack.enterpriseSearch.setupGuide.cloud.step3.instruction1LinkText',
{ defaultMessage: 'configurable options' }
@@ -125,10 +122,7 @@ export const CloudSetupInstructions: React.FC = ({ productName, cloudDepl
values={{
productName,
configurePolicyLink: (
-
+
{i18n.translate(
'xpack.enterpriseSearch.setupGuide.cloud.step5.instruction1LinkText',
{ defaultMessage: 'configure an index lifecycle policy' }
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts
index 1be152ad5ca0b..b28343f37ea25 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts
@@ -17,37 +17,36 @@ export const LOGOUT_ROUTE = '/logout';
export const LEAVE_FEEDBACK_EMAIL = 'support@elastic.co';
export const LEAVE_FEEDBACK_URL = `mailto:${LEAVE_FEEDBACK_EMAIL}?Subject=Elastic%20Workplace%20Search%20Feedback`;
-export const DOCS_PREFIX = docLinks.workplaceSearchBase;
-export const PERMISSIONS_DOCS_URL = `${DOCS_PREFIX}/workplace-search-permissions.html`;
-export const DOCUMENT_PERMISSIONS_DOCS_URL = `${DOCS_PREFIX}/workplace-search-sources-document-permissions.html`;
-export const DOCUMENT_PERMISSIONS_SYNC_DOCS_URL = `${DOCUMENT_PERMISSIONS_DOCS_URL}#sources-permissions-synchronizing`;
-export const PRIVATE_SOURCES_DOCS_URL = `${PERMISSIONS_DOCS_URL}#organizational-sources-private-sources`;
-export const EXTERNAL_IDENTITIES_DOCS_URL = `${DOCS_PREFIX}/workplace-search-external-identities-api.html`;
-export const SECURITY_DOCS_URL = `${DOCS_PREFIX}/workplace-search-security.html`;
-export const SMTP_DOCS_URL = `${DOCS_PREFIX}/workplace-search-smtp-mailer.html`;
-export const BOX_DOCS_URL = `${DOCS_PREFIX}/workplace-search-box-connector.html`;
-export const CONFLUENCE_DOCS_URL = `${DOCS_PREFIX}/workplace-search-confluence-cloud-connector.html`;
-export const CONFLUENCE_SERVER_DOCS_URL = `${DOCS_PREFIX}/workplace-search-confluence-server-connector.html`;
-export const DROPBOX_DOCS_URL = `${DOCS_PREFIX}/workplace-search-dropbox-connector.html`;
-export const GITHUB_DOCS_URL = `${DOCS_PREFIX}/workplace-search-github-connector.html`;
-export const GITHUB_ENTERPRISE_DOCS_URL = `${DOCS_PREFIX}/workplace-search-github-connector.html`;
-export const GMAIL_DOCS_URL = `${DOCS_PREFIX}/workplace-search-gmail-connector.html`;
-export const GOOGLE_DRIVE_DOCS_URL = `${DOCS_PREFIX}/workplace-search-google-drive-connector.html`;
-export const JIRA_DOCS_URL = `${DOCS_PREFIX}/workplace-search-jira-cloud-connector.html`;
-export const JIRA_SERVER_DOCS_URL = `${DOCS_PREFIX}/workplace-search-jira-server-connector.html`;
-export const ONEDRIVE_DOCS_URL = `${DOCS_PREFIX}/workplace-search-onedrive-connector.html`;
-export const SALESFORCE_DOCS_URL = `${DOCS_PREFIX}/workplace-search-salesforce-connector.html`;
-export const SERVICENOW_DOCS_URL = `${DOCS_PREFIX}/workplace-search-servicenow-connector.html`;
-export const SHAREPOINT_DOCS_URL = `${DOCS_PREFIX}/workplace-search-sharepoint-online-connector.html`;
-export const SLACK_DOCS_URL = `${DOCS_PREFIX}/workplace-search-slack-connector.html`;
-export const ZENDESK_DOCS_URL = `${DOCS_PREFIX}/workplace-search-zendesk-connector.html`;
-export const CUSTOM_SOURCE_DOCS_URL = `${DOCS_PREFIX}/workplace-search-custom-api-sources.html`;
-export const CUSTOM_API_DOCS_URL = `${DOCS_PREFIX}/workplace-search-custom-sources-api.html`;
-export const CUSTOM_API_DOCUMENT_PERMISSIONS_DOCS_URL = `${CUSTOM_SOURCE_DOCS_URL}#custom-api-source-document-level-access-control`;
-export const ENT_SEARCH_LICENSE_MANAGEMENT = `${docLinks.enterpriseSearchBase}/license-management.html`;
-export const SYNCHRONIZATION_DOCS_URL = `${DOCS_PREFIX}}/workplace-search-customizing-indexing-rules.html#workplace-search-customizing-indexing-rules`;
-export const DIFFERENT_SYNC_TYPES_DOCS_URL = `${DOCS_PREFIX}}/workplace-search-customizing-indexing-rules.html#_indexing_schedule`;
-export const OBJECTS_AND_ASSETS_DOCS_URL = `${DOCS_PREFIX}}/workplace-search-customizing-indexing-rules.html#workplace-search-customizing-indexing-rules`;
+export const BOX_DOCS_URL = docLinks.workplaceSearchBox;
+export const CONFLUENCE_DOCS_URL = docLinks.workplaceSearchConfluenceCloud;
+export const CONFLUENCE_SERVER_DOCS_URL = docLinks.workplaceSearchConfluenceServer;
+export const CUSTOM_SOURCE_DOCS_URL = docLinks.workplaceSearchCustomSources;
+export const CUSTOM_API_DOCUMENT_PERMISSIONS_DOCS_URL =
+ docLinks.workplaceSearchCustomSourcePermissions;
+export const DIFFERENT_SYNC_TYPES_DOCS_URL = docLinks.workplaceSearchIndexingSchedule;
+export const DOCUMENT_PERMISSIONS_DOCS_URL = docLinks.workplaceSearchDocumentPermissions;
+export const DROPBOX_DOCS_URL = docLinks.workplaceSearchDropbox;
+export const ENT_SEARCH_LICENSE_MANAGEMENT = docLinks.licenseManagement;
+export const EXTERNAL_IDENTITIES_DOCS_URL = docLinks.workplaceSearchExternalIdentities;
+export const GETTING_STARTED_DOCS_URL = docLinks.workplaceSearchGettingStarted;
+export const GITHUB_DOCS_URL = docLinks.workplaceSearchGitHub;
+export const GITHUB_ENTERPRISE_DOCS_URL = docLinks.workplaceSearchGitHub;
+export const GMAIL_DOCS_URL = docLinks.workplaceSearchGmail;
+export const GOOGLE_DRIVE_DOCS_URL = docLinks.workplaceSearchGoogleDrive;
+export const JIRA_DOCS_URL = docLinks.workplaceSearchJiraCloud;
+export const JIRA_SERVER_DOCS_URL = docLinks.workplaceSearchJiraServer;
+export const NATIVE_AUTH_DOCS_URL = docLinks.workplaceSearchNativeAuth;
+export const OBJECTS_AND_ASSETS_DOCS_URL = docLinks.workplaceSearchSynch;
+export const ONEDRIVE_DOCS_URL = docLinks.workplaceSearchOneDrive;
+export const PRIVATE_SOURCES_DOCS_URL = docLinks.workplaceSearchPermissions;
+export const SALESFORCE_DOCS_URL = docLinks.workplaceSearchSalesforce;
+export const SECURITY_DOCS_URL = docLinks.workplaceSearchSecurity;
+export const SERVICENOW_DOCS_URL = docLinks.workplaceSearchServiceNow;
+export const SHAREPOINT_DOCS_URL = docLinks.workplaceSearchSharePoint;
+export const SLACK_DOCS_URL = docLinks.workplaceSearchSlack;
+export const STANDARD_AUTH_DOCS_URL = docLinks.workplaceSearchStandardAuth;
+export const SYNCHRONIZATION_DOCS_URL = docLinks.workplaceSearchSynch;
+export const ZENDESK_DOCS_URL = docLinks.workplaceSearchZendesk;
export const PERSONAL_PATH = '/p';
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/oauth_application.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/oauth_application.test.tsx
index 4d329ff357b89..a992cf49f75fb 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/oauth_application.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/components/oauth_application.test.tsx
@@ -124,9 +124,9 @@ describe('OauthApplication', () => {
`);
});
+ /* This href test should ultimately use the docLinkServiceMock */
it('renders description', () => {
const wrapper = shallow();
-
expect(wrapper.prop('pageHeader').description).toMatchInlineSnapshot(`
{
Explore Platinum features
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.tsx
index 905ba20e4f660..e52a174850c4c 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.tsx
@@ -15,19 +15,23 @@ import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants';
import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { SetupGuideLayout, SETUP_GUIDE_TITLE } from '../../../shared/setup_guide';
import { SendWorkplaceSearchTelemetry as SendTelemetry } from '../../../shared/telemetry';
-import { DOCS_PREFIX } from '../../routes';
+import {
+ GETTING_STARTED_DOCS_URL,
+ NATIVE_AUTH_DOCS_URL,
+ STANDARD_AUTH_DOCS_URL,
+} from '../../routes';
import GettingStarted from './assets/getting_started.png';
-const GETTING_STARTED_LINK_URL = `${DOCS_PREFIX}/workplace-search-getting-started.html`;
+const GETTING_STARTED_LINK_URL = GETTING_STARTED_DOCS_URL;
export const SetupGuide: React.FC = () => {
return (
From 50c02645cf32eded853f934e3cfe24d0d6daaaee Mon Sep 17 00:00:00 2001
From: gchaps <33642766+gchaps@users.noreply.github.com>
Date: Mon, 29 Nov 2021 11:46:58 -0800
Subject: [PATCH 29/47] [DOCS] Changes index pattern to data views in intro
docs (#119403)
* [DOCS] Changes index pattern to data views in intro docs
* [DOCS] Updates image of data views UI
* [DOCS] Removes faulty sentence
* [DOCS] removes sentence about index patterns
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
docs/concepts/data-views.asciidoc | 8 ++++----
docs/concepts/index.asciidoc | 5 +----
docs/concepts/save-query.asciidoc | 2 +-
docs/concepts/set-time-filter.asciidoc | 2 +-
.../getting-started/quick-start-guide.asciidoc | 8 ++++----
.../index-patterns/images/create-data-view.png | Bin 0 -> 190415 bytes
.../images/create-index-pattern.png | Bin 161561 -> 0 bytes
7 files changed, 11 insertions(+), 14 deletions(-)
create mode 100644 docs/management/index-patterns/images/create-data-view.png
delete mode 100644 docs/management/index-patterns/images/create-index-pattern.png
diff --git a/docs/concepts/data-views.asciidoc b/docs/concepts/data-views.asciidoc
index 7eb95405db6bc..954581faa2460 100644
--- a/docs/concepts/data-views.asciidoc
+++ b/docs/concepts/data-views.asciidoc
@@ -1,7 +1,7 @@
[[data-views]]
=== Create a data view
-{kib} requires a data view to access the {es} data that you want to explore.
+{kib} requires a data view to access the {es} data that you want to explore.
A data view selects the data to use and allows you to define properties of the fields.
A data view can point to one or more indices, {ref}/data-streams.html[data stream], or {ref}/alias.html[index aliases].
@@ -37,7 +37,7 @@ If you loaded your own data, follow these steps to create a data view.
. Click *Create data view*.
[role="screenshot"]
-image:management/index-patterns/images/create-index-pattern.png["Create data view"]
+image:management/index-patterns/images/create-data-view.png["Create data view"]
. Start typing in the *name* field, and {kib} looks for the names of
indices, data streams, and aliases that match your input.
@@ -87,11 +87,11 @@ For an example, refer to <:
+:
```
To query {ls} indices across two {es} clusters
diff --git a/docs/concepts/index.asciidoc b/docs/concepts/index.asciidoc
index eac26beee1f9b..457251e62ae8d 100644
--- a/docs/concepts/index.asciidoc
+++ b/docs/concepts/index.asciidoc
@@ -40,8 +40,6 @@ image:concepts/images/global-search.png["Global search showing matches to apps a
{kib} requires a data view to tell it which {es} data you want to access,
and whether the data is time-based. A data view can point to one or more {es}
data streams, indices, or index aliases by name.
-For example, `logs-elasticsearch-prod-*` is an index pattern,
-and it is time-based with a time field of `@timestamp`. The time field is not editable.
Data views are typically created by an administrator when sending data to {es}.
You can <> in *Stack Management*, or by using a script
@@ -129,8 +127,7 @@ Previously, {kib} used the {ref}/search-aggregations-bucket-terms-aggregation.ht
Structured filters are a more interactive way to create {es} queries,
and are commonly used when building dashboards that are shared by multiple analysts.
Each filter can be disabled, inverted, or pinned across all apps.
-The structured filters are the only way to use the {es} Query DSL in JSON form,
-or to target a specific index pattern for filtering. Each of the structured
+Each of the structured
filters is combined with AND logic on the rest of the query.
[role="screenshot"]
diff --git a/docs/concepts/save-query.asciidoc b/docs/concepts/save-query.asciidoc
index 61113b5491c29..54137d1f9f2cf 100644
--- a/docs/concepts/save-query.asciidoc
+++ b/docs/concepts/save-query.asciidoc
@@ -17,7 +17,7 @@ image:concepts/images/saved-query.png["Example of the saved query management pop
Saved queries are different than <>,
which include the *Discover* configuration—selected columns in the document table, sort order, and
-index pattern—in addition to the query.
+{data-source}—in addition to the query.
Saved searches are primarily used for adding search results to a dashboard.
[role="xpack"]
diff --git a/docs/concepts/set-time-filter.asciidoc b/docs/concepts/set-time-filter.asciidoc
index 116bcd6f91f77..b379c0ac279e5 100644
--- a/docs/concepts/set-time-filter.asciidoc
+++ b/docs/concepts/set-time-filter.asciidoc
@@ -2,7 +2,7 @@
=== Set the time range
Display data within a
specified time range when your index contains time-based events, and a time-field is configured for the
-selected <>.
+selected <>.
The default time range is 15 minutes, but you can customize
it in <>.
diff --git a/docs/getting-started/quick-start-guide.asciidoc b/docs/getting-started/quick-start-guide.asciidoc
index 03e40c7cc6cef..2667729f4b854 100644
--- a/docs/getting-started/quick-start-guide.asciidoc
+++ b/docs/getting-started/quick-start-guide.asciidoc
@@ -11,7 +11,7 @@ When you've finished, you'll know how to:
[float]
=== Required privileges
-You must have `read`, `write`, and `manage` privileges on the `kibana_sample_data_*` indices.
+You must have `read`, `write`, and `manage` privileges on the `kibana_sample_data_*` indices.
Learn how to <>, or refer to {ref}/security-privileges.html[Security privileges] for more information.
[float]
@@ -37,7 +37,7 @@ image::images/addData_sampleDataCards_7.15.0.png[Add data UI for the sample data
[[explore-the-data]]
== Explore the data
-*Discover* displays the data in an interactive histogram that shows the distribution of data, or documents, over time, and a table that lists the fields for each document that matches the index pattern. To view a subset of the documents, you can apply filters to the data, and customize the table to display only the fields you want to explore.
+*Discover* displays the data in an interactive histogram that shows the distribution of data, or documents, over time, and a table that lists the fields for each document that matches the {data-source}. To view a subset of the documents, you can apply filters to the data, and customize the table to display only the fields you want to explore.
. Open the main menu, then click *Discover*.
@@ -65,7 +65,7 @@ image::images/tutorial-discover-3.png[Discover table that displays only the prod
A dashboard is a collection of panels that you can use to view and analyze the data. Panels contain visualizations, interactive controls, text, and more.
-. Open the main menu, then click *Dashboard*.
+. Open the main menu, then click *Dashboard*.
. Click *[eCommerce] Revenue Dashboard*.
+
@@ -104,7 +104,7 @@ The treemap appears as the last visualization panel on the dashboard.
[[interact-with-the-data]]
=== Interact with the data
-You can interact with the dashboard data using controls that allow you to apply dashboard-level filters. Interact with the *[eCommerce] Controls* panel to view the women's clothing data from the Gnomehouse manufacturer.
+You can interact with the dashboard data using controls that allow you to apply dashboard-level filters. Interact with the *[eCommerce] Controls* panel to view the women's clothing data from the Gnomehouse manufacturer.
. From the *Manufacturer* dropdown, select *Gnomehouse*.
diff --git a/docs/management/index-patterns/images/create-data-view.png b/docs/management/index-patterns/images/create-data-view.png
new file mode 100644
index 0000000000000000000000000000000000000000..229ed0f490b41fe2db1e1d70d7b6f77f097f2cf0
GIT binary patch
literal 190415
zcmce;by!qe+c=B}Qc4RFf`CXfbV+wecT0D74xIu50@5WV-3`(W(%s$N_1m0tp6B?!
z@LkvY*EiRUv)OCbTKBrUwt-R-La*Sl;UOR(UWo|v%RoTD+(1A;X~Vt%?&Oq)wE}-2
z8u9T-neYkmS(sW_%UWvb=n3hW>scG=$O!R5K(K^_$g3OT%A<3}SC>+}@An?b%#1+1
zWBgWTDl_OawQ;9cYBoa|X-&aDZLzr;e)%2yckyR%3Ju{bU3H$Erb2fW(2w$rxRio#KAt|v7s8)xU
zN;}qCTiI-z+v&2FUZ?j&@D#
z-R*n)H|4aN3GjCAG6^r&knkWDmdL4!oX?5yio}h`1A0Of4VgNQ0xqi7F!Uka_NWYu
z*v5aeX6Og;Q0@gUAE78@akeVvB*pOFYEo6Aw-a;tX(YU~?WD20IlZ!1OpJwHieSY=
z!2UuEQYb&Mbq>H=B$7$y^
z&1W?JukVnITvb1(XTf7{7^ZGy7^Yr~F6_)VlU?3HRLU9Ob#8AA((q>96CM2i*}QKk
zPgM8P-N`W5?l+viCD9122uLKt`vR9Ra)kzqApKngNtdkd7u`WNQAEa$XhIv^os_V$U-;QEzbip$7aVouXJpYOHMHQ1&M3s@;?1@3G-ziA`vbuLSM65XP@2EOnY}R
zj;TV=cAG;}c4%!^O;-j^bgpJgZ>;&?2I-x{5$ny89>k?DMu}zRaa%zxT`SAl@P%~b
z7%x|UrI2pdY}DcoW+Ily7_LGTxzMpRTZr7+
zh^mzP=l8^p2yHrJJ%EA;(o+)A7Z-;h2d-fupq^nvKm%9LfDh+0oc~@6J|l&A{?~m-
z2nc^82&jL4BLRFryuJdThdF`fM`%g8xhh{^B4sw6(Ql1A!bI9H<@WsV%GxK(wr^tRNaX
z5FH&A@Czy%Cv#gZM=En0qQ4jU&pP~iHagZumbOL~=IcWq!Q`@>x}DI-TcQ)PZ5GXQ769-Oqabad>0O?Wi)
z@0Nc|Rr+@-9SsA+pHu%B`rlLKZS<`9EX;sSZ8`rX*gup19Q*ATp+pCLp1U*Bk+
z!q;Kyp1xe>FaGb7kPqHLN~iOGfW5egqi=l$rnp#$5qnp#A>_8aT!~Tx5?0e8dmW_@2PJCk-J)
z6W15+bet#93yT1WeAD7ZclFf71D*$XzQcThd!Ih2>Tx7H&5o&nr*sK-42>?17qLFIFdAg{-W
z@bE|T@NM*$eCLPs1R_L%vqmvkJ|$zC%+Fx&G|z9AwjRq0;TvEK#kAR~`Y~Bh;vk^z
zVL5KA93SD&voHi0D>M_d;&?po-RDFIDDbxF*XK{bi6``+4aBitynJF15d{_z5l~`?
zseHtb_I!p6n+))f|A13d_Tz(a|9T4y)_RjqJ%LtF5I=<1JtkzBInQG)_wEZE6f|^G
zGuM~c^p8*MYDod0$hf!9mDUfbuK!@RWVxC>PzpruW?>Z(<(H
z5^^!XdSOb(A-RvORlo!QkI>F#$LM1Lb=3pLz@K_Uof8-#3cdb+R8o~?g=hg34i}ShX@$pyer?p8=rybJ(1~KC!B1
z5U?sp0PprG(Zd079-1f*+GS98N#-e`d;ttHK@i|P+76(9-~;{RsJ^^@VlaUSpg*g7
z_Nyl-wfI0OOUAcvUOq{GZYe2bo&yIQ4Th&wjMjrwF+ndB_5^wkG5|8)%d8B7o?6%w
z0GF9tAo7Wc$cX?t*X^Kc9ZAJa!WK0`iu4{$PvQ3Z{{6N8os4auP+D}N64hkHW#Q75M
z2_EeQWP*9!^UV{>ZvYNfp%9GI6EH(SYKa0!{=Ot=@OTtY0#FzKUnX7??LpFpO_x+2
zOWKV1uSn?og@w;vVqk}P0z>>K;BEd25T3>-q~P&%_9PDygu9pcfN7rhs)Bfe60pR8
z7xoRh|M6VzUl`9MF>buQyZ{=DwR<5o_kV%vmEgAPQ4KBaA
z9&qW%^6c)N)71%UTL_MS8h_xnngf1?#53pEZkCk%F5I(kKgp4+cb2!KTl$j)v;Zds{Kiv|`OlkwUu!}G
zq+fK!_U3d;OZ@0CJadV#aS}^^a?~akPed(U0wtd-6HBh}le<`_twb3Qn)??Toat7%hvD4+cVWT4wo0Jz2URQSi1b5Afw0?({(yRRqHP{2Ga*eDKNcR7kyga7GEQJu(
zM+h=^JTGG`|JKf*$?<^OcrvZp97|V_5^{g8J{_H`-b};x^MWzCT6RjGHR+$~YQY&G
zhWY?H)e|gJ4?yPMQmtP4;VYZnp7!W$84=&!R5`uf?oc4WFiXOABUUJ$;QQN{yPM-E
zbCY82HXprW>eR2FBr$I$T{jtu!)W+}?5p`L
zrk>P4-7=4DK-L{NWXm4g#)DHJ=)n(NJ8SU|8_BW&FZ#KLstT^It_pa1=8_skyf-((
z51INhxSO)*d)EwA7KqIjhl`jD{pYV}LVqYCY
zA(l)^sIZvkKV0r`FyS&(iw7*38FlCn-UA08>@6BkJdW$%dCH~v&7I#^iFT(;dyF~h
z{*?2XhX~%~GR^L>ycGsN*kYRGovB*ajGwkwBbzi>;x%PPM#pQfS__s@nxlce#t;1#
z_SvFQ@-qOLk=kWD-CSt$#)wJccjQ*atct6vlTleAc=m_JdT08;UpW06(0|EWq;_pM?e(r-Lr7qD*_#c&gL|bbEV7
zB@l!jc(m3pK&8TvZaA1GAosq?{NLliVm@$Gu+gt~f1dmAYj&Rp-PqLBgf4P}wnLD|
z=Q^q5B9zn?U0W+
z2M9)Sy__FvU%URq>fg)0?x2hTrEWkGqx%;Yg$|fDzVt_I#&9=qp~E9Qb@LN#X^n2
zS(o#+TT4xL#bT)S>67I!I8s3Sf9s}rP5kLQcUFZ-iDPP{#=?61zC$|C?H8lbVC>V6
zrRz)^!z9k_scxVH&+st6N{zEclnZudDb8X(mL}F{*<$VED|!lrf27N};mSs%7&JS`Gd{J`#l
zy%f99zgx@TxIv>*X_n;*hDe5Lz}IUPk$g*tWG{yW8qx5d}}n@
z)3Fjq8M*CTqN%yfc0Fu*vdk(`qjIEH5^M$P{Y^ET5Pxpy6h;)~k%M*$su!+MmE7B%iBLNzOlsdc$lnC+ZD@H2T^(%8h(L
zr!7e2ISgWov%B55F24alJ|uM7L()p!_k851IF9q>Qiei>05*Lxn;l&gN-(Dy
z*@b^w{eoyya^=!*v=t|mHZR{`qob7^CSPTQ&SbP8bTVGI>ysY|tTsv%+74`7`ytrO
z<;wf*AryWX$p>C93P+6c8^Aw8U%cFqG@CB_mL^xHYgFU98H78|Mtf9e#c?)6V}8Tm
z9N0YZql*j$g3-U4{BrNTS
zhv9sT+ZsPFRhG#8b!PT4`)(kltfY5nZ?0NPE61GwVBHrs!>xNONNo%XjM4Q12}^L<
zS8B~Pdrvi_JrvK#>Xq{@wqE+U-?xt74`T%yB38@oQ4uRTO7M3$%x0MtX48}CT&qpW
ztX&a+f=c`t{9sne7UNcYgE3@ds2kZvCKj5WlWEjBj?|Pln!8btmk8L*(rMX&e4-Za
z_hvu-l%Ea@efzP%Wmb?r(FrE!`ZI;&KEtNzT)J$QL|Po9>*y%el299?LV;Qzp?ad_
zVKZy#F1#A?#r^5H=7^jlLQ#2=eE5QsKFNvt2j9a2d@o3v`c$m%
zgM6Ud#06x?3E>u5CIDd#5L;R4iX1-F@i*PeGTptJ>>mFp?i{}~)&06Bhd(e)zwZso
zjmdZcv08B3VEm{VjXmC^a$?A8)u$E2wJcxb*K|Gj$cc>vY3t&cM?3IcoJ
zmKsJ3>bw@w1AHde_aS&33MPh#8HaUdb5))tx_vuRZmLoGu=^P+moC5d6G%$z_Vk*#9?cWgA3YQgl2+S+7Rw;*$@{vED&zjT!g6^lMM
zL6&K-$9FHl1HwR;qh5(OTkoPcSth&Q&@gIrRn`?}_USuK;0x%NgT0Zc*Jr!pyVK=S
zY5GEEnbNrxv=*c;_Pa$_J2;aVpVxYgO191h@JBvgepHz`IFsx~0#eTd*XabLJF^*)0+$Bwis-c2d
zSc@K#bm(VgfL?Ixj;!?HkjJIYCAsiFtw+Z20^7|`AzG||MmP#5f*}p5G()gb-Nj|G
z{OW45(Kzn7?T0g7s8miDb44nXhpt}hEFWZyClrFs6N1e|(_^D>u-+y|EPBCG_BwEq
zn}HAr(lRo|DLG2jYHVXgznu(bqr{yIOX?X7Han%l1<|K#=v4(dBR~nzugF$-S&oAh
zVs)+DkK5&!So!~`0|`BZ0N-%8{)b2PSCGKZ|A4(xvqmBKJ7$a7G%x5rs;zSKhUv|mBsGmcJ%Ou}Ks5!Wbz#zTO
zuM+0NvtIWtLSe1-a;=$|Fiza|Npi0hYD#^|3n=)ael`HXth6GNQ8^Vy6Ib3ov;)GO
zKO%mr@u;zq-lC~shUjafy@c3)CO)2IPU&{a$<5W^m>RRq>a6u3@Xeu5iT<#?W}&H)
zn5(_Q0kigM0j_ub`ah9|vYc2lZ7_9Z)#1`mIRz%wmK85?@u}ya8D1V0?t(9(NW_-K
zX*i(Tr^;<|*WP^nBOVfbNQa2RuReA=xIJKj?0Xf$7o{p=<#zv7sab-HM%T-Tqg4=p
zp=M*T6Im>s!H;HN_{d5JV`m_8P_J_g94nmvT#AQTR3Wu=6@nvIWoZ>}R;1^0yw*o5
z+x`We*jTqX`IIA$)8>PEgKe9>I#(kbgO+QyiCfY(TqLi0B$wM&tJFtg(P*0O?T?F|
zJU!Oq*^WsxTD;`)HShI$zYdP^=t5~igv8;9`
zg+vgGNg(0PWJQul;=~=RRoe_!P~lL;nGXJ>f-ZPf2Ka0V>{j1oGC!q$N&~_!_|!S}
zzB~`|=CR8lwu!ZAy*VU
zqs2zoHge#@O!YWo)=@P1i4P@t$U-pTXrHCCnsoh
zc~jP4BkSmO{+bxpE9{Xh51v~pwc|$T+c@{#v6f7a>~eX}k&5~b{XSJJjVfAOVTjSZ
zO|fE~4ko+fn@bx4)PZ#A^o}=sV{r@kczeDE14+`Ey_0r@ZE>IT3v3lBMZ4k)Q`jac
z`v(jc;zr|KN{>tB%aq_sk5o_;sqSd3_m9$&-CXiOpA8RebfzlIYR70+%QlBIzZP0B
zvQj6q5M7Mt?FwC=?M227u^&Oki=dIfR^CS^sW}dctrs+IsBGD!cZA_(%H`DePOVd^
zu-R_tMrVe8!9)n%3iK7~{>-1P7`<*&UWqD!!=;4^4fS$SHdkx5rd%%jvwQAk=O2W7
zhy`#`edzx6S^k@2K?X__fK;M=3Hb2fF}DSuv>7=d&f+yS+V84-5Zjt4*4{)6%-^0Y
zQ2|Y$qR-d62tl{n!-n}#xR?+~Ce4)Tm1Zz|K>7v^<;Pd%$rE90R|Yw6`M!|xt+ber
zP$aj>H71i}+o~Q}qboqa0q>3_uJx(Dv&(lX(f{F
zuPlef_Z~b9PDgTj5p9=6T722c!|fQGq3>6^6E&6Uxqjz6uO2xC;d3?#jTfqC0%-u{5eK;g1JElhI{k7($=F{A6rp&m*{tR{Gf@Wfv%ZEwE8#Nj4N-9Zi1%-2`z>Ze{^`nnDa@$l-kY($ZFFK$UDj75|KfY$
z!GQ^t;!7;_{3WZ!UVJvAESgM%@>()7nlO+H_TL}=O_pF(ue~(b!6L6IqKPypQ!q=`JJV|?JhnNV9p`^8tdcj~FL#9TI`*b*MT?IXk&}g?WV6)ac
zN}=67j7pUus(JN5pn-98TwKbv14fS5NzapluVbfU_6{u?Lq0Xyj%p&)Xs;Mzlih7W
zgBP9B8V|S^gJ^`6f+UeKmYtiX+zeLUrmV*{OE-b9z9=_87tyRI7|v6s&o+({tNmuD=G>dVL{*W_F5=31ov9O1^flf_$bW{;72Ia@iE%2Ke})Vt!giTo_^_p1Vmx~{06
z@0Y<}o+oc4SR0E@TDJJr);P8!?Qpvo=BC%g-oa6Q?a57>m}nv)
zw4UUuz@<#)2mC|od%@MsQxiSUZODI0sSYTBhnpPh_(Kd#wAZRyVM=|riMLVUR5@9I
z(v&=_fX`Z&?0&Hb6Tb@$t9ZBUD+aE&R0vQN@$J-muiF(T>mYfaBTFLPhut6;N2k^v
zfMadGb62m5&f#p^XRl6tfrG+cuI6HbDEhv_bT)dd0In=rTt%Tp0YSCv4b5j7@i_KL
zQFCEBRai|HaP)+z3TUSB-otvmc$Y~{@?hL#ULlEM4_Xo7uA)6JW*`_pj>*JmSfGJo
zUQDn8R*EiDa%GRlyMQB={^V8&sPVkfrAynDUL)C2Yv17C0bAv`MjvLz7hUQ~X-L1$ovS>j
z{z^n5UNG*F=K4I$Q^ob`i+_@Jg0K%6IyOJR%}nq3lBLz+x7{Dcm?~Bofj}P;ASxcm
zkcQIYkG(b8Ik$Vf-bXuvfoVKam192H;N}d6xqerpcS3i6wGGnd+3TOJwOwo$V6(gW
z(&tv2an{UxkWBBu2^0#Da>V+Ue|bJ9&G3tPp5H8+De+J#Fwu)0Qq!uQZs0ResW7b`
z0KSj7vakK_9G~6x7_*qHP&B0mw_f+f_Xv=B%_m|}zl7YL$sl}I
zYmXsEm-rwm<(dRG`<*=1)gmQ`XeM#&S-Q?Ys<40C#}!vBk)1}jb;PzWXz_?=*bA=d
z_GLxVGIjFob8NQ(=;Ss0S
z`)j%#^(5{GtG$2%uNQ&XtiB0SY8o5Azq)V8(z*3FWO5Xutjb~2{hCmDRjKifsVU4F
zmqas^JJr)|W1rdL)AJ3v+)&lLeIl=gMk#g#A}%h33VnLnniGaX5riNN;-LJr&i}T2
z{C@XWK`InrhG0xkhD2hm@h2fendshFqXE2a7h?Zt+kse=Ch$l$%1E}>bH3-7Q*gcX6aMoN#i=5FrNe*SdjPKBR*C@Uq@JprHp@I-M%rHoW)
zPpr)x-sgEdH>+8NYr&ZyRhz|v(X)fabisRjUnx$3(O}
zqzg5sf{`z5)|&Q_@@h8msWEIBUnA7A*lvvYMpG;6vyET*b2O;cSqlEo)XhUvls!>t
zZF3C9wbQSrCCSmi<&6T%eM(>XS!byld^8d1%j`4QUxZtGNp73h*@G)|nk`-aDPgu!
zHy^_3%-KcXGT&j=0)3DDss0Q5xQz!=I9`p%r3b>MAC=9eHuh0=y4o6z8ISs+y|o2{
zC76>rQa!|RHu5Y_LB2d8aWbQMlNqF;|F!@2K>LLS45i}hS*kOc0-`gyF$B|8=VL#+
z9>w~af=+tEi(FrpdUxd%omA>PUf>Z3qqDqCh1y!jMbr?ykD*NFGrHwp(y;(4I3Pz?
zi21geDM6RJSO{JHlh-O#wOb8Zl}qE7o~4t?4ELoM1lnEfKviM~20V^U%>oQIYq&KO
z>~d9fRVoL}gmabVvq3Lj?T~1;=PBD{3k}R!t8Krhv1EKrEhk0M^KC6);l2Z3lGLOk
zL1Eff$WO*nu|hNBXQ5KItz4|GeG*7hV+u%glI3eH>zC;rW0bm*4W;sZthrxsfLF_{
zPZS#cDQ`H|Ym~X%
z#o6uJhS#C$dGKl&uW^N85tzy=U$;a~
zfL>KhPeqlT{^lVQO^>TgE5V}cI*cDk4&N_=U`-nP_$uFgSR+)7#Ny6Hs7E3xr4(sz
zFp^7ika_7NPehd!8Q9q3XE+h28>aHK_(`0N!N$gJe5Ss2rm)dy$lWh0oDGY^cu4=`
zW6ZQXk%+kd%jEFdiow!>y~cQSa^67q01?$zCY@Sp&9wPsjtp|A<4ACEgte0iNw>Z6
zTEEz(jANHTloM4DdX`)>!mr|Mhs}jP99tDf=nHCNInj7h+R@&qc)AatD94A{F3($F
zRIIO{-eTI_JD!rXAxBrT%4TJcM0>E19-Tqzk#-MLgU|^i7bsUUISmKQo|#ps
z38%O$O{TRoAxFq3`12caZkzjZkHp)o;q(1L=;8|vRGMnHxny;C?_7nf(#CrU3dzKj
zEDMd{O$5vzl-*H`6t@>ng^mqjWow6f$snlXbldeVS!as94k$0pB)J^u;}M0*=PdUd
z1XQT1+LprD9}(@)ryJhZx(HcT^LLo5WqmGAY>kNCB~>`t_@S#L%I?2Pr=KYnhCk@3
z%Dj*X3K=<@db
z8>NQY&j=2Z*GET8xo7KK7DgKteVGiaAIW?jLAs)NONWJqQ?_!f!5PqOVOGl-2xa?M
z^3FF$#BT8LbfaBKl+dpwR>k3T+8MTkiBza>3)!7M!C1`xSYF!iX}tfi&mWl0y~VIX
z(QZO9am`LXtrJG!Vxf_B+^n=6RHca*Xc9ouo}k7KVzgP!Fbz6SEJ>Pkx)@ELxT`V~O<5gf_T-r8XI4>1fhGiP9TIvk_nhN_WQFW>dk_+0v5~s>!3M#dXexMM*)4*slyeg*n<9#J=3-3YUo+?nh
zd3npzN`;wb%P%x}EX8Zz9Bo`xv}hSy-~4PRs8WsUY+#jfIqbq;e2N2lE~0Tp5Zb-0VCs9|
zF!}L^va_s9f5hK82vZs-D)Kq{cAn1=7R(GJV>&1t-bqZXo>i?;WmitvTuUC}!22_e
zy5@u^eNI8_y%~2ZU3HROKV}a#`aRK`rdV&_*5!I>977hf{Bkl=KnhO^E;KSKDJ^<*b>-+TB09C
z`@SlwM_j&6##y?a*VicE=RL=BKPh$sKMJg?C@P_1oz|2b&*&G7GfJrm)rM)BZo$4t
zDmsxv-*iNXFk;J2$;8z4eH^1ByM;Semy{*Xm%~O(@6_0+DwgD68Z`YGjR{%wDI<@F`hzG&deWxd7v)RJTt=
z5?#~&w0${5ksl$N38*`
z-c`t0vDySTI0u}FPs-g!cmpPk1MFSh1tDMi
zZ~X4Ec6QSVWaF_i+TEG*>CA&V*}RtnNmTI)^wx1iUX9_qFe`{^w%Xzc>tXd}Oa71=
z?D|wE+vEO@Cf}*m-A5^xfKor;W*c@7+l+JR_X^iI>~n@-YCz}teu||ZYTzKy?9Y$l
zVf!Py%m*|RG3Ad1ugB*VcLcP3Kik{K(`a+w6vYhk%_Q>er1TwYhOaRjME!wrM1e`c
zU#^!mM!QG)vU&vbR+ghJ*8SwW@B_7zp*l+L-`Z7b3
zkqX$8iMx%U-h|MYsua`Nk#DA(_ZzFRVyvAX-U{WOqYOwQE)KSgH3!dfTo0W~^YOdv
zeWyC@33+3Bh->_c+%2xGOwN?3d5-i8?44atbViaMMYnjp^EuLJ0z<#4XIMfG+ont{
zHDfEw)UC
zA6?hxu>tsAAWHC6)cQ}kJ4l9t=;THF#J5}s6O1G{@m%==EZwZOz6%!H$1NM{ZyP%d
z0vv?*R>=C4*pBh6qRS__k^e3@S|U6&g<=JCz~9ZfoMcXxu1_S$xj;$T>10VJqU@FM
z-J|{Nk6HRB&HW>LbHli4KFbuE&EYIh8NVAALH7C8x$Fm4yCfQE-Xk(~QS+7!CU_a&
zmF8D6{Ryn3W>XB`2>6`46DdfnRBm5{7+#;fm7(p^0R-e0<|PnCWEr1$r3%r+j_fgrl_Jr;@P)eTw#6D9YHb~qJu|z!5cA}
z;PlI5K7QjgE##K=u>gmOAz1cd{&@dWoYwy^q`FuRF8
zEwgfoA%@vp8e_g{r3QT%T2B;6=pJnhD_0?Zj56Jo$@z3oj9$NYh;n^fb@qg45~v+A
z9M0kn(Z@ul8Jdo`-iKL{f!mmdu*wSea6h{F19;FAl>Vj`w%Xze=O`-yI
z^i0$+D42lk?JJ)P3gzxn |