From 39a29cc7698578c4a9c3923141a54f63a97de4e2 Mon Sep 17 00:00:00 2001
From: Dario Gieselaar
Date: Mon, 29 Nov 2021 10:14:33 +0100
Subject: [PATCH 001/224] [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 931215c75fde..381222ee10ef 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 5a48093a26db..334c0f296851 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 000000000000..a7a826d144d0
--- /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 f762bf730a71..ba2af8ce9ee5 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 0fd8b44b6985..ebba6a0e89a6 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 546214f83c36..4a25d7009ad0 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 0031456248c1..9a919e505185 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 67a4d5773b93..882029a50e47 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 000000000000..f020d9a1282e
--- /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 08444fde48ba..4051d7e8241d 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 c1ebbea31312..88177e816a85 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 859afa18aab0..16917821c7ee 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 3c8d90f56b78..91cbacadf59c 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 3a8d32e1843f..47924e49e9b8 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 81b72f6fa01e..505f7452fe5d 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 016f1c5362fb..46456098df4a 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 fbe11d295e09..f040ca46a9db 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 8eae0941c6bd..4f29a31d5d27 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 decf2f71a9be..7adcdaa6ff94 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 4d46461c6dcc..1595e5895722 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 c6e0c7193f8b..f1b11a3905df 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 3a92dc539855..e9ffe3ae9699 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 000000000000..7a665522abba
--- /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 000000000000..0995013cbcbb
--- /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 000000000000..ee926269ea36
--- /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 000000000000..fec244bc19dc
--- /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 000000000000..495e5f013600
--- /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 000000000000..3e80d1e9f733
--- /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 4a2ab281a284..91b8e0084b27 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 000000000000..4f38a7025f3b
--- /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 4afdda74105c..000000000000
--- 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 000000000000..58bafffaff69
--- /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 8c1f24bd5e64..559c636cfaee 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 000000000000..2ba3c4a29c52
--- /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 000000000000..53dcd820f551
--- /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 aa427d8e211a..4078c848aa48 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 000000000000..c134c08cd835
--- /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 000000000000..0dee6dbc951e
--- /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 f8c59cff4feb..43f9e4f5e998 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 baa1d8758c3c..5c081707bb75 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 dc568170a974..dd848d9f66c6 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 cec0970420d1..3610ffae3c7e 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 738294852598..d68a1b88132b 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 2fe5f9b6a6d6..c25fc7ca9f1c 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 02d17f6b561a..b8d030255892 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 fc20202e210f..b38d34266f3a 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 58b28f71b9af..d074bcbf6c1f 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 0bf59f044bf0..fe4734c65739 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 469f56b99c5f..817f0aad9f5e 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 63fdb691e8e5..b9b12aeab075 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 59ca8f0edbe8..7bae1e51f1ab 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 bd01c83b9cc6..a6d2454de99f 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 7f1c14ac2551..7215d2f435e1 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 9ebaa1747d90..d4a2cdf10302 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 350d90ccb3fe..90cf96469127 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 14e746a55a3d..0ff00d415e7a 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 e36e99b447aa..21af5d91d14e 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 7aca21f4fc7f..f1aefa06304a 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 ce27183e84ca..421b536c6d5a 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 f7874b1c6149..b9ac77ca3442 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 e87f03efeeef..1c0185c39655 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 6b6d61fdb1d3..4c1e1850c177 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 5800ddf00480..a60da5f2bd5c 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 f02f1e7493ff..ef77cd4003a1 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 077119156c64..87c1f5a04ed2 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 375206d0a0bc..d4dacadfee03 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 1b2c919f538a..bc2118f55f65 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 7318fc449fcd..3492d2967a35 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 72a0cdbbee48..be60c655ce50 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 002/224] 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 260cbf42c4d8..e97a2b2901f3 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 0ec611a30751..53ede4e3f710 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 b1bbfcd5aa87..4a06162714a2 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 e9aa51a7384b..a58770ed1c1d 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 b983eaaeaae4..9fc49535e18e 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 8b0686d0a309..102051ac2a9d 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 003/224] [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 bccb0f449100..1e247fd06739 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 000000000000..38c753bbebf3
--- /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 69a6672db6e9..4b64ae07ddf0 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 a3c060f5dc5d..2636463bcfd7 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 bd5f2ada4990..4d2f4b971f08 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 5a03f72e540b..c351b45b2ea9 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 4976c1c225ab..9f6c78130674 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 004/224] [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 e9750bd19881..ba40bcf294e5 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 005/224] [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 c2c4baf0751c..8669bc180f42 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 5500324e4bdd..c367b60a6501 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 1fc4093a67d8..86ca94d5b649 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 fe7fd0918450..84d256630433 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 006/224] 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 d657db443e4e..bb89fa8f683f 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 007/224] 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 61773aaf825f..7562f69f673c 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 008/224] [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 e6021fa31b9f..4dd9a807eb24 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 009/224] 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 1fa65172cdee..868c91cd9ed1 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 010/224] 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 d3a79dc7d8bf..3a57a77a9772 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 011/224] [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 cb6a5383688d..2be6e9b269e7 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 fa484de2180b..40f6f872535f 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 99665d312d32..fc4c6b299284 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 063515233299..b20a96c79aed 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 51c64f187537..797765eda232 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 587f741461bb..ab442bf839e3 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 b5efa0447e65..de1a475fdbd1 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 f8880ac5618f..fe39f6112a7f 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 7d87c49bda64..4f10f833f643 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 3e6566f0da0a..7aedbe9e1100 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 4a22899c12e8..c74ac506e480 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 6cd102a4d477..744d63c1ba04 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 54fa1f05b9c0..d7081bf020d8 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 52f04bcead66..7518a36433d3 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 9d2afdba36db..09ac0c1dd94b 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 56483d9d1019..02411f5902b3 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 000000000000..a451178cc46b
--- /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 7c671ce7736d..f0333cefd612 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 5561d1676e41..0ef21fca26f2 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 fddcc309e1ef..cb5c7483f261 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 cce2b4eb042e..616fe56102df 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 409d80e2ef06..6f9a30e3a704 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 a256a65a5d7f..b6655e246de3 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 ff0ac0642ec9..9912aef94314 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 000000000000..12ec1bca2207
--- /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 d4a6cb20bc55..b7b146aeba34 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 c3cac2d5d67d..b9d9d4cc3414 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 9807a47698a5..6748e9f3b1d0 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 4be69feb79f5..3497a1e52697 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 ff79ccf0126f..850f70d2d002 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 9c8c3d24ef28..949691911fc2 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 7fa93ff0bcea..d7e69e9d8921 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 a005bb7c3d05..bb34fe84e2c3 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 f6963de0cbd6..d1603cbceb26 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 9295451f640c..b885ff97bf26 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 566ae1971945..1b9f3868f096 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 0947d24f827c..0f2572ff2b2e 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 bc74f5463ba3..43aefb73aebb 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 508d217cdd03..60513c417165 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 424e85327c22..7f6bc9e5d950 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 7d38ebe81e4e..000000000000
--- 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 0849f8850f91..68226affb41e 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 1db313b09102..cdbddb8d89c8 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 63a5e80289e3..b26037aa917b 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 012/224] [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 2e2c80b790cd..e334d214f246 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 fa6af0f5e422..69c7c24b6312 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 e442d3b4fd11..b11993e2baa5 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 013/224] 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 bb89fa8f683f..1d8a172e57b7 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 014/224] [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 000000000000..ed2bd4985831
--- /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 b2efae74c9c7..c642ca7bd577 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 000000000000..49ddd8aec0fe
--- /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 629868fb88bf..f79e95559571 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 e6c189ed0c74..a2f6fd493313 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 a02fc7fe6665..6d690415d8c6 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 d5cd423b2b12..b33f152a6301 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 9fc49535e18e..6d54be0664e0 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 102051ac2a9d..f04696d7dbe3 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 015/224] 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 983dddda5d4f..5e8a77f2c55f 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 bc90fe35199b..def7fefd5517 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 44185306ca38..821b788bc7c8 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 016/224] [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 6b5863c8b122..dddc44c3c26e 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 c9c2ed549a1c..35835cd0bc8e 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 8a99b6a53cf0..b4dda3ed3559 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 bf513d8a1a99..bbf3096e5510 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 0dab3e513571..7646ac9bec9b 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 000000000000..b37ed1d873ba
--- /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 7100a0552876..cc38445e3a0f 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 000000000000..7100a0552876
--- /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 6549e892cab1..6213ea3e66d4 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 000000000000..f4cdec680af9
--- /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 544f3feecb2b..a3ec446e5c30 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 d99cf0865c0d..51204c7512a3 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 017/224] 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 59dd36a4fa5e..8936e41762c6 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 cb8237c5aa38..a9053b90ce72 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 018/224] [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 ccd5e7b5a2cc..8b7086964564 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 bef84c41796d..9c8098390d12 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 eae9dd5e73ca..d51496d6efaf 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 344dd4d203d8..4eb6ae307125 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 000000000000..11d7dcedcaa3
--- /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 000000000000..68eb8aa130d2
--- /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 000000000000..46a91738c380
--- /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 000000000000..537d6c77195c
--- /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 000000000000..a57a03fd3a1f
--- /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 000000000000..bc49587fab87
--- /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 000000000000..f5d54c40a864
--- /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 000000000000..76d27ff8a9d1
--- /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 dc3c00b03f71..f674879552d6 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 e2c2e0b52dfd..bf42a5b0865a 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 019/224] [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 87a7812165a6..7c7f7dd28f6c 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 4c1827dc58c0..525463c9de24 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 cfc3ddabe075..58f5cf8e52c9 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 64576d4978c9..23cae0ee852c 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 8ffeefefd0cc..98ba8b4fbcda 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 020/224] 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 5e8a77f2c55f..b0c7e4659a55 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 07513ac94c85..c9a0f6a759b2 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 e567c18807df..15dbc163cd28 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 b52a6efc3513..13b60ad9fa07 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 821b788bc7c8..71b82ffdf5af 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 021/224] [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 3a3763693db9..824a73f9b261 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 beff36023343..f00905f3f492 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 c964219e1fed..5cb60344037f 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 27e887eda65c..53f9c82b8681 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 ee1e97ceb386..972e5283274d 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 611a426dd4d7..1e19e495585f 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 007c3e306372..1601ea481cf2 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 022/224] [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 859070bd498e..1ea85e5a5434 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 6b10ca5f837d..bbcf651bd6d6 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 bfdec28a5098..bbfa17c5694f 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 023/224] 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 7646ac9bec9b..2383044bc14c 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 64d495dbbc79..36b1fc2f2b6e 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 4fdc8d245799..13fb5d805fb8 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 c5cad5f3b1c8..ced4896c5f31 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 000000000000..4153ab6e5b59
--- /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 926f03acf01d..14d47d1e7e9d 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 38c753bbebf3..d717e916de2c 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 3adfb0a1d9c8..5126647161fa 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 000000000000..57ad311f65d1
--- /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 7b2880308406..680798811e9a 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 000000000000..b6df77f07588
--- /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 79a27faa96c6..25de2e36b08c 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 80ccd4a69b28..d9fa6c6e2221 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 000000000000..797415632708
--- /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 000000000000..84badecd29dc
--- /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 e06b5d333a9a..4dce3ee80b83 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 29c5e88788a8..a9819a6619dc 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 d857b9d6bd65..86116fb96968 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 2636463bcfd7..b19a1dbe86fe 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 000000000000..e3509e04b2f2
--- /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 4b64ae07ddf0..bf99bcedc16b 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 000000000000..7bbcc43230a4
--- /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 000000000000..074f48f42664
--- /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 3e0a801fedbe..d00109cc5d63 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 dfa4afcd939c..5e81286affba 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 000000000000..525f3441c447
--- /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 91f45c711d6a..f4bc5af7f604 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 169f4b5254c0..6f38a66cdb64 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 024/224] [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 eb4e226940c5..87a5710ab037 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 025/224] [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 0fc25b28b60e..58179366fa42 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 17c43e36e5cc..00440b2b5185 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 aea92d06b758..bca71ed71b1f 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 c79dde721d13..fd638a6731c6 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 604348355f38..528963709712 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 51b14809982d..06a24cbd34a4 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 026/224] [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 36976bea4a97..ac88204f082b 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 535d93cc3ece..5ac348ad7c8a 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 8b906b68556a..76fa7778eafa 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 027/224] [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 923482954aa2..a214598af31a 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 028/224] 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 5c2c1d531754..7669b9b64491 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 cbfe53d3eaea..6aa528d4f04d 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 92b4c815f224..5bc7691d6a40 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 772faa5321d9..cec80af843c4 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 19f45ced5dc5..cb1c34a19c01 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 76bd0cba1731..c78bf3e91873 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 d447db60fb25..bef8ed4462fd 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 ea894e2b00ac..26794d042135 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 aaf3cc451606..4fc7a0569ba0 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 5f7200cb826d..128dcdcb778c 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 6c3cb51111ae..c84deb3cb0c9 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 6a5f3df0e86f..315b4d864b3f 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 040f313b1220..3ea2c022ec48 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 60ae386bea58..69c2cc4b987b 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 872a7282136e..10d81f162395 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 4b4e11c31d4b..b95ae0bca5bf 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 d78ca852ee7d..ffefea96d3a2 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 793c6250d859..e86b06b423a9 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 5366c00c0e7f..a8179f297644 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 907dcf8c9c20..b8bb26fa9ad6 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 39fe02a84854..85e834b32075 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 6750ebf1140e..54bc7fb26e9d 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 6f8332e1e332..ada2df654d52 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 8b4f5a69b814..350412825b99 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 ad96f21022f2..3cf461e3f7d4 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 8fbbf406cf5d..bf2a122ead42 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 af7b6f3201b3..e41809054e12 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 a60f68c19f6d..454437a203bc 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 df29010bd682..f17f7a582efd 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 3be30b77bc2e..0554b31c8835 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 8e7a59c290ce..e4b2027aa3d6 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 d8963b33b8ab..463c61fb60c9 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 537fd9ec6a0d..8798c1a4bc52 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 dae8390a35fd..7f91447b910b 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 3e692aa48623..e2021ac582d0 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 ad9285c7b8fe..3c2d5fc4df66 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 39f0cb376b32..3466542c0973 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 b7665a58de30..9a663e137221 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 2b210bd07ab4..43ea60fa8461 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 d460132dddbb..f1d9beaca513 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 a43f170e5822..cdfdbadf6759 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 f856a5c035f8..ac8383ccea9e 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 97a9b407b3cd..1f2e7c883e1c 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 e82dbcaa4113..c7c85fdd4935 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 cbd7a1c6107b..b14af1c69795 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 6034846fac4f..93bead4d31f4 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 1877a4cbd0e4..07c71def01be 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 af3b33e3d7a3..d0fe98a7c139 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 6e213edf457b..667980d5f049 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 25aff5077c68..077ef44c66b2 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 42bf690c388c..56e0a325aafd 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 4845d682b877..8d41e221a2cc 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 1be152ad5ca0..b28343f37ea2 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 4d329ff357b8..a992cf49f75f 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 905ba20e4f66..e52a174850c4 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 029/224] [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 7eb95405db6b..954581faa246 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 eac26beee1f9..457251e62ae8 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 61113b5491c2..54137d1f9f2c 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 116bcd6f91f7..b379c0ac279e 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 03e40c7cc6ce..2667729f4b85 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 |